Compiler-Introduced Double-Fetch Vulnerabilities – Understanding XSA-155

I recently read a great blog post from Felix Willhelm (@_fel1x) about some double-fetch vulnerabilities he discovered in the Xen Hypervisor. These bugs are described in the Xen Security Advisory XSA-155. This post is as a result of me trying to understand the bug better.

Double-fetch vulnerabilities are introduced when the same memory location is read from memory and assumed by the programmer to be the same value, when in fact the memory could have been modified by an attacker in a concurrent thread of execution, such as in a shared memory section. What was particularly interesting about this advisory was that upon inspection of the code, there was no apparent double-fetch, but it can clearly be seen in the compiled binary.

TL;DR – All pointers into shared memory should be labelled as volatile to avoid compiler optimisation introducing double-fetches. A good presentation about this is “Shattering Illusions in a Lock Free World” (especially slides 28+). The compiler is not doing anything wrong which is why this is a bug in Xen, not gcc.

To demonstrate the issue, here is the vulnerable code, distilled from the vulnerable Xen code:

This vulnerability is specific to how gcc optimises switch statements with jump tables then there are 5 or more cases (more information here). Other cases where pointers to shared memory are not labelled as volatile could be exploitable, but in practise it seems relatively rare for the compiler to dereference a pointer twice.

And below is the resultant binary in IDA compiled with gcc 5.3.0 for Intel x64 (gcc 4.8.4 and x86 give the same result). The rbx registers points into a memory allocation, which could be shared memory and by defeferencing the pointer twice, we have our double-fetch vulnerability.

df-O1-x64The compiler appears to do this to avoid using a register in the case where the default case is hit. Given that the two memory accesses are so close together, there is unlikely to be a big performance hit from the double fetch. But it’s not enough to prevent the race-condition from being winnable by the attacker (see the bochspwn research for techniques to try and win these tight race conditions).

The compiler is allowed to turn a single memory access in code into multiple accesses because without the ‘volatile’ attribute on the pointer, it’s assumed that the memory will not be changed by another thread of execution. Simply declaring the pointer as volatile as below resolves the issue.

The double-fetch has now dissappeared as a register is used to store the switch value:

df-O1-x64-fixed To try and find other cases where double-fetches would be introduced, I used the following code to trash all current registers and to try and force the compiler to dereference a pointer a second time (code assumes that -fomit-frame-pointer is enabled).

But in every case that I tried, the compiler used the local variable in preference to a double-fetch from memory. The compiler could eliminate the local variable by fetching the memory location twice, but this didn’t happen with  gcc.

Here are the setups I’ve tried so far that exhibit the double-fetch behaviour in switch statements:

  • Compilers: gcc 4.8.4 and 5.3.0
  • Architectures: x86 and x64
  • gcc Optimisation Levels: O1, O2, O3 and Os

Binaries compiled with optimisation disabled or with -fno-jump-tables are not affected. Also, an initial experiment with an arm64 compiler from the Android SDK suggests that ARM binaries may not be affected.

Conclusion: Failing to label pointers to shared memory regions as volatile allows compilers to introduce double-fetches that aren’t reflected in source code. But in practice the compiler will only do this in specific circumstances. One case is switch statements that use jump tables on Intel procecessors. Further research is needed to figure out which other compilers, flow-control contructs and CPU architectures could introduce these double-fetches.

The code and build script are on GitHub.

Reverse Engineering Obfuscated Android Applications

The slides are now available for download.

Recently, I’ve been doing a fair amount of Android application reversing-engineering and many of the more security sensitive applications use obfuscators like ProGuard and DexGuard. At first it can be a little bit daunting, but once you figure out some of the obfuscation techniques it becomes a much more tractible problem.

steelcon-logo-11I presented some of what I’ve learnt at SteelCon in Sheffield this weekend. The conference is only in its second year, but it seems to be off to a strong start, and very well organised. There was a good mix of students, hobbyists, developers and infosec professionals; with a wide selection of talks to match. I’d highly recommend it to anyone with an interest in security based in the North of England.

Nothing groundbreaking by any means, but hopefully a useful introduction to people looking to get started with obfuscated Android applications.

android_slides

 

 

NFC – The Non-Radio Bits

Over the past couple of years I’ve been working at BlackBerry as a Security Researcher, working mainly on BlackBerry OS 10 devices. One of the really interesting projects that I’ve worked on is NFC (Near Field Communications) and I’m especially interested in the role that smart cards play in NFC mobile payments. My employer was kind enough to let me present some of what we’ve been working on at DC4420 in London and explain some of the technology that is used in contactless debit cards, oyster travel cards and mobile SIM cards.

NFC Title Slide

The slides can be downloaded from here which contain references to support the talk along with some explanatory notes.

Thanks to Tony and Major Malfunction for organising the event and thanks to everyone who came – really interesting questions from the audience.

Escaping From Protected Mode Internet Explorer with BNO Namespace Squatting Attacks

Back in early 2011, I did some research into ways of escaping the Protected Mode Internet Explorer (PMIE) sandbox. Having had some time between jobs recently, I looked into writing an exploit for one of the bugs, a Low to Medium Integrity privilege escalation, which can also be used to escape the current Adobe Reader X sandbox.

I didn’t finish the exploit, but I think it’s still worth sharing because at the time I reported the issue Microsoft decided not to issue a patch and the issue is still unfixed in the Windows 8 Consumer Preview. This is in part because they do not regard PMIE as implementing a security boundary, but their decision was potentially also influenced by the lack of any proof-of-concept code. Plus, I think the bug nicely demonstrates the practicality of “BNO Namespace Squatting” attacks.

“BNO Namespace Squatting” attacks are possible when two process running with different privileges share an object namespace and the higher privileged process creates an object (such as a shared section) with a predictable name, but doesn’t check that the object already exists. In this situation, the lower privileged process can specify arbitrary permissions on the created object.

In the exploit, a Low Integrity CreateFileMapping() is used to create a shared section by the Low Integrity process (inside the sandbox) and the PMIE broker process running at Medium Integrity (outside the sandbox) calls CreateFileMapping() again for a shared section with the same name. The second call succeeds, though GetLastError() returns ERROR_ALREADY_EXISTS. An added complication is that the name of the shared section isn’t static, but contains the Process ID (PID) of the broker process which hasn’t been created yet. To avoid having to predict the PID of the broker process (although this is possible) a large number of malicious shared sections are created.

The shared sections relate to Loosely Coupled IE (LCIE) functionality and are of the form: “ie_lcie_sf2main_<PID>”. Where the PID is a lower-case hexadecimal number.

Once the malicious shared section is accessed by the PMIE broker, a function pointer is called, which is under the control of the Low Integrity process and therefore control of EIP is gained. However, before the function pointer is called, the PMIE broker is terminating and the cause of this is currently unknown – thus why the exploit is unfinished. MSRC did originally confirm the bug as being exploitable, so I’m reasonably confident that I could finish the exploit given enough time.

 

The exploit code and related files can be found here, additional notes can be found in the source comments.

For more information, see: