What is the Spectre?

Asked

Viewed 187 times

6

The Spectre is a security breach that compromises a large amount of systems.

  • What is?
  • How it works?
  • What kind of systems and devices are vulnerable?
  • What can be done to defend yourself against him?
  • Why did he get that name?
  • Are the closing votes considering that the question is about hardware? I find it valid, especially considering the relevance of this vulnerability.

  • @bfavaretto I think that whoever voted to close should not have understood the question.

  • I use Iobit ASC and it patches in Windows 10 for correction.

1 answer

8


What is?

The Spectre is a vulnerability arising from a failure of microprocessor designs that allow malicious processes to read memory belonging to other processes.

It was discovered along with the Meltdown in mid-2017, but became public only in the first week of 2018.

How it works?

To understand how the Spectre works, it is necessary to get into some details of computer architecture, in particular the pipeline, the speculative execution, the branch Prediction and the cache memory.

What is pipeline?

For a processor to execute an instruction, it is necessary to perform several actions:

  • Find the instruction to be executed in memory.
  • Decode the instruction and identify it.
  • Map the registers that the instruction reference.
  • Execute the instruction itself.
  • Store the result of the instruction in some register.

The exact steps obviously vary greatly from one type of processor to another. Older processors run one instruction at a time, meaning that only one of the above steps would be active at any given time. Newer processors gain performance when implementing the pipeline concept, where an instruction starts its execution before the previous one ends: While the result of the instruction X is being stored in some register, the instruction X+1 is already being executed, the instruction X+2 is having the registers mapped, the instruction X+3 is being decoded and the X+4 is being searched in memory.

However, the pipeline has two problems:

  • When conditional deviation instructions of type occur se A então B, senão C, because before the instruction that evaluates A have your result known the consecutive instructions are already entering pipeline. The processor has no way of knowing if it will put the way of the então or the path of senão in the pipeline.

  • When the result of an instruction depends on loading some value from the main memory, especially if this value is not present in the cache memory. Loading a value from the main memory to a logger may take a few hundred processor cycles.

And that’s where the speculative execution comes in.

What is speculative execution?

With speculative execution, the processor will kick the result of conditional deviation and then choose one of the two paths to put in the pipeline even though we didn’t know if it was the right way. If he got it right, then great, the performance gain will be satisfactory. If he has chosen the wrong path, he discards any change that would have resulted from it, comes back and takes the other way, which is slower.

Something similar happens when a value is read from memory and is unavailable. To not stop the pipeline, the processor kicks a read (normally zero) value and continues execution speculatively with that value. If when the value becomes available, it turns out to be different from the value kicked, the processor undoes the changes made with the speculated value and remakes with the correct value.

What is branch Prediction?

To know is the best side to be kicked on conditional deviations, the processor uses an algorithm of branch Prediction.

The branch Prediction makes a simple analysis in the history of each conditional deviation to try to determine which is the best side to kick. If a given if has fallen much more recently in the então, the branch Prediction will tell to kick the então because this is likely to be the case the next time if is executed. The same occurs if it is falling much further into the senão. The details of the branch Prediction, such as the required number of wrong kicks for him to change his mind, what are the deviations that must be tracked and when they vary from processor to processor.

In practice, ifs whose result is completely random and chaotic are rare, then, except if the if is being executed for the first time, the branch Prediction will probably kick the right side for the processor to put inside the pipeline.

What is cache memory?

In addition to the main memory, there is another smaller memory within the processor called cache. Access to it is much faster than access to the main memory, but its capacity is much smaller. The most frequently and recently accessed data from the main memory is cached. The data in the cache are mapped blocks for the main memory. The size of each block varies from processor to processor, but sizes such as 128, 256, or 512 bytes are common. The cache size of each processor is fixed and cannot be changed.

Keeping the data more frequently and recently accessed in the cache avoids the time cost of having to locate it in the main memory. Since the cache is smaller than the main memory, when a data block has to be brought from the main memory to the cache, another existing data block in the cache has to be removed.

In fact, modern processors maintain multiple levels of cache, where in addition to the main memory cache, we have the cache cache and even the cache cache cache cache. These various caches are called L1, L2 and L3, where the L1 is the innermost. On Intel processors, each core (core) the processor has its own L1 and L2, while the L3 is shared between all cores.

What is the problem of speculative execution?

The path or value the actual processor has chosen (branch Prediction) to put in the pipeline should be something completely invisible to the process that is being executed. However, given the fact that if the processor chooses the right side or the right value in speculative execution, it will perform the task faster than if it chooses the wrong side or value, then the time taken can be measured to determinewhether which path the processor has run speculatively.

Speculative execution can bring blocks from the main memory to the processor cache. Although the effects of speculative execution when incorrect are reversed, there is no reversal in the caches. A memory block brought to cache due to speculative execution is there even if this speculative execution is reversed.

This means that an attacker hacker can, by measuring the time it takes for a function to execute, determine whether it accessed the cache or not, even if speculatively. With a certain ingenuity, it is possible to make the difference between running quickly and running slowly serve to reveal the content of some information in memory.

Like the Spectre can be used to plot an attack?

The Spectre is a vulnerability that allows a malicious process to read (in a rather indirect way) the content of the memory of another process that should be inaccessible, by taking advantage of speculative execution.

For example, let’s assume that the process to be attacked has a check like this in C (code provided by the discoverers of Spectre):

if (x < array1_size)
    y = array2[array1[x] * 256];

In that case, this is a if whether the array1 can be accessed. If so, it is accessed and the value read is used to index the array2. The attacker needs to have control of the value of x. 256 is a value that is large enough that different values of array1[x] result in different portions of array2 being cached.

With this, the attacker first trains the processor so that the speculative execution always kicks that the if will enter (ie that would not fall into a else). One way to do this is to assign zero to x and then invoke the code that contains the if above a few times.

Having trained the processor, the attacker performs some operations to ensure that array1_size and array2 stay out of the cache. One way to do this is to use the instruction clflush which specifically serves to clear the cache. If this is not possible, you can access several parts of the memory far apart from each other so that they occupy the cache and end up leaving array1_size and array2 outside of her.

The attacker then executes this code using a value x greater than array_size. Since array_size is not available in the cache, the processor will kick its value and start a speculative run that will incorrectly enter the if and read data out of bounds with the array1[x]. As this reading is out of limit, it will result in some other information whatever is in the memory of the attacked process.

Running this repeatedly with several values for x, it is possible to access much of the memory of the attacked program. So if the attacker wants to force a speculative access to the memory address y of the wholesale program, knowing that a is the memory address of array1, compute the x with x = y - a.

However, although any byte of memory of the attacked program can be read by the same while accessing array1 outside its limits (even if in a speculative way), this still does not allow the attacker to know its content, because, directly, it will only get the result of the actual execution, which will not be relevant. And that’s where the array2 enters.

The read content of array1[x] is used to access array2, so that different parts of array2 cache for different values obtained from array1[x]. Assuming the speculative reading of array1[x] has produced as a result a number k, an access to array2[k * 256] will be quick, while an access to any other part of array2 will be slow.

If the attacker has access to array2, he can guess a value j (Let’s assume that 42) and access it in position j * 256 and if such access is fast, then 42 shall be the value of the position corresponding to x. Otherwise (if access is slow) the attacker will know the value in position y is not 42, and can repeat that the process with other values of j until you find out what the byte content is y.

If the attacker does not have access to array2, still it can invoke the code to be attacked by passing a valid value of x and measure the resulting time so that if it is fast, it is deduced that the array2 was in the cache and this helps to find out which part of array2 was accessed and consequently (with a good dose of trial and error) what is the value of y.

All this is possible if the attacker has access to a code as shown above. However, several other code patterns containing more than two possible paths (ifs, switches, whiles) and make access to memory blocks (arrays, arrays and similar) can be somehow abused when measuring the time taken in speculative executions. That is, these code patterns that can be abused by Spectre are common and abundant in almost all types of programs, often found even within standard libraries that are included within it.

The attack is not restricted only to low-level code that interacts directly with memory. For example, the following Javascript attack was published by the discoverers of Spectre:

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

A variant of Spectre is when the attacker has control not only of determining whether or not a conditional deviation will be executed speculatively, but also when he has control of where the deviation occurs. In many languages, this is more or less the case that occurs when the attacker is taking advantage of a function, procedure or method that receives as parameter a lambda, a callback, another function or similar thing and this is something that the attacker controls. Thus, the attacked function ends up executing code chosen by the attacker in a speculative way, increasing the possibilities of carrying out the attack.

Attacks that determine one bit at a time are possible. This reduces the need to perform 256 tests per byte of attacked memory to only 8 tests per byte (i.e., 1 per bit).

What kind of systems and devices are vulnerable?

Almost all modern devices are vulnerable. Pcs, Notebooks, smartphones, tablets, virtualized servers and cloud. This is because almost all modern processors use speculative execution.

The only devices left out are microcontrollers, Rduino, embedded devices, calculators and other devices that have extremely simple designs and extremely limited capabilities or that are quite old. These devices do not use speculative execution or even pipelines on their processors.

Specifically, the attacking program needs to be able to interact in some way with the program being attacked, which greatly reduces the possibility of a hacker taking advantage of it. However, in the case of browsers, this is much more likely to occur since Javascript allows the attacker to forge the code that accesses any other part of the browser’s memory in a speculative way (including that belonging to other tabs), which in theory means that any tab could use the Spectre to read the contents of any other tab or even the internal details of the browser, and thereby steal passwords or other sensitive information.

What can be done to defend yourself against him?

The Spectre is something very difficult to defend. The two ways to combat it are:

  • Eliminate or greatly modify the functioning of speculative execution.

  • Eliminate the possibility of measuring time precisely enough to enable the attack.

Neither of the two alternatives is very attractive. Speculative execution is what brings high performance gains and cannot be abandoned. And even if it were, it would still require the exchange of all the processors of almost every PC, laptop, tablet, smartphone and server produced in the last 20 years or so, which is clearly not feasible.

Browser developers (Chrome, Firefox, Safari, Edge, etc.) for the time being are providing a palliative solution consisting of updates that reduce the accuracy of the Javascript functions that measure time. With this, the idea is to prevent an attacker from measuring the time that certain instructions took to execute, which prevents the attack from taking effect.

It must be admitted that this solution is rather palliative and simplistic, but since this failure came to light only very recently, other methods that allow its mitigation are still unknown.

LLVM developers are modifying the way code compilation occurs to reduce (but this does not eliminate) the possibility of accessing improper parts of memory through speculative execution.

Why did he get that name?

The key to everything is in speculative execution. The word speculative remembers spectrum. Moreover, in the words of the discoverers, this problem is something that will haunt to all for many years, as it is something quite difficult to be corrected. And that is why he received this logo:

I would also add that speculative executions of code that are reversed is something that sounds to me like a "ghost" code running on the processor. It is something that should be totally invisible and undetectable and that would leave no discernible trace of its existence in the real world as if it had never existed, because it depended on conditions that were not true to come into existence. But, some paranormal effect of its (non-)existence is still able to cause it to somehow manifest itself in the world of the living bringing haunting and torment.

References

Browser other questions tagged

You are not signed in. Login or sign up in order to post.