A small security research group with solid background.     We do research to solve real problems with real solutions.
Hector Ismael

Fixing Offset2lib weakness

Current ASLR implementation in Linux suffers from the offset2lib weakness. Here we present a simple solution (a small patch) to fix it.

Introduction

The current implementation of ASLR in Linux defines three randomly located zones for PIE executables (for most Linux architectures): a zone to allocate the stack, another for the heap and another zone to locate the shared objects (referred as mmap_base). As of 16 February 2015 the only architecture which is not vulnerable to Offset2lib is the s390.

CurrentPatched

The offset2lib attack exploits the fact that the executable and the libraries are located "together", that is, one after the other. If the attacker is able to leak a pointer belonging to the application then the ASLR is defeated.

Solution

In order to remove the offset2lib weakness, the executable shall be located at a different zone than libraries. There are several implementation alternatives; one possible solution is to move the executable from the mmap zone to the any other two, but this solution moves the weakness to a different form of exploitation rather than removing the weakness. A better solution would be to define a new zone for the executable.

The Pax patch implements four ASLR zones, which effectively settles the offset2lib weakness. Pax solution also increases the number of entropy of each zone, even it is able to randomise non-PIE applications. As far as we know it is the most advanced ASLR implementation. Unfortunately, some people think that it is a too complex patch with, may be, too many features (some advanced features may break backward compatibility on some applications).

Our patch just creates a new random zone for the executable when it is PIE compiled (following the s390 architecture implementation). The figure on the right sketches the main differences between current process layout and the resulting layout with our patch.

Patching the Kernel

Here you'll find a roughly description of how to get and use the patch for the Kernel.

The patch [fix_offset2lib.patch] has been tested from kernel 3.18rc1 to 3.18-rc7 and also 3.17.4.

# wget http://cybersecurity.upv.es/solutions/aslrv2/fix_offset2lib.patch
# cd linux-sources
# patch -p1 < ../fix_offset2lib.patch
# make bzImage
  "Boot your system from this kernel image (configure grub2 accordingly)"
Compile a simple "C" PIE program which shows its own memory maps:
$ cat show_mmaps_pie.c
#include <stdlib.h>
#include <stdio.h>

int main(void){
    char command[1024];
    sprintf(command,"cat /proc/%d/maps",getpid());
    system(command);
    return 0;
}

$ gcc -o show_mmaps_pie -fpie -pie show_mmaps_pie.c

If you execute show_mmaps_pie test application before applying the patch, you will see that the executable image is located right above the dynamic linker/loader.

 $ ./show_mmaps_pie
 7f621ffbb000-7f6220176000 r-xp 00000000 00:02 5192        /lib/x86_64-linux-gnu/libc.so.6
 7f6220176000-7f6220376000 ---p 001bb000 00:02 5192        /lib/x86_64-linux-gnu/libc.so.6
 7f6220376000-7f622037a000 r--p 001bb000 00:02 5192        /lib/x86_64-linux-gnu/libc.so.6
 7f622037a000-7f622037c000 rw-p 001bf000 00:02 5192        /lib/x86_64-linux-gnu/libc.so.6
 7f622037c000-7f6220381000 rw-p 00000000 00:00 0
 7f6220381000-7f62203a4000 r-xp 00000000 00:02 4917        /lib64/ld-linux-x86-64.so.2
 7f622059c000-7f622059d000 rw-p 00000000 00:00 0
 7f622059d000-7f622059e000 r-xp 00000000 00:00 0
 7f622059e000-7f62205a3000 rw-p 00000000 00:00 0
 7f62205a3000-7f62205a4000 r--p 00022000 00:02 4917        /lib64/ld-linux-x86-64.so.2
 7f62205a4000-7f62205a5000 rw-p 00023000 00:02 4917        /lib64/ld-linux-x86-64.so.2
 7f62205a5000-7f62205a6000 rw-p 00000000 00:00 0
 7f62205a6000-7f62205a7000 r-xp 00000000 00:02 4896        /tmp/show_mmaps_pie
 7f62207a6000-7f62207a7000 r--p 00000000 00:02 4896        /tmp/show_mmaps_pie
 7f62207a7000-7f62207a8000 rw-p 00001000 00:02 4896        /tmp/show_mmaps_pie
 7fff47e15000-7fff47e36000 rw-p 00000000 00:00 0           [stack]
 7fff47e63000-7fff47e65000 r--p 00000000 00:00 0           [vvar]
 7fff47e65000-7fff47e67000 r-xp 00000000 00:00 0           [vdso]
 ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0   [vsyscall]
 $

Running the same test program with the patched kernel, you should see something like:

 $ ./show_mmaps_pie
 54859ccd6000-54859ccd7000 r-xp 00000000 00:02 4896         /tmp/show_mmaps_pie
 54859ced6000-54859ced7000 r--p 00000000 00:02 4896         /tmp/show_mmaps_pie
 54859ced7000-54859ced8000 rw-p 00001000 00:02 4896         /tmp/show_mmaps_pie
 7f75be764000-7f75be91f000 r-xp 00000000 00:02 5192         /lib/x86_64-linux-gnu/libc.so.6
 7f75be91f000-7f75beb1f000 ---p 001bb000 00:02 5192         /lib/x86_64-linux-gnu/libc.so.6
 7f75beb1f000-7f75beb23000 r--p 001bb000 00:02 5192         /lib/x86_64-linux-gnu/libc.so.6
 7f75beb23000-7f75beb25000 rw-p 001bf000 00:02 5192         /lib/x86_64-linux-gnu/libc.so.6
 7f75beb25000-7f75beb2a000 rw-p 00000000 00:00 0
 7f75beb2a000-7f75beb4d000 r-xp 00000000 00:02 4917         /lib64/ld-linux-x86-64.so.2
 7f75bed45000-7f75bed46000 rw-p 00000000 00:00 0
 7f75bed46000-7f75bed47000 r-xp 00000000 00:00 0
 7f75bed47000-7f75bed4c000 rw-p 00000000 00:00 0
 7f75bed4c000-7f75bed4d000 r--p 00022000 00:02 4917         /lib64/ld-linux-x86-64.so.2
 7f75bed4d000-7f75bed4e000 rw-p 00023000 00:02 4917         /lib64/ld-linux-x86-64.so.2
 7f75bed4e000-7f75bed4f000 rw-p 00000000 00:00 0
 7fffb3741000-7fffb3762000 rw-p 00000000 00:00 0            [stack]
 7fffb377b000-7fffb377d000 r--p 00000000 00:00 0            [vvar]
 7fffb377d000-7fffb377f000 r-xp 00000000 00:00 0            [vdso]
 ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0    [vsyscall]
 $
  Contact us Home