Skip to content

Instantly share code, notes, and snippets.

@lattera
Last active October 21, 2016 12:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lattera/c785e7088118442f10addf8c6017c7d0 to your computer and use it in GitHub Desktop.
Save lattera/c785e7088118442f10addf8c6017c7d0 to your computer and use it in GitHub Desktop.

Thoughts on the BTB Paper

The Branch Target Buffer (BTB) whitepaper[1] presents some interesting information. It details potential side-channel attacks by utilizing timing attacks against the branch prediction hardware present in Intel Haswell processors. The article does not mention Intel processors later than Haswell, such as Broadwell or Skylake.

Side-channel attacks are always interesting and fun. Indeed, the authors have stumbled into areas that need more research. Their research can be applicable in certain circumstances.

As a side-note, KASLR in general is rather weak and can be considered a waste of time[2]. The discussion why is outside the scope of this article.

No Independent Analysis

The authors of the paper have not shared their code or provided any method for independent analysis. Code on GitHub[3] now exists for breaking Linux KASLR. But as mentioned above, KASLR is worthless.

With regards to breaking ASLR, we will see that in order to fully analyze their findings, we will need full steps for reproduction. Since the authors provided no such thing, independent analysis is not possible.

The Local Attack Requirement

The BTB whitepaper makes an assumption that is becoming all too common in recent anti-ASLR whitepapers: the local attack vector.

The primary assumption made by the whitepaper is that the attacker can already run arbitrary code on the system. This would mean that the attack against ASLR is local. Exploit mitigation technologies like ASLR are not meant to protect against local attacks, but rather remote attacks. Indeed, if an attacker can run arbitrary code, the game is already over.

The concept ASLR was designed solely to help protect against remote attacks. If an attacker is able to gain entry to a system remotely, it should be in a way such that ASLR isn't applicable. Take a phishing attack, for example. The attacker crafts a malicious Word document that contains a macro to spawn a shell. If the attacker can successfully convince the user to open the document with macros enabled, ASLR isn't applicable.

One could argue that ASLR should help protect against privilege escalation (privesc) attacks locally. ASLR might indeed help, but once an attacker has gained access to the system, so many other vectors for privesc have opened up. Traditional system hardening would apply best in mitigating local attacks, not ASLR. Normal system hardening could include implementing MAC/DAC, disabling unprivileged debugging, setting securelevel, etc.

Another assumption made by the whitepaper is that the attacker does not use any information leaks directly provided by the victim process. The only information the attacker gains about the victim process is through the BTB side-channel attack.

Victim Process and Spy Process

The paper describes a scenario where there are two processes involved: a victim process and a spy process. The victim process is the process the attacker is truly interested in. The attacker crafts a special spy binary that when loaded, certain code branches align with that of the victim process (meaning, they share the exact same virtual address).

Crafting this spy application would require intimate knowledge of the victim process, including its memory layout during runtime. If the attacker needs to use side-channel attacks to determine ASLR deltas, how would the attacker be able to craft such a special binary in advance?

Non-ASLR ASLR

Early on, the whitepaper describes an ASLR system that isn't applicable to its target operating environment (Linux):

some ASLR implementations randomize positions of libraries only one time during the system boot. Consequently, all processes executed on a machine receive the same mappings of the libraries.

Linux does not implement ASLR as described above. Every new execution environment will have separate deltas applied. Thus, libc loaded in one application will have a different base address than libc loaded in another application (or even a separate instance of the same application).

Later on, the paper describes why their attack on ASLR is successful:

Our expectation is that the two branch instructions will map to the same BTB entry if they are located at the same virtual address.

(Emphasis theirs, not mine).

In order for two distinct processes to match up completely with regards to virtual address space, ASLR would need to be completely disabled.

So, in order to defeat ASLR, this whitepaper assumes ASLR must be disabled.

See the appendixes A and B to see how distinct instances of a sample application with ASLR fully applied do not get the same deltas applied to the virtual address space. The only way for the virtual addresses to be the same is to disable ASLR.

Conclusion

Though the attack might have some merits with regards to KASLR, the attack on ASLR is completely debunked. The authors of the paper didn't release any supporting code or steps for independent analysis and verification. The results, therefore, cannot be trusted until the authors fully open source their work and the work is validated by trusted and independent third parties.

References

  1. https://github.com/lattera/articles/blob/master/infosec/Exploit%20Mitigations/ASLR/2016-10-19_btb/references/micro16.pdf
  2. https://forums.grsecurity.net/viewtopic.php?f=7&t=3367
  3. https://github.com/felixwilhelm/mario_baslr/

Appendix A: Sample application, run 1

7fa9a7b44000-7fa9a7cfb000 r-xp 00000000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7fa9a7cfb000-7fa9a7efb000 ---p 001b7000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7fa9a7efb000-7fa9a7eff000 r--p 001b7000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7fa9a7eff000-7fa9a7f01000 rw-p 001bb000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7fa9a7f01000-7fa9a7f06000 rw-p 00000000 00:00 0
7fa9a7f06000-7fa9a7f27000 r-xp 00000000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7fa9a810f000-7fa9a8112000 rw-p 00000000 00:00 0
7fa9a8125000-7fa9a8127000 rw-p 00000000 00:00 0
7fa9a8127000-7fa9a8128000 r--p 00021000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7fa9a8128000-7fa9a8129000 rw-p 00022000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7fa9a8129000-7fa9a812a000 rw-p 00000000 00:00 0
7fa9a812a000-7fa9a812b000 r-xp 00000000 fd:02 138234307                  /home/shawn/tmp/pid
7fa9a832a000-7fa9a832b000 r--p 00000000 fd:02 138234307                  /home/shawn/tmp/pid
7fa9a832b000-7fa9a832c000 rw-p 00001000 fd:02 138234307                  /home/shawn/tmp/pid
7ffd2a7d1000-7ffd2a7f2000 rw-p 00000000 00:00 0                          [stack]
7ffd2a7f7000-7ffd2a7f9000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Appendix B: Sample application, run 2

7f9fabc8f000-7f9fabe46000 r-xp 00000000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7f9fabe46000-7f9fac046000 ---p 001b7000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7f9fac046000-7f9fac04a000 r--p 001b7000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7f9fac04a000-7f9fac04c000 rw-p 001bb000 fd:00 201329167                  /usr/lib64/libc-2.17.so
7f9fac04c000-7f9fac051000 rw-p 00000000 00:00 0
7f9fac051000-7f9fac072000 r-xp 00000000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7f9fac25a000-7f9fac25d000 rw-p 00000000 00:00 0
7f9fac270000-7f9fac272000 rw-p 00000000 00:00 0
7f9fac272000-7f9fac273000 r--p 00021000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7f9fac273000-7f9fac274000 rw-p 00022000 fd:00 201329159                  /usr/lib64/ld-2.17.so
7f9fac274000-7f9fac275000 rw-p 00000000 00:00 0
7f9fac275000-7f9fac276000 r-xp 00000000 fd:02 138234307                  /home/shawn/tmp/pid
7f9fac475000-7f9fac476000 r--p 00000000 fd:02 138234307                  /home/shawn/tmp/pid
7f9fac476000-7f9fac477000 rw-p 00001000 fd:02 138234307                  /home/shawn/tmp/pid
7fff54004000-7fff54025000 rw-p 00000000 00:00 0                          [stack]
7fff54036000-7fff54038000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Appendix C: Sample application source code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
        while (printf("%d\n", getpid()))
                sleep(10);
        return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment