Htaccess, or how to bypass file upload mechanisms.

📂 How to bypass file upload mechanisms?
Introduction
A file upload vulnerability is a security flaw that allows an attacker to upload a malicious file to a target system. This malicious file can then be used to execute arbitrary code, steal data, or cause other damage.
There are multiple ways to bypass file upload mechanisms. This article is inspired by the l33t-hoster challenge from Insomni’hack Teaser 2019 CTF.
So, follow the guide!
Example of vulnerable code
The objective of the challenge was to execute commands on the remote server using the file upload functionality. However, this feature seems well-protected.
The source code of the page is provided below.
|
|
The web page rendering is relatively simple:
To summarize the analysis of the security filters:
- The application checks the file extension. If the file ends with
.php
or something similar, it is rejected. - The application checks the file name. If the file name cannot be split into two parts with the
.php
separator, it is rejected. - The application checks the content. If the string
<?
is present in the content, the file is rejected. - The application checks the header. If the file is not an image, it is rejected.
- The application checks the size. If the height and width of the file are not equal to 1337, the file is rejected.
How to proceed?
Choosing the right file
In summary, it is not possible to upload files with the .php
extension. The goal is to obtain the ability to execute PHP code in a file other than .php
. For this, it is possible to use a .htaccess
file.
But what is a .htaccess
file?
A
.htaccess
file is a configuration file that allows you to modify the behavior of an Apache web server. It is usually located in the root directory of a website, but it can also be placed in subdirectories.
More details here: https://httpd.apache.org/docs/2.4/en/howto/htaccess.html
A .htaccess
file can have the following configuration:
|
|
- The first line indicates that we want to execute PHP using the
.php16
extension. - The second line indicates a specific encoding.
- The third line indicates if the file has a specific encoding.
- The fourth line indicates to display PHP errors (useful in our case).
This configuration file could allow command execution. However, during the upload, the application gives the following error:
lol filename is empty
By analyzing the code, it splits the string into two parts with .
and checks if there are indeed two parts. Therefore, you need to send a file name like ..htaccess
to bypass this filter.
Next error:
not an image.
Indeed, we are not uploading an image but a configuration file. We need to find a way to bypass the following code:
|
|
Creating a polyglot file
What is a polyglot file?
A polyglot file is a file that can be interpreted in multiple different languages. It is usually a binary file that contains data in multiple formats, such as code instructions, configuration data, or text data.
The first trick is to find a way to bypass the image checker. The PHP documentation provides a clue on how to proceed: http://php.net/manual/en/function.exif-imagetype.php
At the bottom of the page, a format seems interesting:
Ok, but what is an XBM file?
X BitMap, abbreviated XBM, is a monochrome digital image format originally designed for the X Window system, particularly for pointer and icon images.
The page contains an example:
|
|
The format of xbitmap
is quite clear. The size of the image is noted on the first lines of the file using a #
. This format, very close to the .htaccess
format, allows bypassing the exif_imagetype($tmp_name)
function of the program.
Here is the content of the new ..htaccess
file:
|
|
The file is correctly processed and uploaded to the server!
Bypassing anti-PHP protection
Another filter prevents the upload of PHP content by checking for the string <?
. However, it is possible to bypass this protection by encoding the payload.
Indeed, PHP supports multiple encoding formats. Currently, the basic writing is in utf-8, but PHP also supports utf-16 encoding.
In utf-8, a character is encoded on 1 byte.
|
|
However, in utf-16, the encoding is done on 2 bytes.
|
|
Here, a utf-16 Big Endian encoding was chosen. The first character <
will be written as 003c
in utf-16 instead of 3c
in utf-8. With this trick, the filter is bypassed.
Here is a small Python script to automate the creation of the payload.
|
|
All that’s left is to upload and enjoy your well-deserved webshell. Phew! 😂
Conclusion
It is complex to implement a completely secure file upload feature.
To protect against the bypasses used in this challenge, the developer could have implemented the following security measures:
- Use
ImageMagick
functions to verify files before uploading them. - Better verify the file extension.
- Prevent the interpretation of
.htaccess
files in the directory. - Install a WAF (Web Application Firewall) like Apache’s ModSecurity.
Remember! Never trust user inputs!