Math Quiz

Web - 150 Points

So I got this douchy classmate that thinks he’s super cool. He created a math quiz software for our class in 10 minutes, and claims its super secure with protections and everything. We all hate him, and if you hack his code, we’re gonna love you! By the way, he told a friend of mine that he keeps his secrets among the quiz questions, but those questions are never used in the software.

Writeup

Since we don’t have the source code or any indications of it, the first step is to try to cause the app to crash and give us error information.

The web application was so easy to crash that selecting the correct response will throw up this error message

Error 4: syntax error, unexpected '';' (T_ENCAPSED_AND_WHITESPACE) in /var/www/html/web/math-quiz/index.php(44) : eval()'d code on line 1

I was intercepting all the traffic with OWASP ZAP, so I find out there was an anchor in the error message that shows us the source code:

function filter($expression)
{
if (strpos($expression, ";")!==false) return null;
$allowed_functions=explode(",","abs,ceil,cos,floor,log,max,min,md5,pi,pow,rand,round,sin,sqrt,tan");
preg_match_all("/([a-z]+?)\s*\(/i", $expression, $matches);
if ($matches)
foreach ($matches[1] as $match)
if (!in_array($match, $allowed_functions))
return null;
return $expression.";";
}
function evaluate($question,$answer)
{
eval('$x='.filter($answer));
$res=" ".$question[0];
for ($i=1;$i<strlen($question);++$i)
{
if ($question[$i]=="X" and is_numeric($question[$i-1]))
$res.="*X";
else
$res.=$question[$i];
}
$res=preg_replace("/(\d+|X)\s*\^\s*(.*?)\s/", "pow($1,$2)", $res);
$res=str_replace("X", '$x', $res);

$question=filter($res);
if (!$question)
return null;
$question=str_replace("=", '==', $question);
if (verbose()) echo $question.PHP_EOL;
eval('$res='.$question);
return $res;
}
function format($expression)
{
$res="";
$mode=null;
for ($i=0;$i<strlen($expression);++$i)
{
$c=$expression[$i];
if ($mode=="power")
if ($c==" ")
$c="</sup> ";
if ($c=="^")
{
$c="<sup>";
$mode="power";
}
elseif ($c==" ")
$c="";
$res.=$c;
}
return $res;
}
if (isset($_POST['answer']))
{
$index=$_POST['index']*1;
$correct=(evaluate($question[$index],$_POST['answer']));

Anyway, selecting the answer create a new POST request to the server with the following parameters

index=4&index=4&answer=[...]&index=4&index=4

The challenge’s text says that the flag was stored with the questions and I was thinking that the index was the Questions index.

I’ve changed that to “0” only for “sport” and the flag popped out :D

This wasn’t the intended way to get the flag, but a flag is a flag ;)