Blind return oriented programming

Last updated

Blind return oriented programming (BROP) is an exploit technique which can successfully create an exploit even if the attacker does not possess the target binary. BROP attacks shown by Bittau et al. have defeated address space layout randomization (ASLR) and stack canaries on 64-bit systems.

Contents

ROP History

With the current improvements in OS security and hardware, security features like the Linux PAX project, code injection is now impossible. Security researchers then conceived a new attack which they named return-oriented programming to defeat NX (non-executable) memory. This attack relies on affecting program flow by controlling the stack, especially return addresses. Gadgets are the fundamental units of this attack. Gadgets are a group of instruction sequences ending in a return instruction, along with a certain state of the stack. A gadget can perform an operation like loading a word from memory into a register, or performing a more complex operation like a conditional jump. With a large enough target binary, a Turing-complete collection of gadgets can be constructed, which is more than enough to get a shellcode executed. One assumption which ROP makes is that the attacker possesses the target binaries and hence knows the addresses of the gadgets beforehand.

Scenarios for BROP

There are three new scenarios which BROP [1] can be relevant for. They are:

  1. In case of closed binary services, to discover vulnerabilities where techniques like fuzz and penetration testing need to be used.
  2. A known vulnerability in an open-source library can be leveraged to carry an exploit, even though the proprietary binary which uses it is closed source.
  3. It can also be used to hack an open-source server for which the binary is unknown.

The attack assumes that there is a service on the server which has a known stack vulnerability and also that the service should restart on crash.

Phases of attack

Stack reading

Return instruction pointers are usually protected by stack canaries. A stack canary causes the program to crash if its value is modified by a buffer overrun. In the BROP model of attack, the buffer overrun is carried byte by byte. Each try at the overrun results either in a program crash or continued execution. A program crash implies that the stack value was incorrectly guessed, therefore in 256 tries (average case is 128 tries), the stack value can be probably estimated. On 64 bit machines, 4 such stack reads would be required to leak the canary. Once the canary is leaked, the return instruction pointer can be perturbed in the same way. It may, however, be noted that though the estimation of the stack canary is exact, the same cannot be said about the return instruction address. The attacker would be satisfied to be able to leak any address within the text segment of the address space.

Blind ROP

This stage is the heart of the attack. The objective in this phase is to initiate a write system call, sending a dump of the binary to the attacker. The write system call has three params: socket, buffer, and length. As x86-64 calling conventions require the parameters to be passed through registers, appropriate pop instructions into rsi, rdi and rdx would be needed to set up the arguments for the write system call. Instruction sequences like pop rdi, ret and the like would be helpful in this regard. A simple ROP version of the write system call would be:

  1. pop rdi; ret (socket)
  2. pop rsi; ret (buffer)
  3. pop rdx; ret (length)
  4. pop rax; ret (write syscall number)
  5. syscall

One problem with this methodology is that even if useful gadgets are found in the address space after they return the address on the stack would lead to non-executable stack with a high probability. To remedy this, BROP proposers conceived stop gadgets. A stop gadget is anything that would cause the program to block, like an infinite loop or a blocking system call (like sleep). This also workers processors affected in the attack to be stuck in an infinite loop and hence allowing the attacker to carry on the attack.

What is mentioned above is the bare-bones methodology of the attack. In reality, a few optimizations can be carried out which help in efficiently carrying out the attack. Primary among them is the use of Procedure Linker Tables (PLTs) to track down the writing system call instead of passing the system call number to the syscall function. Others include using strcmp to populate the RDX register, as pop RDX, ret instruction sequences are extremely rare.

Build the exploit

Once the writing is found in the PLT, the attacker can dump the contents of the target binary to find more gadgets. The attacker can use conventional ROP gadget search techniques to gather enough and create a shellcode. Once they have the shellcode, the exploited system can be taken under full control with root access.

BROP prevention

A huge assumption in the BROP attack is that the server restarts after each crash and when restarting does not re-randomize its address space. So enabling re-randomization of address space at startup can provide almost complete protection against BROP. Another technique used by NetBSD and Linux is sleep on the crash. This slows down the attack considerably and allows the system administrator to look into any suspicious activity. Apart from this the conventional protection against ROP style control flow hijacking attacks, Control Flow Integrity also can provide provable prevention but at a significant performance overhead.

Similar attacks

Another attack that is similar in nature to BROP, is JIT (Just-In-Time)-ROP, or JIT-ROP. It is also another attack that's based on information disclosure, which is able to also defeat Address Space Layout Randomization. Both BROP and JIT-ROP will attempt to locate gadgets on the binary in order to initiate a ROP attack, where the goal is to exploit some type of data leak. However, unlike BROP, JIT-ROP is not an attack which is interactive, and seeks to adapt to no-crash/crash situations, but rather, the attacker will send out a script which will discover gadgets, then subsequently creates an attack for delivery. Also, JIT-ROP must have two different vulnerabilities (Both a heap and stack) known in advance of the attack, while BROP only requires awareness of a stack vulnerability. [2]

Related Research Articles

<span class="mw-page-title-main">Buffer overflow</span> Anomaly in computer security and programming

In programming and information security, a buffer overflow or buffer overrun is an anomaly whereby a program writes data to a buffer beyond the buffer's allocated memory, overwriting adjacent memory locations.

<span class="mw-page-title-main">Java virtual machine</span> Java Virtual machine

A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. The JVM is detailed by a specification that formally describes what is required in a JVM implementation. Having a specification ensures interoperability of Java programs across different implementations so that program authors using the Java Development Kit (JDK) need not worry about idiosyncrasies of the underlying hardware platform.

Common Intermediate Language (CIL), formerly called Microsoft Intermediate Language (MSIL) or Intermediate Language (IL), is the intermediate language binary instruction set defined within the Common Language Infrastructure (CLI) specification. CIL instructions are executed by a CLI-compatible runtime environment such as the Common Language Runtime. Languages which target the CLI compile to CIL. CIL is object-oriented, stack-based bytecode. Runtimes typically just-in-time compile CIL instructions into native code.

<span class="mw-page-title-main">Netwide Assembler</span> Assembler for the Intel x86 architecture

The Netwide Assembler (NASM) is an assembler and disassembler for the Intel x86 architecture. It can be used to write 16-bit, 32-bit (IA-32) and 64-bit (x86-64) programs. It is considered one of the most popular assemblers for Linux and x86 chips.

x86 assembly language is the name for the family of assembly languages which provide some level of backward compatibility with CPUs back to the Intel 8008 microprocessor, which was launched in April 1972. It is used to produce object code for the x86 class of processors.

<span class="mw-page-title-main">Shellcode</span> Small piece of code used as a payload to exploit a software vulnerability

In hacking, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode. Because the function of a payload is not limited to merely spawning a shell, some have suggested that the name shellcode is insufficient. However, attempts at replacing the term have not gained wide acceptance. Shellcode is commonly written in machine code.

In computer security, hardening is usually the process of securing a system by reducing its surface of vulnerability, which is larger when a system performs more functions; in principle a single-function system is more secure than a multipurpose one. Reducing available ways of attack typically includes changing default passwords, the removal of unnecessary software, unnecessary usernames or logins, and the disabling or removal of unnecessary services.

Buffer overflow protection is any of various techniques used during software development to enhance the security of executable programs by detecting buffer overflows on stack-allocated variables, and preventing them from causing program misbehavior or from becoming serious security vulnerabilities. A stack buffer overflow occurs when a program writes to a memory address on the program's call stack outside of the intended data structure, which is usually a fixed-length buffer. Stack buffer overflow bugs are caused when a program writes more data to a buffer located on the stack than what is actually allocated for that buffer. This almost always results in corruption of adjacent data on the stack, which could lead to program crashes, incorrect operation, or security issues.

A "return-to-libc" attack is a computer security attack usually starting with a buffer overflow in which a subroutine return address on a call stack is replaced by an address of a subroutine that is already present in the process executable memory, bypassing the no-execute bit feature and ridding the attacker of the need to inject their own code. The first example of this attack in the wild was contributed by Alexander Peslyak on the Bugtraq mailing list in 1997.

Address space layout randomization (ASLR) is a computer security technique involved in preventing exploitation of memory corruption vulnerabilities. In order to prevent an attacker from reliably jumping to, for example, a particular exploited function in memory, ASLR randomly arranges the address space positions of key data areas of a process, including the base of the executable and the positions of the stack, heap and libraries.

In assembly language programming, the function prologue is a few lines of code at the beginning of a function, which prepare the stack and registers for use within the function. Similarly, the function epilogue appears at the end of the function, and restores the stack and registers to the state they were in before the function was called.

<i>Hacking: The Art of Exploitation</i> 2003 book by Jon "Smibbs" Erickson

Hacking: The Art of Exploitation (ISBN 1-59327-007-0) is a book by Jon "Smibbs" Erickson about computer security and network security. It was published by No Starch Press in 2003, with a second edition in 2008. All of the examples in the book were developed, compiled, and tested on Gentoo Linux. The book also comes with a CD that contains a Linux environment with all the tools and examples used in the book.

In computer security, executable-space protection marks memory regions as non-executable, such that an attempt to execute machine code in these regions will cause an exception. It makes use of hardware features such as the NX bit, or in some cases software emulation of those features. However, technologies that emulate or supply an NX bit will usually impose a measurable overhead while using a hardware-supplied NX bit imposes no measurable overhead.

This article describes the calling conventions used when programming x86 architecture microprocessors.

In computer security, a NOP slide, NOP sled or NOP ramp is a sequence of NOP (no-operation) instructions meant to "slide" the CPU's instruction execution flow to its final, desired destination whenever the program branches to a memory address anywhere on the slide.

In software, a stack buffer overflow or stack buffer overrun occurs when a program writes to a memory address on the program's call stack outside of the intended data structure, which is usually a fixed-length buffer. Stack buffer overflow bugs are caused when a program writes more data to a buffer located on the stack than what is actually allocated for that buffer. This almost always results in corruption of adjacent data on the stack, and in cases where the overflow was triggered by mistake, will often cause the program to crash or operate incorrectly. Stack buffer overflow is a type of the more general programming malfunction known as buffer overflow. Overfilling a buffer on the stack is more likely to derail program execution than overfilling a buffer on the heap because the stack contains the return addresses for all active function calls.

Return-oriented programming (ROP) is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as executable space protection and code signing.

JIT spraying is a class of computer security exploit that circumvents the protection of address space layout randomization and data execution prevention by exploiting the behavior of just-in-time compilation. It has been used to exploit the PDF format and Adobe Flash.

Sigreturn-oriented programming (SROP) is a computer security exploit technique that allows an attacker to execute code in presence of security measures such as non-executable memory and code signing. It was presented for the first time at the 35th IEEE Symposium on Security and Privacy in 2014 where it won the best student paper award. This technique employs the same basic assumptions behind the return-oriented programming (ROP) technique: an attacker controlling the call stack, for example through a stack buffer overflow, is able to influence the control flow of the program through simple instruction sequences called gadgets. The attack works by pushing a forged sigcontext structure on the call stack, overwriting the original return address with the location of a gadget that allows the attacker to call the sigreturn system call. Often just a single gadget is needed to successfully put this attack into effect. This gadget may reside at a fixed location, making this attack simple and effective, with a setup generally simpler and more portable than the one needed by the plain return-oriented programming technique.

In computer security, a shadow stack is a mechanism for protecting a procedure's stored return address, such as from a stack buffer overflow. The shadow stack itself is a second, separate stack that "shadows" the program call stack. In the function prologue, a function stores its return address to both the call stack and the shadow stack. In the function epilogue, a function loads the return address from both the call stack and the shadow stack, and then compares them. If the two records of the return address differ, then an attack is detected; the typical course of action is simply to terminate the program or alert system administrators about a possible intrusion attempt. A shadow stack is similar to stack canaries in that both mechanisms aim to maintain the control-flow integrity of the protected program by detecting attacks that tamper the stored return address by an attacker during an exploitation attempt.

References

  1. "Blind Return Oriented Programming (BROP)". Stanford Secure Computer Systems group. Retrieved 2016-02-24.
  2. Keener, Lawrence (December 2015). "Evaluating the Generality and Limits of Blind Return-Oriented Programming Attacks" (PDF). Calhoun: The NPS Institutional Archive: 26. Retrieved 28 February 2016.