File Upload

Target: to upload server side script files enabling RCE

Scope cause: Fails to validate properly, whether that be its size, type, contents,etc. Restrictions that are imposed on the file once it has been successfully uploaded allow for the file to be exectable (like .htaccess misconfigs allow for php, jsp execution) Cause: Improper restrictions implementation like flawed or bypassible filter validations. How server handles requests to static files? 1. parses the path in the request to identify the file extension 2. determine the type of the file being requested (comparing it to a list of preconfigured mappings between extensions and MIME types) 3. Depends if: 3.1 file type is non-executable -> contents to the client in an HTTP response 3.2 file type is executable + server is configured to execute files of this type -> assign variables based on the headers and parameters in the HTTP request before running the script. 3.3 file type is executable + server is not configured to execute files of this type -> error or file in plain text.

1. Upload restriction bypass

Exploiting unrestricted file uploads to deploy a web shell

Lab : APPRENTICE Remote code execution via web shell upload

Read Contents from /etc/passwd
<?php echo file_get_contents('/etc/passwd'); ?>

Execute Command (access file with parameter ?command=whoami)
<?php echo system($_GET['command']); ?>

Flawed file type validation of file uploads

validate and sanitize file upload flaws 1. The file upload functionality uses the content type multipart/form-data to send binary data. Within this content type, the message body is split into seperate parts for each of forms' inputs. For basic inputs information, Content-Disposition is suffitient, like for filename,etc. The parts responsible for the binary data transmission use Content-Type header to tell the MIME type of the data submitted to the server. Issue: The server may implicitly trust the Content-Type header to find the type of file being uploaded. With restrictions in place to upload Content-Types only of specific type or a whitelisted list. The attacker can bypass this filter by modifying the content-type to whitelisted one while uploading a forbidden file format. As the server only uses content-type to establish the type of the file. For instance, if only images are to be allowed, the server will analyze that the uploaded file has Content-Type like image/jpeg or image/png. Attacker uploads a php file while intercepting and changing the content-type to that of an image, and successfully uploads a php file.

2. Bypass script execution restrictions in user accessible dirs

Most likely the upload location will have much stricter controls over other locations on the server interms of allowing webshell executions. In this case, we try path traversal in the form-data parameters.

Web servers often use the filename field in multipart/form-data requests to determine the name and location where the file should be saved. Note: In some contexts, such as in a URL path or the filename parameter of a multipart/form-data request, web servers may strip any directory traversal sequences before passing your input to the application. 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.

Need to url encode directory paths Useful is intruder fuzzing-file upload

3. Dangerous file-types restrictions

1. Overwrite server configuration:

Files to target Apache restricts php execution to .php only /etc/apache2/apache2.conf // enable php module, consider .php files as x-httpd-php LoadModule php_module /usr/lib/apache2/modules/libphp.so AddType application/x-httpd-php .php Directory specific configurations configfiles in apache using .htaccess IIS servers using web.config This allows json to be served to users: <staticContent> <mimeMap fileExtension=".json" mimeType="application/json" /> </staticContent>

In case of .htaccess read here: The configuration directives found in a .htaccess file are applied to the directory in which the .htaccess file is found, and to all subdirectories thereof. However, it is important to also remember that there may have been .htaccess files in directories higher up. Directives are applied in the order that they are found. Therefore, a .htaccess file in a particular directory may override directives found in .htaccess files found higher up in the directory tree. And those, in turn, may have overridden directives found yet higher up, or in the main server configuration file itself. https://httpd.apache.org/docs/2.4/howto/htaccess.html#how https://github.com/phanan/htaccess pphp files are not allowed to upload. In this case, rather that solving the issue behind unability to upload php files, better to upload a randon extension ending and tell apache to treat that extension as php. This time, time our php code executes.

File Extension Blacklist bypass using obfuscation

Validation code could be case sensitive -> set for .php file won't block .pHp file Then if when the file is getting mapped to MIME type, the code is case insensitive, our .pHp sneaks past defense and is executable.

Obfuscation techniques Techniques for checks bypass:

  1. multiple extensions: interpreted as either a PHP file or JPG image: exploit.php.jpg

  2. Add trailing characters. Some components will strip or ignore trailing whitespaces, dots, and suchlike: exploit.php.

  3. URL encoding (or double URL encoding) for dots, forward slashes, and backward slashes: exploit%2Ephp (Not decoded at extension check, later when writing at server-side, is decoded)

  4. Add semicolons or URL-encoded null byte characters before the file extension:exploit.asp%00.jpg Checks using HLL, Backend LLL //file end discrepency Extension checks using HLL (PHP,Java) will consider as image, While writing to file, LLL (C/C++) Backend will treat as exploit.asp;.jpg , thereby writing our .asp file

  5. multibyte unicode characters (xC0 x2E, xC4 xAE or xC0 xAE) converted to null bytes (;) or dots (.) after unicode conversion or normalization (filename parsed as UTF-8 string beforce converted to ASCII before used in path) Converted to x2e

Defense should involve stripping or replacing dangerous extensions recursively before used in execution in anyform. If not recursively, strings can be positions in such way that first level filtering will be bypassed and post conversion, valid file extension will be left. For example: exploit.p.phphp -> first level filter will notice and delete .php leaving exploit.php anyways that is valid extension.

Bypass Validation of file contents

polyglot webshell.

Sophisticated defence doesn't trust the user controlled Content-Type parameter to establish the file type of the uploaded file. Instead, the uploaded file is analyzed at the backed to find the file type and then that intel is used to make sure only whitelisted file type is uploaded. For this, the intrinsic properties of whitelisted types are looked for in the uploaded file. The data (specific sequence of bytes identifying whitelisted types) used is looked in places like the header or footer. This data is like fingerprint/signatures of expected types. Used to compare/match content uploads to whitelisted types. For example, 1. JPEG file starts with the bytes FF D8 FF. 2. PHP will not have intrinsic properties of image like dimesions, hence polygrot won't be created using it, unlike a whitelisted JPEG file. Static File Analysis tools like ExifTool can easily detect mismatch.

Lab: (uploaded a php file with jpeg extension) upload failure tells file must be an image(Here, php extension is not blocked, only the file contents are checked to be an image, As uploaded a image with .php extension [test.php]). This means only focus on masquerading our php as an image. In other words a polyglot webshell. https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/hiding-webshell-backdoor-code-in-image-files/

Lab: Create a polyglot php ( basically a 2-in-1 file, that renders as a jpeg when opened as jpeg (extension jpeg) or a php when extension is php)

When uploaded with jpeg extension, rendered as a jpeg.
When uploaded with php extension, executes and reads the flag file

Last updated

Was this helpful?