Rating: 1.0

Exzendtential-crisis
--------
We are given a [site](http://d4a386ad.quals2018.oooverflow.io/) with two forms in the homepage: one to register an account, and one to login to an account. There is also a "debug me" link that shows the source code of the page.

Once we register an account, we can write an essay on the page `essays.php`. This page lists all the essays that the user wrote, and provides a preview. Appending `?source` to the url shows the page source (as in index.php). There is an obvious file disclosure:

```php
if (isset($_GET['preview']))
{
$dirname = "upload/${_SESSION['userid']}/";
$fname = $_GET['name'];

if (check_fname($fname) === False)
{
header("Location: /essays.php");
exit();
}
$content = file_get_contents($dirname . $fname, False, NULL, 0, 524288);
echo "<h1>Your essay submission</h1>";
echo "

";
echo $content;
echo "
";
echo "
";
echo "back";
exit();
}
```

There is also a `flag.php` file, that only says:
```
Only sarte knows the flag. You are not him. Enjoy a quote though:
One love, a career, a revolution, as many companies as we begin ignoring their outcome
```

Retrieving `php.ini` with the file disclousure shows that there is a custom module in the PHP installation, called `mydb.so`. With the file disclousure we downloaded the module, and then we started reversing it.

After reversing the module, we find that it exports 3 functions to PHP: `create_user`, `get_result` (both used in `register.php`), and `check_credentials` (used in `login.php`).
Internally, the module uses SQLite for storing user credentials, without validating the input (this is done on the PHP-side).
After looking a bit, we found an out-of-bounds write vulnerability that we can use to inject arbitrary SQL into a query.
In `check_credentials`, the module first retrieves the function arguments, and then calls `get_user_id` in order to verify the username/password. It passes to it a callback function, `check_hacking_attempt`, that takes two buffers, one containing the username, and one to copy the username to. It does some security checks before sending a query to SQLite. `check_hacking_attempt` copies the username string to the destination buffer, as long as its length is less than 150 characters. However, the destination buffer resides in the stack frame of `get_user_id`, which only allocated 112 bytes for it. Therefore, there is a 38 byte overflow.

In `get_user_id`, the destination buffer is located just before a table name buffer, which contains the name of the table used in the user selection query. By overwriting the table name, we can inject arbitrary SQL into the query. The injection that we choose is pretty trivial: `users where username="sarte" -- `.

The final payload is generated by the Python snippet `print('a' * 112 + 'users where username="sarte" -- ')`, that once inserted as username in the login, authenticates us as `sarte`. We can now retrieve the flag.

Original writeup (https://mhackeroni.it/archive/2018/05/20/defconctfquals-2018-all-writeups.html#exzendtential-crisis).