Exploit-DB #23171
Description: MPG123 0.59 - Remote File Play Heap Corruption
Type: remote
Platform: linux
Date: 2003-09-23
Author: V9

Exploit:
// source: https://www.securityfocus.com/bid/8680/info

A problem in the handling of some types of remote files has been reported in mpg123. Because of this, it may be possible for a remote attacker to execute arbitrary code with the privileges of the mpg123 user. 

/*[ mpg123[v0.59r,v0.59s]: remote client-side heap corruption exploit. ]*
 *                                                                      *
 * by: vade79/v9 v9@fakehalo.deadpig.org (fakehalo/realhalo)            *
 *                                                                      *
 * Url:                                                                 *
 *  http://www.mpg123.de                                                *
 *                                                                      *
 * Mpg123, versions 0.59r and pre0.59s(current) contain a remotely      *
 * exploitable heap based buffer overflow.  The overflow occurs when    *
 * the function readstring(), defined in httpget.c, does not properly   *
 * limit the amount of data written to a buffer. (*request)             *
 *                                                                      *
 * The vulnerable function is used when reading strings from remote     *
 * hosts, such as http audio streaming services.  The function is only  *
 * used in conjunction with writing to the *request buffer, which is    *
 * malloc'd into 1024 bytes.                                            *
 *                                                                      *
 * This function will continue reading into the *request buffer, byte   *
 * by byte, until a '\n' is read.  The function has a "maximum value to *
 * write" argument passed to it, ie. readstring(char *string, int       *
 * maxlen, FILE *f), but does not use it at all. (except for the old,   *
 * commented out, unused code)                                          *
 *                                                                      *
 * This exploit takes advantage of the vulnerability by using the       *
 * unlink() malloc chunk manipulation method.  This will require exact  *
 * addresses for use with the exploit.  You can find out how to get the *
 * addresses needed in the define comments or by viewing the help       *
 * screen(this will still not get you the exact offset, test to find    *
 * it; use the "-+" argument).                                          *
 *                                                                      *
 * Usage:                                                               *
 *  # cc xmpg123.c -o xmpg123                                           *
 *  # ./xmpg123 [-sgr+tl] -p port                                       *
 *                                                                      *
 * Exploit workings:                                                    *
 *  client connects:                                                    *
 *   /usr/bin/mpg123 http://www.host-running-xmpg123.com:port           *
 *  www.host-running-xmpg123.com sends:                                 *
 *   <64 byte filler><shellcode>...<* filler>|<16 byte malloc chunk>    *
 *   Where '|' is the 1024 byte boundary, followed by the 4*4=16        *
 *   byte fake malloc chunk.                                            *
 *                                                                      *
 * The bug itself(mpg123/httpget.c):                                    *
 *  void readstring (char *string, int maxlen, FILE *f)                 *
 *  {                                                                   *
 *  #if 0                                                               *
 *          char *result;                                               *
 *  #endif                                                              *
 *          int pos = 0;                                                *
 *                                                                      *
 *          while(1) {                                                  *
 *                  if( read(fileno(f),string+pos,1) == 1) {            *
 *                          pos++;                                      *
 *                          if(string[pos-1] == '\n') {                 *
 *                                  string[pos] = 0;                    *
 *                                  break;                              *
 *                          }                                           *
 *                  }                                                   *
 *                  else if(errno != EINTR) {                           *
 *                          fprintf (stderr, "Error reading from socke$ *
 *                          exit(1);                                    *
 *                  }                                                   *
 *          }                                                           *
 *  #if 0                                                               *
 *          do {                                                        *
 *                  result = fgets(string, maxlen, f);                  *
 *          } while (!result  && errno == EINTR);                       *
 *          if (!result) {                                              *
 *                  fprintf (stderr, "Error reading from socket or une$ *
 *          }                                                           *
 *  #endif                                                              *
 *                                                                      *
 *  }                                                                   *
 *                                                                      *
 * Source quick fix:                                                    *
 *  -while(1) {                                                         *
 *  +while(maxlen>pos) {