Rating:

# Scribbles

## Problem

```php
hash_hmac('md5', $payload, FLAG),
'payload' => $payload,
]);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1" . $_SERVER['REQUEST_URI'] . "?action=log");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

echo curl_exec($ch);

} else {

if (hash_hmac('md5', $_POST['payload'], FLAG) !== $_POST['signature']) {
echo 'FAIL';
exit;
}

parse_str($_POST['payload'], $payload);

$target = 'files/' . time() . '.' . substr($payload['name'], -20);
$contents = $payload['data'];
$decoded = base64_decode($contents);
$ext = 'raw';

if (isset($payload['ext'])) {
$ext = (
( $payload['ext'] == 'j' ) ? 'jpg' :
( $payload['ext'] == 'p' ) ? 'php' :
( $payload['ext'] == 'r' ) ? 'raw' : 'file'
);
}

if ($decoded !== '') {
$contents = $decoded;
$target .= '.' . $ext;
}

if (strlen($contents) > 37) {
echo 'FAIL';
exit;
}

file_put_contents($target, $contents);

echo 'OK';
}
```

If we request without action parameter, it will construct post payload and send request to self(with action parameter) by curl.

The `hash_hmac` key is `FLAG`, but we don't know the content.

So we can't directly forge the signature.

## Exploit

The vulnerability is on `$payload = "data=$data&name=$name";`

We can't control `$name` variable, but we can use `$data` to control `$name`

Like this: set `$data`: `xxx&name=new_name%00`

The NULL byte will truncate the original name.

Now we can control the file name.

We want to write a webshell and execute it.

But if `$decoded !== ''`, it will append extension to the filename.

So we need to find a way to set `$decoded` empty.

And we know that php's `base64_decode()` will output empty string if its input doesn't contain any valid character.
(valid character include `a-z`, `A-Z`, `0-9`, `+`, `/`, ...)

Our goal is writing a non valid character webshell and the length shold be less than 38.

There are some tips, we can use some arithmetic operation like `XOR`, `NOT`, `AND`, ... to construct the php code.

So if we set data to ``` _`;%26name%3Dz.php%00```

`~%9c%9e%8b` is `cat`

so the payload will cat everthing in `../`, then write to `_`.

After we run the `files/time().z.php`, we can get the content of `config.php` in the `files/_`

## Flag

config.php:

```php

Original writeup (https://github.com/w181496/CTF/tree/master/dctf2018-final/Scribbles).