4. TLS版本降级攻击:检测降级到SSLv3或TLS1.0的特征
版本降级攻击,说白了就是攻击者篡改握手参数,迫使客户端和服务端用更弱的老旧协议通信。我最早接触这玩意是在一次金融APP安全审计里——明明两边都支持TLS1.2,握手包里的ServerHello却吐出一个SSLv3。当时吓一跳,赶紧翻协议栈实现,后来才发现是被中间人劫持了。今天咱们就专门聊聊如何从流量中嗅出这种降级行为。
降级攻击的本质
核心就一句话:客户端发最高版本,服务端回最低版本。
正常握手时,ClientHello里会填客户端支持的最高版本(比如TLS1.2),ServerHello则回应一个双方都支持的版本(一般是TLS1.2)。攻击者要做的,就是把ClientHello中的版本字段改低,或者把ServerHello的版本改低。你想想看,如果服务器端实现有bug或配置不当,直接接收了一个不合逻辑的低版本,降级就成功了。
关键检测维度
我个人习惯从三个层面入手抓降级痕迹:版本号、扩展字段、密码套件。下面列几个我碰过的真实特征。
| 检测维度 | 降级到SSLv3 | 降级到TLS1.0 | 降级到TLS1.1 |
|---|---|---|---|
| ClientHello最高版本 | TLS1.2 / 1.3 | TLS1.2 / 1.3 | TLS1.2 / 1.3 |
| ServerHello响应版本 | 0x0300 (SSL 3.0) | 0x0301 (TLS 1.0) | 0x0302 (TLS 1.1) |
| 支持的密码套件 | 多为RSA+RC4或3DES | 可能含CBC模式 | 类似TLS1.0但新增AES |
| secure_renegotiation扩展 | ❌ 不可能存在 | ✅ 可选存在 | ✅ 可选存在 |
| extended_master_secret | ❌ 不支持 | ✅ 可选存在 | ✅ 可选存在 |
| signature_algorithms扩展 | ❌ 不支持 | ✅ 存在 | ✅ 存在 |
我在项目里遇到过一次奇葩情况:客户端发送的ClientHello版本是TLS1.2,但密码套件只列了SSLv3的RC4。后来追查发现,因为一个老旧中间件升级策略出错,导致握手协商阶段把密码套件列表单独降了版本。所以你不能只看版本号,套件列表和扩展的匹配才是铁证。
看懂握手包里的版本博弈
下面这张流程图,清晰地对比了正常握手和降级攻击下的版本流转。注意深色节点就是关键差异点。
实战检测步骤
我自己在做流量分析时,一般按下面几步排查。嗯,这里要注意——不要只看一个包,要看整个握手阶段的连续包。
- 定位ClientHello和ServerHello。用Wireshark过滤:
tls.handshake.type == 1 || tls.handshake.type == 2 - 比较版本字段。检查tls.handshake.version(ClientHello里的最高版本) vs tls.handshake.version(ServerHello里的版本)。如果前者是0x0303(TLS1.2),后者是0x0300/0x0301/0x0302,先标记可疑。
- 检查扩展存在性。强制关注三个扩展:
tls.handshake.extension.type == 0xff01(secure_renegotiation) —— 如果ServerHello版本是SSLv3但出现了这个扩展,100%被改过。tls.handshake.extension.type == 0x0017(extended_master_secret) —— TLS1.0及以上才可能带,SSLv3不带。tls.handshake.extension.type == 0x000d(signature_algorithms) —— TLS1.2才开始定义,如果ServerHello是TLS1.0但带了这个扩展,说明服务端是伪造的。
- 辅助验证密码套件。列表里如果出现
0x0004(TLS_RSA_WITH_RC4_128_MD5)这类老古董,而客户端本不该支持它,那极可能是被攻击者替换了。
工具与快速脚本
下面是tcpdump + tshark的自动化检测脚本片段,我常用它跑离线pcap。短小精悍,适合放到流水线上
#!/bin/bash
# 检测降级到TLS1.0或更低的握手
tshark -r traffic.pcap -Y "tls.handshake.type == 2" -T fields \
-e frame.number \
-e tls.handshake.version \
-e tls.handshake.extensions_extension_type \
2>/dev/null | awk '
{
# 假设ClientHello的最高版本已知(可另取)
# 这里简单演示:如果ServerHello版本 < 0x0303 且出现0x000d则报警
if ($2 < "0x0303" && $3 ~ /0x000d/) {
print "⚠️ 可疑降级帧 #" $1 " 版本:" $2 " 含signature_algorithms"
}
}'
总结一下:降级攻击的痕迹就藏在版本矛盾、扩展穿越、套件错配这三个方向里。我个人的原则是:看到ServerHello版本低于ClientHello版本时,先兴奋一下,然后立刻查扩展——扩展是最难伪造的,因为它们必须遵守协议规范。做到这一步,大部分降级攻击都逃不过你的抓包分析。