BHack 2022 - B64 - PHP Arbitrary Object Instantiation

This web challenge was a simple application with Base64 encoding and decoding functionality.

Both actions were handled by the same endpoint, run.php, and the only difference was a single parameter in the request body.

When I changed the func parameter to a random string, the application returned an HTTP 500 error.

Exploit

Based on the parameter names, I guessed that the server was instantiating a class from user input and then calling a method from the func parameter, passing input as the argument, something more or less the following code snippet:

$class = new $_POST['class'];
$func = $_POST['func'];
$param = $_POST['input'];
$ret = $class->$func($param);

Since I'm not a PHP expert so this snippet was only my guess about how the application worked. These Stack Overflow threads helped confirm that the idea made sense:

To test the theory, I looked for built-in PHP 8.1.8 classes and found DateTime with the getTimestamp() method, which returns the current timestamp. I used that in the request, and it worked.

At that point, I knew I had understood the application flow even without source code and with only limited PHP knowledge.

From there, I only needed a class and method that would let me read the flag stored at /flag on the server. I first tried SplFileObject with __construct() so I could instantiate it with /flag and read the file contents. That attempt was blocked by the application's filter.

While reading the PHP documentation, I noticed the parent class SplFileInfo. It looked promising, so I tried it instead. That worked: I could bypass the filter and call getFileInfo(), which returned the file name, as shown below.

After a bit more research, I found the final exploit: use openFile() to read the flag from the remote server.

I really enjoyed this challenge because it taught me a useful PHP trick and forced me to reason about the backend behavior without source code. Special thanks to @celesian for sharing the excellent paper "Exploiting Arbitrary Object Instantiations in PHP without Custom Classes".

BHackPHP