Specter攻击如何读取欺骗CPU加载的缓存?

NoS*_*tAl 10 security cpu cpu-architecture spectre side-channel-attacks

据我所知,部分纸,他们欺骗了CPU到内存受害者的部分推测加载到CPU高速缓存.第一部分我不明白他们是如何从缓存中检索它的.

Rin*_*g Ø 9

它们不直接检索它(超出范围读取字节不会被CPU"退役",并且攻击者无法在攻击中看到它).

攻击的向量是一次进行一次"检索".在准备好CPU缓存之后(将缓存刷新到必须的位置),并且已经"教导" 当条件依赖于非缓存数据时if分支通过,CPU推测性地执行来自如果是范围,包括越界访问(给出一个字节B),然后立即访问一个依赖于秘密B的一位的索引的一些授权的非缓存数组(B将永远不会被攻击者直接看到).最后,攻击者从例如用B位计算的索引中检索相同的授权数据数组,比如说零:如果该ok字节的检索速度很快,则数据仍然在缓存中,这意味着B位为零.如果检索(相对)慢,则CPU必须在其缓存中加载ok数据,这意味着它没有更早,这意味着B bit是1.

例如,Cond所有ValidArray没有被缓存,LargeEnough足够大,以保证CPU不会同时加载ValidArray[ valid-index + 0 ]和ValidArray[ valid-index + LargeEnough ]一次性在其高速缓存

if ( Cond ) {
   // the next 2 lines are only speculatively executed
   V = SomeArray[ out-of-bounds-attacked-index ]
   Dummy = ValidArray [ valid-index + ( V & bit ) * LargeEnough ]
}

// the next code is always retired (executed, not only speculatively)

t1 = get_cpu_precise_time()
Dummy2 = ValidArray [ valid-index ]
diff = get_cpu_precise_time() - t1

if (diff > SOME_CALCULATED_VALUE) {
   // bit was its value (1, or 2, or 4, or ... 128) 
}
else {
   // bit was 0
}
Run Code Online (Sandbox Code Playgroud)

在哪里bit先后尝试0x01,然后0x02......到0x80.通过测量每个位的"下一个"代码的"时间"(CPU周期数),显示V的值:

  • 如果ValidArray[ valid-index + 0 ]在缓存中,V & bit是0
  • 否则V & bit是bit

这需要时间,每个位需要准备CPU L1高速缓存,尝试几次相同的位以最小化定时错误等...

然后必须确定正确的攻击"偏移"以读取有趣的区域.

聪明的攻击,但不是那么容易实现.

  • @AnubhavGupta使用`array [4096 + b*4096]`,如果bit`b`为'0`则读取`array [4096]`,如果`b`为`1`则读取`array [8192]` ,在推测执行期间(读取之后,该部分数组被加载到CPU缓存中).就在`if`分支之后,攻击者计算出`array [4096]`的读数有多快.如果数据在CPU缓存中,则读取速度很快; 如果快速读取意味着推测代码加载了`array [4096]`,意思是'b`为零.但是,如果CPU必须将该数据加载到其缓存中,则该位不为零. (2认同)