testssl.sh是开源Bash工具,可离线全自动检测SSL/TLS配置,覆盖协议支持、加密套件、证书链及50+种漏洞(如Heartbleed、POODLE),输出易读报告并提供修复建议。

不能用 Python 脚本直接“扫描 SSL 漏洞”——ssl 模块本身不提供漏洞检测能力,它只负责建立和管理 TLS 连接;真正做漏洞识别(如 POODLE、BEAST、TLS 1.0 启用、弱密钥交换等)需要调用专业工具或解析协议细节,而 Python 标准库对此无支持。
为什么不能只靠 ssl 模块或 requests 判断 SSL 漏洞
Python 的 ssl 模块默认启用安全协商,连接成功只说明“能通”,不代表配置安全。比如:
-
requests.get("https://example.com")成功,但服务器仍可能启用了 TLS 1.0 或支持EXPORT密码套件 -
ssl.create_default_context()会禁用已知不安全协议,但无法告诉你目标是否在服务端主动降级支持它们 - 像 Heartbleed 这类内存泄漏漏洞,需发送特制 TLS 握手包并解析响应,标准库不暴露底层 record 处理接口
实际可用的 Python 自动化方案:封装 sslscan 和 testssl.sh
生产环境最靠谱的做法是调用成熟 CLI 工具,用 Python 控制流程、解析输出、生成报告。推荐组合:
-
sslscan:轻量、快速,适合批量探测协议版本和密码套件(apt install sslscan) -
testssl.sh:功能全面,覆盖 CVE 级漏洞(Heartbleed、ROBOT、DROWN 等),输出 JSON 友好(git clone https://github.com/drwetter/testssl.sh)
示例:用 Python 调用 testssl.sh 扫描单域名并提取关键结果
立即学习“Python免费学习笔记(深入)”;
<pre class="brush:php;toolbar:false;">import subprocess
import json
<p>def scan_ssl(target):
result = subprocess.run(
["./testssl.sh", "--json", "-oJ", "/dev/stdout", target],
capture_output=True,
text=True,
cwd="/path/to/testssl.sh"
)
if result.returncode not in (0, 2): # testssl.sh 会因发现风险返回 2,不算错误
raise RuntimeError(f"testssl.sh failed: {result.stderr}")
try:
data = json.loads(result.stdout)
return {
"target": target,
"tls_versions": [t["id"] for t in data.get("protocol_version", []) if t.get("finding") == "OK"],
"vulns": [v["id"] for v in data.get("vulnerabilities", []) if v.get("severity") in ("HIGH", "CRITICAL")]
}
except json.JSONDecodeError:
return {"error": "invalid JSON from testssl.sh"}</p><p>print(scan_ssl("example.com:443"))</p>常见坑与绕过限制的要点
直接跑自动化容易卡在以下环节:
testssl.sh 默认对每个 IP 做完整扫描(耗时数分钟),批量任务必须加 <code>--fast或限定--protocols tlsv1_2- 某些 CDN(如 Cloudflare)会拦截非浏览器 User-Agent 的 TLS 探测,可加
--sneaky参数模拟浏览器握手 -
sslscan不支持 SNI 主机名指定,扫泛域名站点(如app.example.com)可能拿到默认证书,需确认是否匹配 SAN - Python 子进程超时必须显式设置
timeout=300,否则卡死阻塞整个脚本
真正难的不是调用命令,而是理解每条漏洞结果对应的实际风险等级——比如 fallback_scsv 弱提示不等于可利用,而 heartbleed 出现在结果里就必须立即下线服务。别依赖自动化判断“是否修复”,它只负责告诉你“这里可能有问题”。


















