Sunday, November 6, 2016

svattt 2016 web 100 ctf

source code:
    function checksig($filename, $timestamp, $sig, $secretkey)
    {
        $realsig = substr(md5($filename.$timestamp.$secretkey),0,16);
        if ($sig == $realsig)
        {
            $filename = './'.str_replace('/','',$filename);
            readfile($filename);
            die(0);
        }
        echo "Invalid Signature!";
    }

$secretkey = "XXXXXXXXXXXXXXXXXXXXXXXXX";//This is not real $secretkey, ignore it !!!
echo "
    Web100
   
   
Dare to read flag.php???

    Click me

    ";
if (isset($_GET['filename'])&&isset($_GET['sig'])&&isset($_GET['timestamp']))
    {
        checksig($_GET['filename'],$_GET['timestamp'],$_GET['sig'], $secretkey);
        die(0);
    }
echo "Something's missing!!";
echo "";
?>
This task is exploited based on the PHP operator and expected Behavior of PHP equal to operator.
take a look at function checksig. In this function, there is a comparison
 if ($sig == $realsig)

$sig is a signature that we send to server and $realsig is the calculated signature. Server will compare 2 values to decide whether or not the signature is correct. 
Since the coder use the operator == to compare 2 strings, we can exploit it via the way php performs the comparison operand. When using this operator (==), the comparison will be performed based on the active types of the operands. If the operands are strings or nulls, they are compared as strings, if eithers is a Boolean, they are converted to Boolean values and compared, and otherwise they are converted to numbers and compared. [Advanced PHP programming - George Schlossnagle]

let's take an example "0e1" ==  "0". This operand will return True even the two strings are different.
in this case, with the left side, "0e1", php considers it as a scientific notation, and treats it as 0*10^1 = 0 first, then the right side also will be converted form "0"(string) to 0 (number) (since the left side is considered as a number). from now, php will compare these 2 numbers and return the true result.

Then, we just pass the filename argument as "flag.php", sig=0 and the value of timestamp will be varied until we get the flag (when the real calculated signature contains "0exx" (xx must be the number) at the beginning.

No comments:

Post a Comment