RCE
Last updated
Was this helpful?
Last updated
Was this helpful?
The and wrappers depend on the PHP configuration allow_url_include
(disabled by default). The PHP config file is under:
/etc/php/X.Y/apache2/php.ini
for Apache
/etc/php/X.Y/fpm/php.ini
for Nginx
The can be used to include external data.
If the vulnerable function allows the inclusion of remote URLs, then we can also perform a attack, which allows for gaining RCE by including a malicious script that we host and enumerating local-only ports.
PHP
include()
/include_once()
✅
✅
✅
file_get_contents()
✅
❌
✅
Java
import
✅
✅
✅
.NET
@Html.RemotePartial()
✅
❌
✅
include
✅
✅
✅
In the case that a function allows remote URLs but does not allow code execution, we can exploit the vulnerability to enumerate local ports through SSRF.
A reliable way to determine whether an LFI flaw is also an RFI one is to try and include a local URL (for ensuring that does not get blocked by security measures) and see if we can get its content.
If the index.php
page gets included and executed, i.e., rendered -> RFI + RCE.
This may be useful in case HTTP ports are blocked or the http://
string gets blocked by a WAF. By default, PHP tries to authenticate as an anonymous user.
Windows treats files on remote SMB servers as normal files, which can be referenced directly with a UNC path. This technique is more likely to work if we were on the same network, as accessing remote SMB servers over the internet may be disabled by default.
Writing PHP code in a field we control that gets logged into a log file
Including the log file to execute the PHP code.
The web application must have READ
privileges over the logged files.
Most PHP web applications utilize PHPSESSID
cookies which are stored in session
files. The name of the file that contains our user's data matches the name of our PHPSESSID
cookie with the sess_
prefix. These are stored:
/var/lib/php/sessions/
on Linux
C:\Windows\Temp\
on Windows
Check if the PHPSESSID
session file contains any user-controller data. For instance, if our PHPSESSID
cookie's value is nhhv8i0o6ua4g88bkdl9u1fdsd
, we can include it via LFI.
We can see that the session file contains two values:
page
-> shows the selected language page (not user-controlled)
preference
-> shows the selected language (user-controlled via the ?language=
parameter)
Modify the user-controlled parameter (language
) and see if it changes in the session file.
To execute another command, the session file has to be poisoned with the web shell again, as it gets overwritten with /var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd
after our last inclusion. Ideally, we would use the poisoned web shell to write a permanent web shell to the web directory, or send a reverse shell for easier interaction.
Logs tend to be huge, and loading them in through an LFI may take a while to read, or even crash the server.
Both Apache
and Nginx
maintain various log files, such as access.log
and error.log
. The access.log
file contains various information about all requests made to the server, including each request's User-Agent
header. As we can control the User-Agent
header in our requests, we can use it to poison the server logs as we did above.
Once poisoned, we need to include the logs through the LFI vulnerability, and for that we need to have read-access over the logs.
Apache
/var/log/apache2
, C:\xampp\apache\logs
High privileged users
Nginx
/var/log/nginx
, C:\nginx\log
Low privileged users
The User-Agent
header is also shown on process files under the Linux /proc/
dir. 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 might be useful in case we don't have read access over the server logs, however, these files may only be readable by privileged users as well.
Finally, there are other similar log poisoning techniques that we may utilize on various system logs, depending on which logs we have read access over. The following are some of the service logs we may be able to read:
/var/log/sshd.log
/var/log/mail
/var/log/vsftpd.log
We should first attempt reading these logs through LFI, and if we do have access to them, we can try to poison them as we did above. For example, if the ssh
or ftp
services are exposed to us, and we can read their logs through LFI, then we can try logging into them and set the username to PHP code, and upon including their logs, the PHP code would execute. The same applies the mail
services, as we can send an email containing PHP code, and upon its log inclusion, the PHP code would execute. We can generalize this technique to any logs that log a parameter we control and that we can read through the LFI vulnerability.
The difference between the and the data wrapper is that for the former, the vulnerable parameter must also accept POST
requests. If the function only accepts POST
requests, we can create a static webshell by putting the command directly within the PHP code.
The wrapper is an external wrapper, i.e., it need to be manually installed and enabled, which allows us to directly run command through URL streams. We can check if that is the case similarly to the and grepping for expect.
In older or misconfigured Apache servers these logs may be readable by low-privileged users. In addition, the logs may be in a different location in some cases, so we may use an to fuzz for their locations.