Poking Holes in the Firewall: Egress Testing With AllPorts.Exposed
Beau Bullock //
If you have been even remotely in touch with technology in the past thirty years you have probably heard of this thing called a “firewall”. If not, a “firewall” decides what does and does not get to proceed through it. Most organizations have one of these protecting their network from the rest of the Internet. Some organizations place them in the most opportune spots to segment off specific areas of their internal network. The system you are using right now to read this blog post most likely has a firewall built-in.
The general consensus about what a firewall does is that it keeps “bad stuff” from entering a protected network or system. But firewalls can also keep things from leaving a network or system. This is called “egress filtering”.
Why Should We Care What Leaves?
The simple answer is the more ports allowed out, the easier it is for an attacker to establish command and control. If there are no outbound filters put in place an organization can quickly lose visibility into what is leaving the network. This can lead to malware infections, command and control sessions going unnoticed, or insider employees getting around corporate network policies.
If you are the one in charge of the firewall at your organization, how do you go about knowing what is allowed out of your network quickly without diving into your firewall rule sets?
If you are a pentester, how can you quickly find out what ports are allowed out of a network that can be used as a command and control channel?
AllPorts.Exposed
AllPorts.Exposed is an Internet-resident system with (as the name suggests) all 65535 TCP ports open on it. If you were to portscan it from a system/network without firewall protection you should see that all ports are “open”. Now, if you were to portscan this system from within your network protected by a firewall, and you see open ports, these ports can be assumed as being allowed outbound through the firewall.
How To Test It?
Yes, you could use something like Nmap to do a simple portscan but I prefer PowerShell for this task as it is built into Windows operating systems. Often-times, when we are performing a pentest we are working from a Windows-based system and are typically not an administrator user. So, installing external tools can be difficult.
Here is a short PowerShell portscanning script you can use to test ports 1-1024 against allports.exposed.
- Open up a command terminal.
- Type ‘powershell.exe -exec bypass’ and hit enter.
- Copy the below script into the terminal window and run it.
1..1024 | % {$test= new-object system.Net.Sockets.TcpClient; $wait = $test.beginConnect("allports.exposed",$_,$null,$null); ($wait.asyncwaithandle.waitone(250,$false)); if($test.Connected){echo "$_ open"}else{echo "$_ closed"}} | select-string " "
In the following screenshot you can see where the script prints ‘open’ to the terminal window for ports that were discovered as being open.
Alternatively, if you would like to just check for certain ports you can comma-separate each port you would like to scan at the beginning of the script in place of “1..1024”. For example, the following script will only scan ports 21, 22, 23, 25, 80, 443, and 1337.
21,22,23,25,80,443,1337 | % {$test= new-object system.Net.Sockets.TcpClient; $wait =$test.beginConnect("allports.exposed",$_,$null,$null); ($wait.asyncwaithandle.waitone(250,$false)); if($test.Connected){echo "$_ open"}else{echo "$_ closed"}} | select-string " "
Here is the same script, but this time we are testing the top 128 ports in use on the Internet as defined by the Nmap project.
80,23,443,21,22,25,3389,110,445,139,143,53,135,3306,8080,1723,111,995,993,5900,1025,587,8888,199,1720,465,548,113,81,6001,10000,514,5060,179,1026,2000,8443,8000,32768,554,26,1433,49152,2001,515,8008,49154,1027,5666,646,5000,5631,631,49153,8081,2049,88,79,5800,106,2121,1110,49155,6000,513,990,5357,427,49156,543,544,5101,144,7,389,8009,3128,444,9999,5009,7070,5190,3000,5432,3986,13,1029,9,6646,49157,1028,873,1755,2717,4899,9100,119,37,1000,3001,5001,82,10010,1030,9090,2107,1024,2103,6004,1801,19,8031,1041,255,3703,17,808,3689,1031,1071,5901,9102,9000,2105,636,1038,2601,7000 | % {$test= new-object system.Net.Sockets.TcpClient; $wait =$test.beginConnect("allports.exposed",$_,$null,$null); ($wait.asyncwaithandle.waitone(250,$false)); if($test.Connected){echo "$_ open"}else{echo "$_ closed"}} | select-string " ""
In conclusion, knowing what ports are allowed out of a network is very important for both pentesters and network admins. Each port allowed outbound from a network creates an additional exit point for attackers to utilize. BHIS recommends locking down egress traffic to only the ports required for the business to function. If possible, implement a web proxy and only allow outbound web traffic from it. Block all outbound traffic from client systems, and force their web browsers to use the web proxy to perform web browsing.
*Psst* If you liked this blog, we think you’d enjoy Beau’s class:
Available live/virtual and on-demand!
flux
December 21, 2016 @ 7:58 am
Hi there,
thanks for the great service it is really useful during engagements! Any idea how to implement the powershell snippet into a oneliner? Might be usefull in case of restricted scenarios like uploaded php-shells and where you can’t open up PS and the usage of CMD is mandatory.
Thanks!
f
Nem Schlecht
April 4, 2017 @ 10:03 am
Here’s how to do it as a one-liner, flux:
In Powershell:
PS> $script = {1..1024 | ForEach-Object {$test= new-object system.Net.Sockets.TcpClient; $wait = $test.beginConnect(“allports.exposed”,$_,$null,$null); $wait.asyncwaithandle.waitone(250,$false)); if($test.Connected) {echo “$_ open”}else{echo “$_ closed”}} | select-string ” “}
PS> [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($script))
Take the resulting string (I had to put it into an editor and remove newlines!) and run it as this right from a CMD window (this should all be *one* line):
C:\> powershell -NoProfile -ExecutionPolicy ByPass -EncodedCommand MQAuAC4AMQAwADIANAAgAHwAIABGAG8AcgBFAGEAYwBoAC0ATwBiAGoAZQBjAHQAIAB7ACQAdABlAHMAdAA9ACAAbgBlAHcALQBvAGIAagBlAGMAdAAgAHMAeQBzAHQAZQBtAC4ATgBlAHQALgBTAG8AYwBrAGUAdABzAC4AVABjAHAAQwBsAGkAZQBuAHQAOwAgACQAdwBhAGkAdAAgAD0AIAAkAHQAZQBzAHQALgBiAGUAZwBpAG4AQwBvAG4AbgBlAGMAdAAoACIAYQBsAGwAcABvAHIAdABzAC4AZQB4AHAAbwBzAGUAZAAiACwAJABfACwAJABuAHUAbABsACwAJABuAHUAbABsACkAOwAoACQAdwBhAGkAdAAuAGEAcwB5AG4AYwB3AGEAaQB0AGgAYQBuAGQAbABlAC4AdwBhAGkAdABvAG4AZQAoADIANQAwACwAJABmAGEAbABzAGUAKQApADsAIABpAGYAKAAkAHQAZQBzAHQALgBDAG8AbgBuAGUAYwB0AGUAZAApACAAewBlAGMAaABvACAAIgAkAF8AIABvAHAAZQBuACIAfQBlAGwAcwBlAHsAZQBjAGgAbwAgACIAJABfACAAYwBsAG8AcwBlAGQAIgB9AH0AIAB8ACAAcwBlAGwAZQBjAHQALQBzAHQAcgBpAG4AZwAgACIAIAAiAA==
(You should always generate this code yourself – don’t trust what I posted – even though in this case, it is the same code).