Since Spectre caught the public eye beginning of this year, a lot of noise has been made about it. It raises a lot of questions about the security vulnerability.
All major Silicon Vendors have made announcements either about how their processors were not impacted or about why this flaw was so specific that it was almost inapplicable (still, they provided patches).
Multiple articles have been published to explain how it works, but, they are all extremely technical. If you are not familiar with words like “cache”, “side channels”, “branch prediction” and ideally know how to code in C, it will be hard for you to understand them.
On the other hand, without having an idea how Spectre works, it’s hard to grasp what the real stakes are and what needs to be done to mitigate the risks. So you might feel a bit stuck there.
Why is it so complicated to explain Spectre?
Because the flaw itself is based on a couple of internal processor features that typically only specialists know and care about. Usually, when everything is working well, there are no reasons to complain or even think about these features.
In fact, none of them are complicated and they can be individually explained. This article aims at illustrating the key concepts that are necessary to understand Spectre using simple examples.
First, I will provide you with some insights on how a modern processor is designed to avoid that sensitive information can be leaked from one application to another. In Part 2, I will illustrate two optimizations that are implemented in all modern processors to improve their performances. And then, I will explain how Spectre takes advantage of those two optimizations described in part two to bypass the security described in part one to access secret information on your computer.
MEMORY MANAGEMENT UNIT IS THE KEY OF YOUR COMPUTER’S SECURITY
Let’s imagine you have 2 applications running on your computer. One with a secret, for instance, your credit card number or an encryption key, and a malicious one trying to access it:
You don’t want the malicious application to access you credit card number, do you? And it will not happen thanks to the memory management unit. This hardware component will enforce that those 2 applications cannot access the memory of one another. Thus, the malicious application cannot access your credit card number.
All modern operating systems use the memory management unit to make sure that applications cannot steal information from each other. It has been working for years and it is working still. But the different research groups who* came up with Spectre found a way around. So, the memory management unit, which is the corner stone of the security for your computer, has been broken. If it hasn’t been clear yet, this is bad news, very bad news… But how has this happened?
*If you want to know more about them you can read this article https://www.wired.com/story/meltdown-spectre-bug-collision-intel-chip-flaw-discovery/
THE TOOLBOX USED BY SPECTRE TO HACK YOUR SYSTEM
You should wait for your friends
So the news is the Memory Management Unit (MMU) of your computer can be broken. It has happened because you want your computer to be as fast as possible. Yes, it’s your fault or at least kind of.
In 1980, the speed of an Intel processor 8086-10 was 10Mhz; nowadays a modern processor will run at 3Ghz, 300 times faster. At the time of the 8086, the memory speed was the same speed as the processor, so 10Mhz. But for modern processors, the memory speed is way slower than the processor speed – about two times slower in fact:
Does this mean that your processor is waiting for the memory half the time? No, some mechanisms have been developed to keep your processor as busy as possible while waiting for more information from the memory and two of those mechanisms are used by Spectre to attack your system
First mechanism: Spectre and the cache memory
The first mechanism exploited by Spectre to attack your system takes advantage of the cache memory.
I will illustrate what the cache memory is with an example. You are solving some math problems with a friend. You want to do a very simple operation, 2 + N, but to get the value of N, your friend needs to take his car and drive to the library, read the value and come back:
During this time, you are not really keeping yourself busy. Instead, you are just waiting for your friend to come back with the value of N. But as soon as you get the value, you write it down in your notebook. In your computer, the library is the memory and your notebook is the cache:
Next time you want to solve 2 + N, instead of sending your friend to the library, you just read the value that you had previously written down on your notepad. That’s what we call a cache hit since you don’t need to read the value from the memory (or in our example send your friend back to the library). It’s time for more math, 2 + Y, so your friend goes to the library again and comes back with the value Y that you conscientiously write down in your notebook. You go on with a couple of different values, Z, W, X… until you run out of space and decide to replace N by a different value in your notebook.
Later, you need N again for a new math operation, but it’s not in your notebook anymore. That’s called a cache miss: You need to send your friend back to the library to get the value of N for you.
If we consider that reading from your notebook is fast (your notebook is in front of you), getting information from the library is slow in comparison (you need to drive to the library and back). By measuring the time needed to read a value, it is possible to know if you have read that value from the cache (your notebook) or from the memory (the library). So far, every time a value was not available, you have been waiting for your friend to come back with it from the library. But if instead of waiting, depending on your previous experience you might speculate on what could be the next value?
Second mechanism: Speculation including branch prediction
To explain the second mechanism used by the Spectre attack, speculation/branch prediction, let’s take a different example.
You are used to having a cup of tea with your friend every day, but this time you don’t have any tea left. Therefore, you send your friend to the shop to buy some. Meanwhile, to save time, you start boiling some water as you speculate that your friend will find some tea (because this is what usually happens). You just predicted the most likely branch of the next 20 minutes of your life:
But this time your friend comes back and there was no tea available anywhere in the city, so you stop the kettle and forget about it.
The processor in your computer is doing exactly the same, this is called branch prediction. Every time it is waiting for some information, it is trying to use this time to start some action based on its previous experience. In our case, this action was boiling the water. But, if for some reason the condition which is usually true is false, the processor just cancels what it was doing. In our case, it means to switch off the kettle.
But there is a side-effect to this: even if you switched off the kettle as soon as you have received the information that no tea was available, the water inside still had the time to warm up and it will take some time to cool down. There is some residual information due to your previous action (hot water) and this is the kind of information that Spectre can use to steal your secrets. This indirect way to steal data is called a side channel.
SPECTRE BREAKING UP INTO YOUR SYSTEM’S SECRET
As an example, we are going to demonstrate how one variant of Spectre could be used to steal your credit card number (5468) from a victim program.
In this example, the victim program is used to save your credit card number and some other personal information like your name, your age…
One of the features of the victim program is to centralize all this information for all applications on your computer. You enter your name and age one time and all other applications can find your personal information in one centralized space managed by the victim program.
To start the attack, Spectre will empty the cache of the processor and call the victim program to read the index to name at index 1:
The victim program will check if its input index is inferior or equal to MAX_INDEX (the maximum value that is allowed in order to keep your other information safe) and if so, it will use it to get the index to read your name.
But why would your processor use two indices to access one piece of information?
Let’s get back to the library. In a library, you have multiple books, each of them categorized depending on its type. It’s the same story for the information in your computer: All information is usually classified depending on its type. For instance, if you have multiple users on the same computer, you will have all their names in one table, all their ages in another table and so on. But to keep the relation between the age and the name of each user, you need a summary table (in our case, Table 1). Table 2 contains the information itself.
Because the cache has been emptied before the attack was started, each access to MAX_INDEX to do the comparison will produce a cache miss (i.e., your friend will need to go to the library to get MAX_INDEX, remember?). Spectre will call the victim program multiple times in a row with index 1 and then it will change to index 26 where your credit card numbers are located.
How does Spectre know about the index of your credit card number?
In fact, you need to know the structure of the program you want to attack in detail. A difficult task, but not impossible with some effort
So far, the index has always been inferior or equal to MAX_INDEX, so instead of waiting to get the value of MAX_INDEX from the memory (remember: the cache has been emptied), your processor will speculate that this is true again. As a result, the victim program will go ahead and use an index of 26 even though it is above MAX_INDEX. The victim program will misuse the value of the first 2 digits of your credit card number as an index to read in Table 2. But why doesn’t Spectre try to read the secret directly?
Because as soon as the processor receives the value of MAX_INDEX, it will cancel the reading and not return any value to Spectre. So instead, we are going to use the side channel (remember, the kettle technique?). Assuming that we know in which range the victim program will access the memory (in our case it is from 50 to 70), we will read this memory range from Spectre:
But how does Spectre know if there has been a cache hit?
In fact, Spectre measures the time for each access; if it’s a short time, it means that the cache has been accessed (cache hit), if it’s a long time, it means that the memory has been accessed instead (cache miss). And because the cache had been emptied before the beginning of the attack, the only cache hit in the memory will be the index accessed by the victim program, which is the first two digits of your credit card number…
Here we are, we have the first half of your credit card number. Another loop and we’ll have access to the second half.
Spectre is about making the processor start some actions that in theory should not have any consequences because they are being cancelled right after. But unfortunately, these actions will leave behind some traces (the residual information) that can be accessed later by a malicious program. Yes, exactly like the warm water in the kettle.
SOME CLUES ON HOW TO PROTECT YOUR SYSTEM FROM A SPECTRE ATTACK
Now that you have an idea how Spectre works, it is time to discuss how you can protect your systems from it:
The easiest solution will be to disable the branch predictor, but if you have followed me so far, you know that doing that will have a huge impact on the overall performance of your system (up to 30% on an Intel processor). In order to decide whether it may be a practical solution for your use case anyway, you will need to benchmark your system.
Alternatively, you can address some of the problems associated with Spectre using the patches that have been provided by the Silicon Vendors whose processors are affected. However, these patches will only address the two known variants of Spectre (Silicon Vendors are not fortune-tellers). This is a major problem because Spectre is an extremely powerful class of hacks and it is very likely that plenty of new variants of it will be discovered in the coming years (in fact, the reason why the research group who published the first article on Spectre came up with this very name is because it will haunt the tech industry for years…). These new variants may use different side channels or apply new ways of misusing the built-in branch-prediction in processors.
Additionally, these patches have only been provided for the latest versions of kernels. Depending on your system, this means that you will need to either backport them to your specific version of kernel or upgrade your kernel to the latest version. Choosing the best solution for your system requires a diagnostic of your kernel.
For most modern processors that both allow a secure boot and only run a pre-defined set of applications, there is another powerful way to protect them against Spectre: It is possible to secure their runtime environment by only booting images that are trusted by the system.
Finally, because end users will always want more performance, Spectre will not stop Silicon Vendors to provide new generations of processors that use speculation and cache memory. Even though they will, of course, make sure to protect these new versions against the two known versions of Spectre, they will not necessarily be protected against the next flaw. Thus, it is important to make sure that all systems will be updatable. It will allow adapting to the next version of Spectre.
If you want to know more about secure boot or discuss the best solutions to manage updates for your embedded system, you can ask your questions or make your comments in the comment area below, I will be happy to help.