RenewSSP
(Renew Stack Smashing Protector)
renewssp
Prevent SSP Brute Force Attacks

Do not be left behind in the race of security, particularly in network applications that are exposed to the wild.

Tutorial

The RenewSSP relies on the already existing SSP infrastructure, and so, only minor modifications are needed in the system. It can be implemented in several ways:

  1. Modify the source program of your application to explicitly change (renew) the reference canary at key places. This would be the preferred way for application developers.
  2. Extend the functionality of the clone() system call with a new flag (CLONE_RENEWSSP) which renews the reference canary on children processes. This shall be the way to provide the RenewSSP as a standard service from system API.
  3. Override the fork() function of the C library, using the LD_PRELOAD facility, with a modified version of it which replaces the canary. This is the quickest and easiest way of using the RenewSSP.

The last solution provides a way of using the RenewSSP that is transparent to users and applications. In just a few seconds, you can give it a try.


Simple example of using RenewSSP

This PoC shows how the renewSSP works. The following example prints the canary values of the process and its child, in both with the standard SSP and with the renewSSP.

  1. Download and compile the code of the tiny library which overrides the fork() function: renewSSP.tgz.
    $ wget http://hmarco.org/renewssp/download/renewSSP.tgz
    $ tar xvf renewSSP.tgz
    renewSSP/
    renewSSP/librenewssp.c
    renewSSP/Makefile
    renewSSP/test_renewssp.c
    $ cd renewSSP
    $ make
    gcc -O2 test_renewssp.c -o test_renewssp 
    gcc -O2 -fno-stack-protector -shared -fPIC -o librenewssp.so librenewssp.c -ldl
    
    There will be two ELF files: test_renewssp and librenewssp.so.
    Note that test_renewssp do not depends on renewSSP. We can check this by executing ldd linux utility:
    $ ldd ./test_renewssp
    linux-vdso.so.1 =>  (0x00007fff241fe000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f52fbd2a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f52fc10e000)
    
  2. The test_renewssp just prints the value of the canary at the beginning and after creating a child process.
    $ ./test_renewssp 
    Canary before fork():           0xc5dff361e98fe700
    Reference-canary of the parent: 0xc5dff361e98fe700
    Reference-canary of the child:  0xc5dff361e98fe700
    
    As expected, the parent and its child have (share) the same canary value.
  3. Now, we will execute the same program but with the renewSSP. To achieve that, we only need to preload the librenewssp.so library:
    $ LD_PRELOAD=./librenewssp.so ./test_renewssp 
    Canary before fork():           0x20f9625237f42200
    Reference-canary of the parent: 0x20f9625237f42200
    Reference-canary of the child:  0xe954ae35970ba300
    
    As can be seen, the child process has a different reference canary and it exits normally.

Using Apache2 web server with RenewSSP

  1. Install the Apache2 server with pre-forking (in Ubuntu/Debian it is the apache2-mpm-prefork package).
    $ sudo apt-get install apache2-mpm-prefork
        
  2. Download and compile the tool canarydump_x86_64 to inspect canaries:
    $ cd ~
    $ wget http://hmarco.org/renewssp/download/canaryDump64.tgz
    $ tar xvf canaryDump64.tgz
    canaryDump64/
    canaryDump64/Makefile
    canaryDump64/canarydump_x86_64.c
    $ cd canaryDump64/
    $ make
    gcc canarydump_x86_64.c -o canarydump_x86_64 -m64
    
    This tool prints the value of the reference canary of the process whose PID is passed as parameter.
  3. Inspect the reference-canaries of the apache2 processes:
    $ for pid in `pidof apache2`; do sudo ./canarydump_x86_64 ${pid}; done
    Canary: [0x6fa5c4a7d4a1ba00] Pid [21946] /usr/sbin/apache2
    Canary: [0x6fa5c4a7d4a1ba00] Pid [21945] /usr/sbin/apache2
    Canary: [0x6fa5c4a7d4a1ba00] Pid [21942] /usr/sbin/apache2
    
    All the apache processes have the same reference canary value (0x6fa5c4a7d4a1ba00).
  4. Download, compile and install renewssp:
    $ cd ~
    $ wget  http://hmarco.org/renewssp/download/renewSSP.tgz
    $ tar xvf renewSSP.tgz
    renewSSP/
    renewSSP/librenewssp.c
    renewSSP/Makefile
    renewSSP/test_renewssp.c
    $ cd renewSSP
    $ make
    gcc -O2 test_renewssp.c -o test_renewssp 
    gcc -O2 -fno-stack-protector -shared -fPIC -o librenewssp.so librenewssp.c -ldl
    $ sudo cp librenewssp.so /lib/
    
  5. Configure the Apache2 launching script to use RenewSSP:
    $ sudo sed -i 's/APACHE2CTL="$ENV/RENEWSSP="LD_PRELOAD=\/lib\/librenewssp.so"\
    APACHE2CTL="$ENV $RENEWSSP/g' /etc/init.d/apache2
    $ sudo service apache2 restart
    $ cd ~/canaryDump64/
    $ for pid in `pidof apache2`; do sudo ./canarydump_x86_64 ${pid}; done
    Canary: [0xee735adece8cfc00] Pid [23402] /usr/sbin/apache2
    Canary: [0x04e6609d9707ec00] Pid [23401] /usr/sbin/apache2
    Canary: [0x4e84ad51a92f9100] Pid [23398] /usr/sbin/apache2
    

    Note that the default configuration of the pre-forked Apache2 is to launch two working servers. As showed in the previous output, every child process has a different reference canary and the apache web server works accordingly.

    Now you can test the Apache2 using the ab (Apache Benchmark) utility. Our results show that the time per request (across all concurrent requests) is the same in both cases. In order to avoid network interference, we ran the benchmark in the same computer than the Apache2 server.

    There is no significant performance difference between the standard SSP and the RenewSSP.