
微架构通道是现代网络安全中的一个关键但常常被误解的方面。与传统网络侧信道不同,微架构通道利用现代CPU低级硬件行为来泄露敏感信息。这篇博客深入探讨了这些通道是什么,它们如何工作,为什么它们很危险,以及可以采取哪些实际步骤来检测和防止它们,并配有现实世界的例子和代码示例。
目录
现代CPU是工程学的奇迹,优化了速度、效率和并行性。然而,在软件抽象的背后,是一个复杂的系统,其中进程共享物理资源如缓存、内存控制器和执行单元。微架构通道是一种通信路径,利用这些共享资源,如果不加以缓解,可能被用来跨越进程边界泄露秘密——违反基本的安全假设。
侧信道 是一种信息泄露路径,它不直接利用软件漏洞,而是通过观察系统行为的差异(如功耗、时间、缓存命中/未命中)来推断秘密。例如,攻击者可以通过观察某些操作所花费的时间来推断加密密钥。
隐蔽信道 是一种用于传输信息的通信路径,违反了系统的安全策略。与侧信道不同,隐蔽信道通常用于两个串通方之间秘密交换信息。
关键区别:
微架构通道在硬件深层次工作,利用进程之间资源的共享,而网络通道则使用数据传输介质。
让我们来看攻击者如何使用共享的CPU资源构建微架构隐蔽(和侧)信道。
// Prime+Probe的简化步骤
1. Prime: 访问缓存行以填充特定缓存集合
2. 让受害者执行
3. Probe: 访问相同的缓存行并对访问进行计时
4. 缓存未命中意味着被驱逐,可能是由于受害者的访问
这些利用投机执行,CPU为提高性能而猜测未来指令。不正确的猜测会被回滚,但微架构中的副作用(如缓存状态)仍然存在,泄露秘密。
利用分支预测表中的历史记录,攻击者可以推断出受害者代码中的控制流程决策。
如果两个进程共享物理执行单元,争用会导致可测量的时间变化。
假设进程A(攻击者)和进程B(受害者)在同一机器上运行,共享缓存资源。
微架构隐蔽通道不仅是理论上的——它们已经促成了一些对现代计算基础设施最具重大影响的实际攻击。
在云环境中,与目标共驻在同一硬件上的攻击者可以使用缓存攻击泄露来自邻近虚拟机的信息。
JavaScript代码可以测量时间间隔并使用共享缓存状态,从用户的浏览器上下文中掠夺敏感数据的比特。
检测这些通道挑战性很大,但有几种实际的方法。
现代CPU提供了用于事件的计数器,如缓存未命中、分支预测错误、执行停顿。突发或异常模式可以表明攻击。
相关事件示例:
cache-referencescache-missesbranch-instructionsbranch-misses先进的操作系统(和超管)可以监控、记录和分析进程时间异常以识别可疑行为。
最近的研究利用机器学习区分硬件资源的良性和恶意使用,建模正常模式并标记异常。
防止微架构隐蔽信道通常涉及硬件和软件两方面的方法。
降低可用计时器粒度或添加抖动/噪声可以减少攻击效果,特别是针对基于JavaScript的攻击。
编写的代码执行时间不依赖于秘密数据,防止许多计时信道。
一些CPU现已包含“抗侧信道”设计,具有分区缓存或投机执行缓解措施。
让我们演示从业人员如何使用开源工具和代码扫描微架构异常。
perf 工具收集性能数据perf list | grep cache
<pid> 替换为实际PID)sudo perf stat -e cache-references,cache-misses -p <pid>
104,212 cache-references
12,342 cache-misses
sudo perf record -e cache-misses -p <pid> -- sleep 10
sudo perf report
sudo perf stat -a --per-socket -e cache-misses sleep 5 | grep "cache-misses"
或者每个进程:
ps -eo pid,comm | while read pid comm; do
sudo perf stat -p $pid -e cache-misses -I 1000 -- sleep 1 2>&1 | grep cache-misses
done
假设你想自动扫描多个进程或解析 perf 结果用于异常检测。
perf stat 输出中可疑的缓存未命中import subprocess
import re
def get_cache_misses(pid):
cmd = ["perf", "stat", "-p", str(pid), "-e", "cache-misses", "--", "sleep", "2"]
result = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
match = re.search(r"([\d,]+)\s+cache-misses", result.stderr)
if match:
count = int(match.group(1).replace(",", ""))
return count
else:
return None
# 扫描所有进程
import psutil
for proc in psutil.process_iter(attrs=['pid', 'name']):
pid = proc.info['pid']
name = proc.info['name']
try:
misses = get_cache_misses(pid)
if misses and misses > 100000:
print(f"Suspicious: PID {pid} ({name}) has {misses} cache misses")
except Exception:
continue
#!/bin/bash
THRESHOLD=100000
for pid in $(ps -e -o pid=); do
MISS=$(sudo perf stat -p $pid -e cache-misses -- sleep 1 2>&1 | grep cache-misses | awk '{print $1}' | tr -d ',')
if [ ! -z "$MISS" ] && [ "$MISS" -gt "$THRESHOLD" ]; then
echo "Warning: PID $pid high cache misses ($MISS)"
fi
done
出于伦理和法律原因,仅在安全、隔离和获得许可的测试环境中进行实验。
// 警告:仅供演示之用,请勿用于生产系统。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <x86intrin.h>
#include <unistd.h>
#define CACHE_LINE_SIZE 64
#define PROBE_COUNT 100000
volatile char *array;
void prime_cache() {
for (int i = 0; i < 4096; i += CACHE_LINE_SIZE)
_mm_clflush(&array[i]);
}
int probe_cache() {
int sum = 0;
uint64_t start, end;
for (int i = 0; i < 4096; i += CACHE_LINE_SIZE) {
start = __rdtscp(&i);
volatile char x = array[i];
end = __rdtscp(&i);
sum += (end - start);
}
return sum;
}
int main() {
array = malloc(4096);
for (int i = 0; i < PROBE_COUNT; i++) {
prime_cache();
usleep(1); // 让“受害者”运行
int timing = probe_cache();
printf("%d\n", timing);
}
free((void *)array);
return 0;
}
解释:
此代码测量“受害者”可能运行之前和之后的缓存访问时间,推断是否另一个进程使用了缓存——这是许多微架构攻击背后的基本思想。
微架构通道在多核和云计算时代代表了一种独特且日益重要的信息安全威胁。与传统基于网络的侧信道不同,这些攻击利用了物理硬件资源的复杂共享。该领域正在迅速发展,每个从业者都应该理解基础和高级含义。
要点:
perf)、操作系统强化和编码实践进行检测和防御。对于安全敏感的环境——云、浏览器、加密应用程序——关注微架构安全已不再是可选的。
本文仅用于教育目的。进行安全研究时,始终遵循伦理准则和当地法规。