Spectre

Steps
  1. Trick the processor to speculatively load privileged data
  2. Read something interesting

Spectre is a full family of attacks

Spectre-V1 Bounds Check Bypass, Pattern History#

  1. Train the code to think an if statement will be taken

  2. Execute the following code

    if (x < array1_size)
    y = array2[array1[x] * 4096];
    1. What does the code do?
      1. Indexing into array 2 by using a value in array 1 * 4096. Assuming this is all in bounds, and assuming that you have access to array 1 and array 2, everything should work. It is a little unsafe though. Depending on the value of x, you could request something that is out of bounds in array 1 or array 2. When you access that, the hardware will speculatively do the load, put it in the cache, and if it is out of bounds, before you get the results into y, the hardware will detect this, and reverse this, but the cache won't be reverted.
      2. If you can guess where some extra hidden information might be (buffer overflow for instance), you can index into that. Get it loaded into the cache, and then do a timing attack to see if something got loaded into the cache or not.
  3. This speculatively executes

  4. Eventually this is discovered and corrected

    1. Cache isn't reverted...
    2. Consider a 1 bit example

Some necessary Assumptions#

  • The value of x is maliciously chosen (out-of-bounds), such that array1[x] resolves to a secret byte k somewhere in the victim's memory
  • array1_size and array2 are uncached, but k is cached.
  • Previous operations received values of x that were valid, leading the branch predictor to assume the if will likely be true.
  • Flush and reload to determine which element of array2 was read

JavaScript implementation#

if (index < simpleByteArray.length) {
index = simpleByteArray[index | 0];
index = (((index * 4096)|0) & (32*1024*1024-1))|0;
localJunk ^= probeTable[index|0]|0;
}

NetSpectre (Spectre V1 variant)#

  • Memory Access latency reflects network latency
  • Allows distinguishing cache hit/misses remotely (Trash+reload)
  • 60 bits per hour
  • Defense: Add some noise

Spectre-V1 Defenses#

  • Compile Option
    • Inset LFENCE (load fence) on branches with loads

Spectre-V2 Poisoning Indirect Branch Prediction#

  • Involves context switching:
    • Context A, the regular code, and context B has some Spectre gadget that you want to branch to. We train the branch predictor so that when a function is always called, it jumps to function A. Now, we switch to context B, it will speculatively call a spectre gadget, which it will execute, potentially execute information into the cache.

Spectre-V2 Defenses#

  • Indirect branch restricted speculation (don't let low privlege influence higher)
  • Single thread indirect branch predictors (keep logical process prediction separate)
  • Indirect branch predictor barrier (reset the branch predictors)

Spectre-V3 (Return Stack Buffer)#

  • Reversing the stack buffer - source of misspeculation
    • Overfill or underfill due to limited structure size
    • Direct pollution of the RSB
    • Speculative pollution of the RSB (didn't get removed)
  • Across context the RSB is maintained

Spectre-V3 against SGX (attack 3)#

  • It work!
  • Attack 4 - user to kernel (maybe, didn't work on paper)

Spectre-V3 Defenses#

  • RSB Refilling
    • Default to branch predictor if RSB underfill
    • Fill RSB with benign gadget for kernel
  • Supervisor mode execution privilege (not bypassed by RSB)

Spectre-V4 Store to Load#

  • Speculation also tries to remove dependencies
  • This could be bad
  • Still in development
Last updated on