You might have heard about “NAT Slipstreaming” by Samy Kamkar. It’s an amazing technique that allows punching a hole in your routers firewall by just visiting a website.
The attack depends on the router having the
Application Layer Gateway enabled. This gateway can be used by anyone inside your network to open a firewall port (totally by design). Protocols such as
Session Initiation Protocol) use it.
What I will focus on in this post is the
Application Layer Gateway (
SIP. In particular to understand how these can be abused by an adversary.
I won’t be discussing the browser-based attack angle in this post.
Let’s get started.
Application Layer Gateway and SIP
ALG monitors traffic passing through your router. It will act on and modify requests for some protocols if enabled. One of the protocols that can be enabled is
SIP is a text-based protocol, just like HTTP. It is used in Voice over IP (VoIP) applications. VoIP works better peer-to-peer, so there is a
REGISTER verb that allows punching a hole into your firewall.
More details of the
SIP protocol are described in RFC 5626.
To learn more about this I implemented a simple fake SIP server and a client for Linux/macOS and also a client for PowerShell for Windows.
Implementing a fake SIP Server
The fake SIP server is just a basic TCP server written in Python. I took the core messages that are sent back and forth from Samy’s implementation.
The code for the server, called it natty-slipstream, is here.
SIP REGISTER Request
After the fake
SIP server is up and running outside your network, you can try to punch a hole in your firewall. This is done by sending the
REGISTER request to the server.
I created two implementations for this:
- Windows PowerShell
- Linux/macOS - Bash/curl
Bash based Linux/macOS version
curl is used. Interestingly my router did not mind some incorrect headers and strings in the
If you are on macOS you might have to modify the way to get local IP, if you don’t have
ip available. Or just manually update the script and insert the IP on your local network
This is how the request looks like:
REGISTER sip:example.org;transport=TCP SIP/2.0 Via: SIP/2.0/TCP 192.168.0.141:5060;branch=I9hG4bK-d8754z-c2ac7de1b3ce90f7-1---d8754z-;rport;transport=TCP Max-Forwards: 70 Contact: <sip:firstname.lastname@example.org:1433;rinstance=v40f3f83b335139c;transport=TCP> To: <sip:email@example.com;transport=TCP> From: <sip:firstname.lastname@example.org;transport=TCP>;tag=U7c3d519 Call-ID: aaaaaaaaaaaaaaaaa0404aaaaaaaaaaaabbbbbbZjQ4M2M. CSeq: 1 REGISTER Expires: 70 Allow: REGISTER, INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE Supported: replaces, norefersub, extended-refer, timer, X-cisco-serviceuri Allow-Events: presence, kpml Content-Length: 0
The parts of the request that require customization are:
192.168.0.141The IP address of the internal target machine
Port 5060The remote port of the fake SIP Server
Port 1433The port that we want to expose externally to the fake SIP server
If your router has
SIP enabled, it will replace the internal IP address in the packet (in this case
192.168.0.141) with the routers public IP address.
After receiving the client’s request, the server responds with the following message:
SIP/2.0 200 OK Via: SIP/2.0/TCP 174.nn.nn.nnn:59973;branch=I9hG4bK-d8754z-c2ac7de1b3ce90f7-1---d8754z-;rport;transport=TCP;received=10.10.10.10 From: <sip:email@example.com;transport=TCP>;tag=U7c3d519 To: <sip:firstname.lastname@example.org;transport=TCP>;tag=37GkEhwl6 Call-ID: aaaaaaaaaaaaaaaaa0404aaaaaaaaaaaabbbbbbZjQ4M2M. CSeq: 1 REGISTER Contact: <sip:email@example.com:44444;rinstance=v40f3f83b335139c;transport=TCP>;expires=3600 Content-Length: 0
Notice the IP address (
174.nn.nn.nnn) which is the public IP of the router.
When the response is processed by the router, it will replace the public IP with the internal IP again.
And it will open up the requested port
1433 for the server to connect. Nice.
The hole is punched
That is it, now I was able to connect to the port from the outside!
The port stayed open for about 2 minutes. I tried changing the expiration header, but it did not change the duration of the exposure for my router model. But two minutes is plenty of time to connect.
Check your router configuration to ensure attack surface is limited. Disabling
ALG on the router will mitigate this. In my case there was no need for
ALG, so this was a simple fix.
This is a design flaw of the protocol, and it is not unlikely that more attacks in this realm will show up as more people start looking at this.
That’s it. Hope this was interesting and useful. For red teaming this is an interesting TTP to expose internal infrastructure with a benign looking request to port
If you haven’t yet, check out Cybersecurity Attacks - Red Team Strategies for lots of red teaming goodies.