TLS Audit
对一批域名/IP 执行非破坏性 TLS 安全审计:协议版本协商、逐套件定向握手、证书链与有效期、已知漏洞判定(POODLE/BEAST/CRIME/Heartbleed/ROBOT/Sweet32/Logjam/FREAK/RC4/Export/匿名套件/不安全重协商/HSTS),最终产出单页暗色 HTML 报告。零第三方 Python 依赖(标准库 + OpenSSL CLI)。
环境
- Python 3.10+(标准库 ssl/socket)
- OpenSSL CLI(Windows 默认
C:\Program Files\OpenSSL-Win64\bin\openssl.exe,Linux/usr/bin/openssl;可用环境变量TLS_AUDIT_OPENSSL覆盖) - 证书信任验证使用系统信任库
脚本位于本 skill 的 scripts/ 目录。以下命令均在该目录下执行。
工作流
1. 配置目标
两种方式任选:
- 编辑
scripts/targets.py中的targets列表(一行一个域名,PORT默认 443) - 不改文件,直接用环境变量:
- PowerShell:
$env:TARGETS_ENV="a.com,b.com"; $env:TLS_AUDIT_PORT="443" - bash:
TARGETS_ENV="a.com,b.com" TLS_AUDIT_PORT=443 python scan.py
内网 IP/自签名端口直接把 IP 写入列表并改 PORT;证书信任验证失败属预期,不影响其余探测。
2. 按顺序执行四步
# ① 快速探测:连通性 + 协议粗测(结果仅作参考,套件结论不可信)
python scripts/scan.py # -> scripts/results_raw.json
# ② 精确探测(核心、权威):协议逐版本锁定 + 25 套件定向握手 + 临时密钥 + 证书/会话特性 + HTTP 头 + Heartbleed PoC
python scripts/probe2.py # -> scripts/probe2.json(约 5-7 分钟,8 线程并发)
# ③ 证书采集:链下发 + 字段解析(SAN/EKU/CT/OCSP)+ 系统库信任验证 + 剩余天数
python scripts/certs2.py # -> scripts/certs.json
# ④ 生成报告 + 自检
python scripts/report.py output.html # 可传标题环境变量 TLS_AUDIT_TITLE / TLS_AUDIT_SCOPE
python scripts/check.py output.html
report.py 需要 probe2.json 和 certs.json 同时存在。修改目标后重跑 ②③④(①可跳过)。
3. 解读与交付
- 等级映射:有高危=F,有中危=C,有低危=B,全通过=A。
- 报告已含:总体结论 → KPI → 目标概览 → 证书表 → 去重风险清单 → 单目标明细。
- 整改建议需结合实际服务器(Nginx/Tengine/IIS 等)给出具体配置片段,由模型根据
probe2.json中的弱套件列表生成。
关键方法论(必须遵守,否则结果失真)
- 版本锁定:判定套件/协议时必须
minimum_version = maximum_version锁定单一版本。Python ssl 上下文会向 TLS1.3 回退,导致 legacy 套件"假成功"——第一轮scan.py的套件结论因此只能作参考,以probe2.json为准。 - 单套件定向握手:每次握手只放行 1 个套件,服务器接受与否即支持与否的直接证据。
@SECLEVEL=0仅作用于本地:只为让本地客户端能构造 legacy ClientHello;服务器拒收与否是独立判定。- 双路径枚举:本地 OpenSSL 3.0 编译裁剪的算法(RC4/3DES/Export/IDEA/SEED)必须走
openssl s_client -cipher "<套件>" -tls1_2 -brief,Python 侧构造不出来。 - 非破坏性:全部为正常握手 + 单次恶意心跳探针;禁止 DoS/暴破/大规模攻击流量。ROBOT 只做"是否接受静态 RSA 套件"的攻击面判定,不实施 Bleichenbacher 攻击。
- Heartbleed inconclusive 的处理:握手时序可能导致 PoC 无法完整确认,标记"无法完全确认"即可,不要凭空升级为漏洞。
详细方法与实测案例见 references/methodology.md。
排障
- 超时多/慢:公网抖动时增大
probe2.py中try_handshake的timeout=6,或减小ThreadPoolExecutor线程数。 - OpenSSL 版本差异:本地 OpenSSL 只决定"能提供哪些 ClientHello",服务器接受集合才是结论;若本地裁剪了某套件,按双路径原则补测。
s_client卡住:脚本已用input=""喂 stdin 并设 timeout;Windows 下必须shell=True且路径带引号。