#!/usr/bin/env python3 # 弱口令自查:拿一批常见弱口令去撞 talent_card 库里所有 password_hash。 # # 算法与 MerchantPasswordHasher 一致:PBKDF2WithHmacSHA256(possword, salt, iterations, 256bit) # 存储格式:pbkdf2$$$ # # 只打印命中的账号名,不打印哈希值。 # 用法: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())