yeg
2026-09-22 f7f4a8cc3714c7e377c98750b19dc9cee8ea0da5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env python3
# 弱口令自查:拿一批常见弱口令去撞 talent_card 库里所有 password_hash。
#
# 算法与 MerchantPasswordHasher 一致:PBKDF2WithHmacSHA256(possword, salt, iterations, 256bit)
# 存储格式:pbkdf2$<iterations>$<base64 salt>$<base64 derived>
#
# 只打印命中的账号名,不打印哈希值。
# 用法:python3 /root/check-weak-passwords.py
 
import base64
import hashlib
import subprocess
import sys
 
CANDIDATES = [
    "123456", "1234567", "12345678", "123456789", "1234567890", "123456789a", "a123456789",
    "a123456", "123456a", "abc123", "123abc", "abc123456", "Aa123456", "Aa123456.", "Aa123456789",
    "111111", "000000", "666666", "888888", "112233", "123123", "123321", "654321", "5201314",
    "woaini1314", "qwerty", "qwerty123", "1qaz2wsx", "1q2w3e4r", "zxcvbnm", "qwe123",
    "admin", "admin123", "admin888", "admin@123", "Admin@123", "admin123456", "administrator",
    "root", "root123", "toor", "password", "password123", "passw0rd", "P@ssw0rd", "P@ssword123",
    "letmein", "welcome", "iloveyou", "monkey", "dragon",
    "test", "test123", "test@123", "Test@123", "demo123",
    "talentcard", "talent_card", "talent-card", "card123", "rencaika", "rc123456", "pzh123456",
    "huifu123", "merchant123", "shop123", "88888888", "168168", "666888",
]
 
TABLES = ("admin_operator", "merchant_operator")
 
 
def derive(password, encoded):
    parts = encoded.split("$")
    if len(parts) != 4 or parts[0] != "pbkdf2":
        return None
    iterations = int(parts[1])
    salt = base64.b64decode(parts[2])
    expected = base64.b64decode(parts[3])
    got = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, iterations, dklen=len(expected))
    return got == expected
 
 
def rows_for(table):
    sql = "select id, account, password_hash from " + table
    out = subprocess.run(["mysql", "-N", "-B", "-D", "talent_card", "-e", sql],
                         capture_output=True, text=True)
    if out.returncode != 0:
        print("  (跳过 " + table + ":" + out.stderr.strip().splitlines()[0] + ")")
        return []
    return [line.split("\t") for line in out.stdout.strip().splitlines() if line]
 
 
def main():
    accounts = []
    for table in TABLES:
        for row in rows_for(table):
            accounts.append((table, row[0], row[1], row[2]))
 
    print("待检账号 " + str(len(accounts)) + " 个;候选弱口令 " + str(len(CANDIDATES)) + " 个")
    hits = 0
    for table, rid, account, encoded in accounts:
        matched = [c for c in CANDIDATES if derive(c, encoded) is True]
        if matched:
            hits += 1
            print("[命中] " + table + " id=" + rid + " account=" + account + " -> " + str(matched))
    if hits == 0:
        print("结论:没有任何账号命中这批常见弱口令。")
    else:
        print("结论:有 " + str(hits) + " 个账号仍是弱口令,必须改。")
    return 0 if hits == 0 else 1
 
 
if __name__ == "__main__":
    sys.exit(main())