每次接了一批新服务器,我第一件事就是用弱口令扫描器过一遍。不为别的,就想知道这些设备的密码强度心里有没有数。等哪天被黑产扫到弱口令再发现,那可就晚了。
用Python写一个简单的SSH弱口令检测工具,依赖paramiko库:
pip install paramiko
思路也不复杂:读取一个密码字典文件,逐个尝试用SSH登录目标主机,一旦连接成功就说明这个密码是有效的。登录成功后会执行一条whoami命令来确认会话可用:
importparamiko
fromconcurrent.futuresimportThreadPoolExecutor, as_completed
# 简单弱口令字典(实际使用时请准备更全的字典)
DEFAULT_WEAK_PASSWORDS= [
"123456", "password", "admin", "admin123", "root",
"12345678", "123456789", "123123", "111111",
"P@ssw0rd", "P@ssword", "Passw0rd", "Password123",
"admin@123", "root@123", "qwer1234", "abc123",
]
deftry_ssh_login(host, port, username, password, timeout=5):
"""尝试SSH登录,返回(是否成功, 使用的密码)"""
try:
client=paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname=host,
port=port,
username=username,
password=password,
timeout=timeout,
banner_timeout=timeout,
auth_timeout=timeout,
)
# 登录成功后执行一条命令验证会话可用
stdin, stdout, stderr=client.exec_command("whoami", timeout=3)
result=stdout.read().decode().strip()
client.close()
returnTrue, password, result
exceptparamiko.AuthenticationException:
returnFalse, password, ""
exceptExceptionase:
returnFalse, password, str(e)
defscan_ssh_weak_password(host, port=22, username="root",
passwords=None, max_workers=10):
"""扫描SSH弱口令"""
ifpasswordsisNone:
passwords=DEFAULT_WEAK_PASSWORDS
found= []
withThreadPoolExecutor(max_workers=max_workers) aspool:
futures= {
pool.submit(try_ssh_login, host, port, username, pwd): pwd
forpwdinpasswords
}
forfutureinas_completed(futures):
success, pwd, info=future.result()
ifsuccess:
found.append((pwd, info))
print(f" [发现] {host}:{port} 用户'{username}'密码='{pwd}'")
returnfound
# 批量扫描多个目标
defbatch_scan(hosts, port=22, username="root", passwords=None):
"""批量扫描多台设备的SSH弱口令"""
results= {}
forhostinhosts:
print(f"\n扫描 {host} ...")
found=scan_ssh_weak_password(host, port, username, passwords)
iffound:
results[host] =found
returnresults
if__name__=="__main__":
# 重要提示:仅限内网授权测试环境使用!
# 未经授权扫描他人设备属于违法行为!
target_hosts= ["192.168.1.101", "192.168.1.102"]
results=batch_scan(target_hosts, username="root")
ifresults:
print("\n"+"="*50)
print("扫描结果汇总:")
forhost, credsinresults.items():
print(f" {host}:")
forpwd, infoincreds:
print(f" 密码: {pwd}")
else:
print("\n未发现弱口令(基于当前字典)")
并发线程控制在10个以内比较稳妥。太快的话,有些SSH服务器会检测到暴力破解行为,直接封掉你的IP,脚本反而扫不下去了。
有一个坑必须说清楚:很多生产环境的Linux服务器装了fail2ban或者类似的登录保护软件。短时间内连续登录失败几次,IP就会被封禁30分钟到几天不等。脚本扫着扫着突然大部分都返回超时,不一定是密码字典太大,而是IP被封了。解决思路是先拿少量密码试一下,如果连着两三个都失败就先跳过这台机器,等一会儿再继续。
另外,有些SSH服务器禁用了密码登录(只允许密钥登录),这种情况用密码扫描根本扫不出来。脚本里的AuthenticationException异常就是用来区分认证失败和其他错误的。
再次强调:这类工具只应该用在自己有管理权限的设备上,扫描他人设备是违法的。测试环境里用一用可以理解,但拿到生产网络去扫之前,务必确认有完整的授权文档。