|How Spectre Works|
|Written by Mike James|
|Wednesday, 10 January 2018|
This the second part of our examination of how Meltdown and Spectre work. The aim is not to explain how to manage the vulnerabliities but to understand how they work and what exactly the flaw is in the hardware that the software can take advantage of.
Spectre and Meltdown exploit the same flaw in the hardware but they use different routes to gather the information. What happens in both cases is that the processor is made to execute instructions it should never execute as part of its speculative execution hardware. Once the processor discovers that it shouldn't have carried out the instructions it removes all trace that the instructions were ever carried out - except of course it forgets to reset the cache back to its original state. It doesn't cache the data that should never have been accessed, but if that data is used to access some other data used as an address then that data is still in the cache. To find the data that is in the cache just needs a comparison of access times to reveal which of a possible set of data has been acessed. Which data have been cached gives you the value of the restricted data that you should never have had access to.
The Meltdown exploit uses an attempted access to the OS kernel address space to fire an exception, but not before speculative execution has retrieved and used the off-limits data and left a trace of it in the cache. Meltdown is an exploit directed at the kernel and as such is fairly easy to counter by keeping kernel and user addresses separate and this is the basis of the fix that is being rolled out for most operating systems at the moment.
The Spectre exploit is much more difficult to deal with, even though it is based on the same principles as Meltdown, because it can be used to attack any program and that program doesn't need to have any defects to be vulnerable.
The Spectre attack comes in two forms. The first is a classic buffer overflow exploit. However, in this case the buffer is protected against overflow and yet it still overflows! The mechanism looks a lot like Meltdown, but there are a few differences.
Consider the following:
As long as x is smaller than the array1_size then nothing bad happens and the test is to prevent x from going beyond the end of array1, which is exactly what every good programmer should do. However, this analysis ignores branch prediction and speculative execution. Most modern processors keep a record of how often a branch is taken and this is used to predict what will happen. In this case suppose the branch prediction is that x is usually smaller than array1_size, then it is reasonable to speculatively execute the instruction before the condition has been evaluated. We can arrange for array1_size not to be in the cache and thus the time to evaluate the condition is relatively high compared to the time to speculatively execute the following instruction. We can also ensure that the branch predictor thinks that the instruction is the next instruction to happen by training it with a lot of valid examples of the test and the array access. Spectre needs a fair bit of preparation to work well.
When the condition is finally evaluated the processor realizes its mistake and throws away the computation, but at this point the contents of array[x], which is in memory beyond the end of the array, has be used to look up an element of array2 which is now in the cache. Notice that the contents of array1[x] are not in the cache, but this doesn't matter because by simply finding which element of array2 is in the cache we can deduce array1[x]. All we need do is access each element of array2 and time how long it takes - the fast access is the one in the cache.
This is a fairly easy attack and it works with programs that are apparently not vulnerable to buffer overflow. This makes fixing the problem much harder. About the only direct solution to the problem is to change the processor's microcode so that the cache is cleared of all changes during speculative execution and, at the moment, there is no sign of this - even though Intel is making comments about fixing the problem in two weeks.
It clearly isn't just Intel failing to think through the implications of what happens when you add a new feature.
As well as a simple buffer overrun, the Spectre mechanism can be made to force the speculative execution of instructions in the victim code in conditions in which it was never meant to be executed.To do this the branch predictor has to be trained to expect a jump to a possibly illegal location. It seems that this is possible because the branch predictor ignores any errors:
"The branch predictor learns from jumps to illegal destinations. Although an exception is triggered in the attacker’s process, this can be caught easily (e.g. using try...catch in C++). The branch predictor will then make predictions that send other processes to the illegal destination."
This is a much more difficult exploit to implement in the real world because you need to know a great deal about the code being attacked. It is very similar in approach to a Return Oriented Programming (ROP) attack. However, like the buffer overrun, it doesn't need the attacked code to be flawed in any way.
It is a characteristic of both Meltdown and Spectre that they work with code that is written in an absolutely perfect way from a security point of view.
Although this is not intended to be a "how to fix" look at the two exploits, it is worth mentioning that the current attempts at fixing the problems don't really fix their cause. The only real fix is for the processor architecture to be changed so that speculative execution no longer causes any architectural micro changes. In other words, speculative execution has to do a better job of cleaning up after itself. This can only be achieved by changes to the microcode that controls the processor. Intel does issue such updates and they are installed usually as part of a BIOS update. Is this what Intel has promised as a fix in a few weeks time?
If so I don't think the operating system and browser fixes that are currently being worked on are needed.
Without a microcode fix the basic mechanism of Meltdown and Spectre are still operational and it is just a matter of time before someone thinks up another way to use speculative execution, branch prediction and cache timing.
or email your comment to: email@example.com
|Last Updated ( Wednesday, 10 January 2018 )|