概念定义
协商本该选双方共同支持的最优项。主动攻击者编辑握手过程抹掉强选项:ClientHello 或 ServerHello 里的版本号被调低、密码列表被滤成弱项——双方于是“合法地”用了弱配置,且毫无察觉。
工作机制
TLS 1.2 及以下,重试回退是主要入口:客户端在伪造的失败后降到 1.1,就可能被钉死在那里;TLS_FALLBACK_SCSV 给重试打标记,诚实的服务器会中止。TLS 1.3 在 ServerHello 随机数里嵌入降级哨兵:支持 1.3 的服务器看到 1.2 协商即发出被篡改信号,1.3 客户端随之中止。
使用场景
自管重试策略的客户端 SDK、生命周期长的嵌入式设备、以及一切 TLS 终结代理。全面禁用废弃版本与出口套件,再用遥测核实实际协商到的版本。
常见误区
证书校验认证的是身份,不是实际协商的协议版本;服务器单侧禁旧版不够,攻击打的是客户端协商——回退标记与客户端策略才闭环。HSTS 与证书固定也不能替代协议策略。中间盒强制 1.2 会让降级面在 1.3 端点间依然存活;配置漂移会悄悄重开遗留套件——外部扫描必须排期。
代码示例
function shiftLetters(text, offset) {
if (typeof text !== "string") throw new TypeError("text must be a string");
if (!Number.isInteger(offset)) throw new TypeError("offset must be an integer");
const normalized = ((offset % 26) + 26) % 26;
return text.replace(/[a-z]/gi, (char) => {
const base = char <= "Z" ? 65 : 97;
return String.fromCharCode(((char.charCodeAt(0) - base + normalized) % 26) + base);
});
}
export function caesarCipher(text, offset) {
return shiftLetters(text, offset);
}
export function rot13(text) {
return shiftLetters(text, 13);
}
package main
import (
"crypto/sha256"
"crypto/subtle"
"fmt"
)
func ConstantTimeEqual(a, b string) bool {
left := sha256.Sum256([]byte(a))
right := sha256.Sum256([]byte(b))
return subtle.ConstantTimeCompare(left[:], right[:]) == 1
}
func main() {
secret := "s3cr3t-token"
fmt.Println(ConstantTimeEqual(secret, "s3cr3t-token"))
fmt.Println(ConstantTimeEqual(secret, "s3cr3t-tokeX"))
fmt.Println(ConstantTimeEqual(secret, "short"))
}