A Simple CTF walk-through( Hack.me )

eLearnSecurity hosts a sandbox website named “Hack.me”. This website is a great playground to sharpen skills in web application security. I tried few of their sandbox challenges and felt this simple CTF was quite cleverly built. It helped me speed up on simple PHP concepts. I’m going to start with the walkthrough for this challenge, I strongly suggest you to give this one a shot. You will need to know php concepts to get around this CTF, to be specific object serialization. I used BurpSuite as a proxy with chrome browser to solve this challenge.

Simple CTF by Light ( walk-through )

Note: You have to register @ hack.me website to get your own sandbox, and my sandbox URL shown in screenshots would have been destroyed by the time you are reading.

The portal suggested to try genflag.php as the URI to generate the flag and this seemed to be the end goal objective of the CTF.

genflagThe sandbox URI pointed to index.php page, which provided  two leads

  • A comment in view source “<!– feed it the “class name ” –>” in line 91
  • Input form with POST method, hidden with no border. Very sneaky! ..

viewsource

Fired up BurpSuite and wanted to check the name field, but what on earth is Class name?. The website indicated some liking towards cookies and the Set-cookie field in response contained “class” as a key. So sent this to the Burp decoder as it appears to be URL encoded. Decoding it revealed the following.

cookie“String” appears many times and it appears to be the class name. using the POST param as “name” and value as “String”. Got to the next stage, it pointed a HREF “final.php”

final

Hovering over the final.php page indicated to use ?array variable as input to PHP.

array

Adding URI “final.php?array”  pointed to “http://prnt.sc/cqsfq0&#8221; ie below screenshot.  phpss

In summary,   the snippet creates an object named CTF. internally creates a file using __wakeup and names it “param.txt” containing whatever is hidden (white gaps) with $param field. our goal is to identify the contents of $param. As this is serialized,  if we unserialize it by feeding the $obj to  array attribute in GET. It will write the content to param.txt and if successful response should be “Ahan!”.

unserializeAccessing the param.txt, it contained ?minion inside it. This is the value of $param.minion

?minon seems to be an another attribute for final.php andits functionality is to read files.

filereadI provided the input as param.txt,  it appears to replace the “txt” to “toixt” and “final.php” becomes “final”. So, after few attempts…(alot.. cough!!..) the following trick worked.-> “?minion=final.ph.PHPp” the middle “.PHP” becomes null and ends up creating “final.php”, bypassing the filter and now we have the source of final.php .. !!

finalp

Finally !!…reading the final.php!! and.. “minion” has a new agenda with method POST

&amp;amp;lt;?php

//Since you are this far in the challenge .. You gotta read everything carefully.. Best of luck ..
echo "

Welcome... We will meet again 🙂 

";
if(isset($_GET["array"])){

	echo "

http://prntscr.com/cqsfq0 

";
	class CTF{

		private $param = '?minion';
		private $file = "param.txt";

		public function createFIle($file,$write){

			fwrite(fopen($this->file,"a"),$this->param);

		}

		public function __wakeup(){

			$this->createFIle();
			echo "

Ahan!

";

		}}
$obj = new CTF;
$obj = serialize($obj);

$cmd = $_GET['array'];
if(preg_match('/shell_exec|system|passthru|exec|"\'/i', $cmd)){die("

 😉 

");}
if(strlen($cmd)>18 || strlen($cmd)<18 ){die("

You killed me 😥 

");}
$cmd = @eval($cmd);

echo $cmd;

}

$o="glob('*')";
$p="print_r(";
$f=".t";

if(isset($_GET['minion'])  ){

	$cmd = $_GET['minion'];
	$cmd = preg_replace('/.php/i', "", $cmd);
	$cmd = preg_replace('/.txt/i', ".toixt", $cmd);

	$cmd = str_replace('$f',"$f",$cmd);
	$cmd = readfile($cmd);

}

if(isset($_POST['minion']) ){
	$cmd = $_POST['minion'];

	if(strlen($cmd) > 9){die("noooooo! :");}
	$cmd = str_replace('$o',"$o",$cmd);
	$cmd = str_replace('$p',"$p",$cmd);
	echo "
";
	$readfile = $cmd;

	echo(@eval($readfile) );
}

?>

To print the array values using glob we need to formulate string print_r(glob(‘*’)); which is equivalent to $p$o);  and should be less than 9 characters and provided via POST method.

arrayfull

array [0] seems to be the flag, navigated to /327a6c4304ad5938eaf0efb6cc3e53dc.txt and it obtained a base64 string. This given as input  to genflag.php was the last step 🙂

flag

I have probably taken a long route to solve this challenge. But, trying this way helped me learn some concepts of PHP . I hope this was informative 🙂

thanks!,

Ramnath

 

Published by Ramnath Shenoy

I work a penetration tester and this blog is just some of my personal notes!

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: