File Uploads¶
- https://tryhackme.com/room/uploadvulns
- https://portswigger.net/web-security/file-upload
- https://portswigger.net/web-security/file-path-traversal
Methodology¶
Check with gobuster dir --url http://host.com -w /usr/share/seclists/Discovery/Web-Content/common.txt
what directories exists.
Check with echo http://host.com | httpx -tech-detect -title -status-code -path /,/login
what technology the sub/site is using.
Upload an allowed file and catch request/response with ZAProxy/Burp.
Frontend filtering¶
Nowadays modern web applications tend to check file uploads on the client side via javascript and html-annotations before they are sent to the server. Because javascript is executed on the clientside it's quite easy to omit it completely or catch the required data for the upload-request and issue it ourself.
If the web application requires javascript use Burp/ZAProxy to modify the responded javascript to allow all file/mime types and disable all security checks to ease your pentester life.
Frontend filtering might check for file -name, -size, mimetype, modification date and -content.
Backend filtering¶
Once the file is sent to the server a backend filter might be applied.
Backend filtering might check for file -name, -size, mimetype and -content. Be aware that these checks might apply to multiple files in a single request. Depending on the filesize the request might span over multiple multi-part requests.
What to check for¶
Things you should check for:
* storage location of the uploaded file
* simple websites will run on a single server and thus, store the files on the same server as the website is served from.
* check if the uploaded file is stored in an (public) accessible folder.
* filename uniqueness
* the server has to give the stored file a name.
* check if the name of the uploaded file is modified (added timestamp or guid) or if it will replace/overwrite an existing file.
* filename path
* the server will form the storage path of the file by combining the storage folder with the filename.
* check what happens if the filename contains ../../file.ext
. also check what happens if the value is encoded.
* you can sometimes bypass this kind of sanitization by url encoding, or even double url encoding, the ../
characters, resulting in %2e%2e%2f
or %252e%252e%252f
respectively. various non-standard encodings, such as ..%c0%af
or ..%ef%bc%8f
, may also do the trick.
* filename with null-byte
* the null-byte \00
in a string has a special meaning and lead to various vulnerabilities. in php <= 4 it was possible to bypass extension filtering by sending a filename of shell.php\00.jpg
which resulted in a valid state but the stored file was shell.php
.
* check what happens if the filename contains a null-byte \00
, %00
, maybe double-encoded \2500
, %2500
.
* file extension enforcement
* the file upload will contain the mimetype (eg. image/jpeg
) of the file as well as the file extension (eg. .jpg
). Modify the mimetype and/or extension and see if the server is enforcing one of them.
* Example: Upload of dog.jpg
with image/jpeg
. Does the server change the extension to .zip if the mimetype is changed to application/x-zip-compressed
?
* double file extensions
* sometimes the server will only check if a file extension like .png
exists in the filename.
* check if the upload is valid if you name the file shell.png.php
.
* filename, extension and mimetype cASiNg
* the filename and extension might be blacklist-checked with lowercase values.
* check if you can circumvent the filtering by changing the casing of the values.
* other allowed file extensions / mimetypes
* files might have multiple extensions of the same mime-type.
* php for example might have .php
, .phtml
, .php3
, .php4
, .php5
, .php7
, .phps
, .php-s
, .pht
and .phar
.
* jpg might have .jpg
and .jpeg
.
* mimetypes N-1 extension (99%)
* see this gist of mimetype-to-extension table.
* check if you can change the file extension / mimetype to an legal replacement.
* magic strings
* the mimetype can be determined by checking for magic strings that each file will contain to support appications - like zip-header in a zip-file or ms-word header in a docx file. See https://www.filesignatures.net/index.php?search=png&mode=EXT for a complete list of file signatures / magic values for all known files.
* modify the file with hexeditor -b <file>
, insert new bytes with ctrl-a
, write over the new bytes and save/exit like in nano
. Confirm the change by issuing file <file>
to see if the edit was successful.
* check if you can upload a shell.php
but with the header of a png file 89 50 4E 47 0D 0A 1A 0A
and the mimetype set to image/png
.
Dangerous uploads¶
These uploads might consume all resources the server has available which will result in a DOS attack.
- Zip Bomb
- This zip file with a size of a few kilobyte to megabyte will expand into gigabytes to petabytes and thus will fill the working memory and/or physical storage.
- 50k Gigapixel Image
- This png image with a size of 5.8 megabytes will expand to 141 gigabytes when processed.
- Endless file upload
- In case you can give a server an url to upload, a custom server implemenation could offer a file that will never end. For that the server should avoid sending the content-length.
WebShell, ReverseShell¶
- A webshell is a website written in a language which is understood by the webserver. Like a
shell.php
on a PHP-Server. This webshell is not the same as a reverse shell as you can only communicate via the uploaded file with the server, but in a shell setting. Be aware that all the communication might be logged in the server-logs -> send the requests per POST!<?php echo system($_REQUEST['cmd']); ?>
is a valid php shell and can be used likehttp://target.com/shell.php?cmd=id;whoami;ls
. Ensure to use theview-source:...
to ease the reading of the result.<?php echo "<pre>" . shell_exec($_GET["cmd"]) . "</pre>"; ?>
is using the<pre>
tag to ease the output on the page.- Other variants are:
echo `whoami`
,echo shell_exec("whoami")
,passthru
- With the use of a webshell a reverseshell could be established. Send the reverse shell command url encoded.
- A reverseshell is a script written in a language the (web)server understands. It might by a php script if executed by the php server or a bash-script for a cron job. The biggest difference is that the victim-server will call the attacker-server which means the victim-server will hold information about the attacker!
- See ReverseShells for more information.