Unrestricted File Upload In PHP

IndominusByte
5 min readDec 27, 2019

--

Photo by Drew Coffman on Unsplash

Why File Upload Forms are a Major Security Threat?

Allowing file uploads by end-users, especially if done without a full understanding of the risks associated with it, is akin to opening the floodgates for server compromise. Naturally, despite the security concerns surrounding the ability for end-users to upload files, it is an increasingly common requirement in modern web applications.
File uploads carry a significant risk that not many are aware of, or how to mitigate against abuses. Worst still, several web applications contain insecure, unrestricted file upload mechanisms.

No Validation

A simple file upload form typically consists of an HTML form that is presented to the client and a server-side script that processes the file being uploaded. The following example contains such an HTML form and a server-side script written in PHP.

When the PHP interpreter receives an HTTP POST method request of the multipart/form-data encoding type, the script will create a temporary file with a random name in a temporary directory on the server, for example, /var/tmp/php6yXOVs/. The PHP interpreter will also populate the global array $_FILES with the information about the uploaded file as follows.

  • $_FILES[‘uploadedfile’][‘name’]: The original name of the file on the client machine
  • $_FILES[‘uploadedfile’][‘type’]: The mime type of the file
  • $_FILES[‘uploadedfile’][‘size’]: The size of the file in bytes
  • $_FILES[‘uploadedfile’][‘tmp_name’]: The temporary

the filename in which the uploaded file was stored on the server
The move_uploaded_file() PHP function will move the temporary file to a location provided by the user. In this case, the destination is below the server root. Therefore the files can be accessed using a URL such as http://www.example.com/uploads/uploadedfile.txt/.
In this simple example, no restrictions are imposed by the server-side script on what file types are allowed to be uploaded to the server. To such an extent, an attacker could easily upload a malicious PHP that could lead to server compromise.

Filter Input

  • Blacklisting

Another weak validation method that is widely used in file upload forms is to use a blacklist of types of files that have dangerous extensions. Upload forms using this mechanism would check the extension of the file that is being uploaded and compare its file extension to a list of extensions that the application considers harmful.
While this could be somewhat effective against some file types, the choice of employing a blacklist is a poor one since practically impossible to compile a list of all possible file extensions that an attacker could abuse use, especially if the application is running within an environment that allows a large number of scripting languages, such as Perl, Python, Ruby, and others — the list is endless. For example, the attacker may change the letters in the extension to their capital forms (.phP, .PhP, .pHP) or such as: pht, phpt, phtml, php3,php4,php5,php6. A whitelisting approach in this use case is by far more effective.

One possible way an attacker could bypass a file extension blacklist on an Apache HTTP Server is to first upload a .htaccess file with the following contents.

AddType application/x-httpd-php .png

The above configuration would instruct the Apache HTTP Server to execute PNG images as though they were PHP scripts. An attacker would then proceed to upload a file with a .png extension (a file extension that is presumably allowed), which could contain PHP code instead of an image and this would allow for code execution.

The screenshot below shows an HTTP request to a PNG file that contains PHP code that invokes the phpinfo() function.

  • Content-type / MIME-type Validation

A common mistake made when securing file upload forms is to only check the MIME-type returned by the application runtime. For example, with PHP, when a file is uploaded to the server, PHP will set the variable $_FILES[‘uploadedfile’][‘type’] to the MIME-type provided by the web client.
Since an attacker could easily control the MIME-type by sending the server a crafted HTTP POST request, such validation is trivial for an attacker to bypass. To such an extent, an attacker could easily upload a malicious PHP file with an allowed MIME-type that could lead to server compromise.

  • Whitelisting

Whitelist example

Filtering with whitelist means that the app only allowed for image/png type.

Bypassing Content-type (MIME-type) using burp suite we can intercept HTTP requests with burp suite and we can edit requests.

  • Content length Validation

Not allow file size greater than 10 bytes

Bypassing: remember we can upload RCE in this case with 8 bytes for Linux

<?=‘ls’;

Note : <? work for “short_open_tag=On” in php.ini ( Default=On )

  • Checking the Image Header

When image upload only is allowed, most web applications usually validate the image header by using a server-side function such as getimagesize() in PHP. When called, this function will return the size of an image. If the file is not a valid image, meaning that the file header is not that of an image, the function will return FALSE. Therefore, several web applications typically check if the function returns TRUE or FALSE and validate the uploaded file using this information.
If an attacker attempts to upload a simple PHP shell embedded in a JPEG file, the function will return false, effectively stopping the attack. However, even this approach can be easily bypassed using add magic number to our PHP file.

Magic number :

Header reference : [List of file signatures — Wikipedia]

Example :
I'm using bless editor in Linux we can add a header on file PHP by using add fake header png.

And voila we can bypass getimagesize() on PHP

References:

--

--