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.phpon 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.