daveho/EasySandbox

__libc_start_main can be overrided without `-nostdlib` option

virusdefender opened this issue · 2 comments

As is described in the document

 long as gcc/g++ is invoked without the -nostdlib option, any attempt by the untrusted code to define an entry point (_start function) will result in a linker error, because the name _start will conflict with the real _start function defined in crt1.o

However, as I tested, there is no linker error.

#define _BSD_SOURCE // readlink
#include <dlfcn.h>
#include <stdlib.h> // exit
#include <string.h> // strstr, memset
#include <link.h>   // ElfW
#include <errno.h>  // EPERM
#include <unistd.h> // readlink
#include <seccomp.h>
#include <stdio.h>
typedef int (*main_t)(int, char **, char **);

#ifndef __unbounded
# define __unbounded
#endif

int __libc_start_main(main_t main, int argc, 
    char *__unbounded *__unbounded ubp_av,
    ElfW(auxv_t) *__unbounded auxvec,
    __typeof (main) init,
    void (*fini) (void),
    void (*rtld_fini) (void), void *__unbounded
    stack_end)
{

    int i;
    ssize_t len;
    void *libc;
    int (*libc_start_main)(main_t main,
        int,
        char *__unbounded *__unbounded,
        ElfW(auxv_t) *,
        __typeof (main),
        void (*fini) (void),
        void (*rtld_fini) (void),
        void *__unbounded stack_end);

    // Get __libc_start_main entry point
    libc = dlopen("libc.so.6", RTLD_LOCAL  | RTLD_LAZY);
    if (!libc) {
        exit(1);
    }

    libc_start_main = dlsym(libc, "__libc_start_main");
    if (!libc_start_main) {
        exit(2);
    }
    printf("Hijacked\n");    
    return ((*libc_start_main)(main, argc, ubp_av, auxvec,
                 init, fini, rtld_fini, stack_end));
}

int main()
{
    printf("Heloo world");
    return 0;
}
gcc 1.c -ldl -o test && ./test

gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)

Although run this code with EasySandbox will get a segment fault, I think it maybe an way to bypass sandbox.

Maybe we can disable -ldl option to prevent using dlopen function.

I will update the documentation to emphasize that linking with -ldl allows the application to bypass the sandbox. Thanks for the catch!

I think in general it is assumed that EasySandbox will only be used for executables where the compilation is controlled.

I updated the README to advise against allowing untrusted code to link with -ldl.