NAT Slipstreaming

NAT Slipstreaming permits an attacker to remotely procure admission to any TCP/UDP carrier slip to a victim machine, bypassing the victim’s NAT/firewall (arbitrary firewall pinhole control), neatly-behaved by the victim visiting a net space.

Developed by: @SamyKamkar //

Released: October 31 👻 2020

Supply code:

animation generated with my fork of, allowing exportable edge context drift & control in animations

  • Summary
  • The deets
    • Network Address Translation (NAT)
      • Connection Tracking
      • Utility Stage Gateway
    • Router Investigation / Firmware Dumping
    • Reverse Engineering Firmware
      • Finding Attention-grabbing Recordsdata
      • Exploring Attention-grabbing Capabilities
      • Ports / Companies and products to Overview
      • Reversing the Kernel Object
      • Making an try SIP Packet in HTTP POST
      • Proceed Reversing Kernel Object Extra
    • Connection Tracking / Utility Stage Gateway Investigation
      • Linux Netfilter
    • Packet Boundary / Fragmentation Alter
    • TCP Timing Attack / Interior Subnet & IP Discovery
      • Timing Attack
    • Browser Protocol Confusion
      • Live Browser Packet Alteration
  • Other Findings
  • Example / Download
  • Contact

NAT Slipstreaming exploits the person’s browser along with the Utility Stage Gateway (ALG) connection tracking mechanism constructed into NATs, routers, and firewalls by chaining inner IP extraction via timing attack or WebRTC, automated distant MTU and IP fragmentation discovery, TCP packet size massaging, TURN authentication misuse, staunch packet boundary control, and protocol confusion via browser abuse. Because it be the NAT or firewall that opens the commute set port, this bypasses any browser-based entirely port restrictions.

This attack takes profit of arbitrary control of the information half of some TCP and UDP packets without including HTTP or other headers; the attack performs this sleek packet injection methodology all the scheme via all critical up to the moment (and older) browsers, and is a modernized model to my common NAT Pinning methodology from 2010 (supplied at DEFCON 18 + Murky Hat 2010). Furthermore, sleek tactics for native IP deal with discovery are incorporated.

This attack requires the NAT/firewall to enhance ALG (Utility Stage Gateways), which are mandatory for protocols that could per chance employ extra than one ports (control channel + recordsdata channel) such as SIP and H323 (VoIP protocols), FTP, IRC DCC, and so on.

At a excessive level, NAT Slipstreaming works like so:

  • victim visits malicious space (or space with malicious advertisement)
  • inner IP of victim first could per chance have faith to be extracted by browser and despatched to server
    • inner IP attempted to be extracted via WebRTC recordsdata channel over https
      • some browsers (Chrome) most productive repeat the native IP via WebRTC over HTTPS but a couple of of our attacks require HTTP so we first redirect to the HTTPS model of the attack instrument to extract the native IP
      • we then redirect to the HTTP model with the native IP incorporated in the URL if we were able to develop it to avoid other contemptible-starting up set protection mechanisms (the .native mDNS/Bonjour deal with supplied could per chance now not be invaluable for the attack)
    • if inner IP now not divulged by WebRTC (Safari) or no WebRTC (net-based entirely TCP timing attack performed
      • hidden img tags to all classic gateways (eg are loaded in background
      • onerror/onsuccess occasions linked to img tags
      • if any TCP RST (oneror) returned by gateway, or SYN + HTTP response (onsuccess), within a couple of seconds (before TCP timeout triggers onerror), we’ve detected legit subnet
      • re-develop timing attack all the scheme via all IPs on detected subnets (/24), measuring time to onerror/onsuccess firing
      • fastest response is seemingly inner IP, though all responses are thought to be as victim inner IP candidates and attacked
  • colossal TCP beacon despatched via hidden create and automatic HTTP POST to attacker “HTTP server” slip to a non-identical outdated port to force TCP segmentation and maximum MTU size discovery of the victim’s IP stack
    • attacker TCP server sends Most Section Dimension TCP Likelihood to rubdown victim outbound packet sizes (RFC 793 x3.1), allowing control of how colossal browser TCP packets will be
  • colossal UDP beacon despatched from browser via WebRTC TURN authentication mechanism to non-identical outdated port to attacker’s server to force IP fragmentation with TURN username field stuffed
    • we develop a same attack as our TCP segmentation, but over UDP as IP fragmentation will happen and present numerous values than TCP segmentation
    • victim MTU size, IP header size, IP packet size, TCP header size, TCP segment sizes detected by server and despatched back to victim’s browser, worn later for packet stuffing
  • “SIP packet” in sleek hidden create generated, containing inner IP to trigger Utility Stage Gateway connection tracking
    • “HTTP POST” to server on TCP port 5060 (SIP port) initiated, avoiding restricted browser ports
    • POST recordsdata is “stuffed” to staunch TCP segment size / packet boundary, then “SIP packet” appended and posted via net create
    • victim IP stack breaks the POST into extra than one TCP packets, leaving the “SIP packet” (as portion of POST recordsdata) in its have faith TCP packet with none accompanying HTTP headers
    • if browser alters size of multipart/create boundary (Firefox) or packet size modifications for any other reason, size alternate is communicated back to client and client auto-resends with sleek size
    • when opening UDP port, SIP packet is distributed over TURN protocol inner particularly crafted username field forcing IP fragmentation and staunch boundary control
  • victim NAT sees just correct SIP REGISTER packet on SIP port (with out a HTTP recordsdata), triggering ALG to open any TCP/UDP port outlined in packet back to victim
    • victim NAT rewrites SIP packet, changing inner IP with public IP, hinting to attacker exploit became as soon as successful
    • although victim NAT typically rewrites source ports, the ALG will aloof be compelled to port forward to the attacker’s port of different because it believes victim machine opened that port and attacker sees sleek source port in arriving SIP packet
    • attacker can now bypass victim NAT and join today back to any port on victim’s machine, exposing beforehand favorable/hidden services and products

successful packet broken into valid SIP packet

Network Address Translation (NAT)

We employ NATs (Network Address Translation) for loads of causes. Basically the most invaluable characteristic of NAT is that it permits a single public IP deal with to be shared amongst extra than one techniques. It does this by creating a native community, offering native IP addresses to all machines that join, and when one in all these techniques reaches out to the Web, it rewrites packets going out to employ the public IP so responses attain back to the NAT, and vice versa, rewriting desination IP to particular client’s IP.

It is the accountability of the NAT to differentiate connections to the identical addresses/ports ( 443) from inner hosts as in the kill their outbound port, commute set ip and source ip will all be the identical. If two numerous inner peers try to join from the identical source port, up to the moment NATs will alter one in all the source ports (some networks assemble this to all TCP/UDP source ports).


Connection Tracking

From Wikipedia ala Wikiwand:

One in all the main functions constructed on top of the Netfilter 
framework is connection tracking. Connection tracking 
permits the kernel to preserve note of all logical community 
connections or sessions, and thereby scream the overall packets
that could per chance develop up that connection. NAT relies on this 
recordsdata to translate all linked packets in the identical manner, 
and iptables can employ this recordsdata to behave as a stateful 

If a machine in the back of your NAT sends a packet out and your router expects the distant host could per chance reply, it retains note of recordsdata, particularly the source and commute set ports, source and commute set IP addresses, and your inner IP, then returns any packets matching it back to your inner IP.

If any other host in your LAN attempts to develop the identical connection with the identical source and commute set ports + IPs, your NAT wouldn’t be able to discriminate it, so it alters the source port, but rewrites it when sending back to you.

Utility Stage Gateway

ALGs allow NAT to notice a multi-port protocol like FTP to pass out out of your system to an FTP server, then note while you seek recordsdata from a file to be despatched to your inner IP on a particular port, the ALG can rewrite the packet to incorporate your public IP, then forward the FTP’s server connection back to you. Had it now not rewritten your IP, the FTP server would try to join back to you in your inner IP (or now not try in any appreciate if it expects the source IP to be the identical because the signaling connection).

From Wikipedia:

Within the context of computer networking, an software program-level 
gateway contains a safety factor that augments a 
firewall or NAT employed in a computer community. It permits 
customized NAT traversal filters to be plugged into the 
gateway to enhance deal with and port translation for obvious 
software program layer "control/recordsdata" protocols such as FTP, 
BitTorrent, SIP, RTSP, file transfer in IM applications, and so on. 
To ensure that these protocols to work via NAT or a 
firewall, both the software program has to know about an deal with/
port number combination that enables incoming packets, or the 
NAT has to show screen the control traffic and open up port 
mappings (firewall pinhole) dynamically as required. 
Legit software program recordsdata can thus be handed via the 
safety checks of the firewall or NAT that could per chance have faith 
in any other case restricted the traffic for now not meeting its restricted 
filter standards.

Router Investigation / Firmware Dumping

I’d first like to witness how classic gateways in level of truth deal with packets and multi-port protocols like FTP, SIP, and so on. To assemble this, we’ll are looking out to reverse engineer the firmware from classic routers. We could per chance dump the flash from physical routers, nevertheless if we can procure unencrypted firmware from the manufacturers, we’ll be able to match extra router items and a lot faster.

We will start with a classic router, the Netgear Nighthawk R7000. A transient search helps us get a Netgear article with newest firmware. After we procure the firmware and unzip, we discover a 30MB file called R7000-V1.0.9.64_10.2.64.chk.

tigerblood:~c/ng$ wget
--2019-05-19 19: 21: 13--
Resolving (
Connecting to (||: 80... linked.
HTTP seek recordsdata from despatched, looking forward to response... 200 OK
Dimension: 31705064 (30M) [application/zip]
Saving to: ‘’  100%[=============================================>]  30.24M  6.25MB/s    in 11s

2019-05-19 19: 21: 24 (2.83 MB/s) - ‘’ saved [31705064/31705064]

tigerblood:~c/ng$ unzip
 extracting: R7000-V1.0.9.64_10.2.64.chk
  inflating: R7000-V1.0.9.64_10.2.64_Release_Notes.html
tigerblood:~c/ng$ file R7000-V1.0.9.64_10.2.64.chk
R7000-V1.0.9.64_10.2.64.chk: recordsdata
tigerblood:~c/ng$ ls -lh R7000-V1.0.9.64_10.2.64.chk
-rw-r--r--  1 samy  workers    30M Mar 26 11: 46 R7000-V1.0.9.64_10.2.64.chk


The file exclaim doesn’t detect any magic data, so we can employ binwalk to scan the file for nested recordsdata.

tigerblood:~c/ng$ binwalk R7000-V1.0.9.64_10.2.64.chk

58            0x3A            TRX firmware header, minute endian, image size: 31703040 bytes, CRC32: 0xBEF1BB2F, flags: 0x0, model: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x21E3F0, rootfs offset: 0x0
86            0x56            LZMA compressed recordsdata, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5436416 bytes
2221098       0x21E42A        Squashfs filesystem, minute endian, model 4.0, compression:xz, size: 29475437 bytes, 1988 inodes, blocksize: 131072 bytes, created: 2018-12-26 04: 15: 38

binwalk R7000-V1.0.9.64_10.2.64.chk

I employ macOS and binwalk relies upon on some Linux apps out of the sector which could per chance perhaps trigger binwalk -e (which extracts files) to fail so I extract manually (and I

tigerblood:~c/ng$ perl -ne'$@.=$_}{print+substr$@,2221098' R7000-V1.0.9.64_10.2.64.chk> squash.fs

Or employ inout, eg inout R7000-V1.0.9.64_10.2.64.chk 2221098.

You would employ dd, nevertheless it is doubtless you need to a colossal bs (block size) so as that it could perhaps most likely output expeditiously, eg 1024, nevertheless the skip attribute (to notify it to begin on the distance of the squashfs blob) would appreciate the block size and 2221098 isn’t obviously divisible in something expeditiously in my head other than 2…now I’m uncommon.

tigerblood:~c/ng$ time dd if=R7000-V1.0.9.64_10.2.64.chk skip=$((2221098/2)) bs=2 of=squash.fs2
14741000+0 recordsdata in
14741000+0 recordsdata out
29482000 bytes transferred in 78.363403 secs (376222 bytes/sec)

staunch    1m18.385s
person    0m12.553s
sys     1m4.451s

Now let’s unpack the squash filesystem. I’ve created a fork of a fork of squashfs-tools that runs on macOS and has lzo reinforce. You would must install xz and lzo as neatly. Alternatively, it is doubtless you’ll employ sasquatch on Linux.

tigerblood:~c/ng$ sudo port install xz lzo
tigerblood:~c/ng$ git clone && cd squashfs-tools/squashfs-tools && develop && sudo develop install && cd ../..

And in the kill we can unpack the squash fs.

tigerblood:~c/ng$ unsquashfs -l -no squash.fs
Parallel unsquashfs: The employ of 8 processors
1881 inodes (2535 blocks) to write

... (many extra files) ...

tigerblood:~c/ng$ cd squashfs-root && ls
bin   recordsdata  dev   and so on   lib   media mnt   decide   proc  sbin  portion sys   tmp   usr   var   www

We’ve got got the raw OS to stumble on!

Reverse Engineering Firmware

Finding Attention-grabbing Recordsdata

Now let’s witness if we can get any files relevant to FTP because it became as soon as a closely worn protocol so ALG reinforce will be rampant all the scheme via routers. I employ my g tool which is neatly-behaved a convenient wrapper around egrep.

tigerblood:~c/ng/squashfs-root$ get . | g ftp
./usr/and so on/sftp-ssh.carrier

Nothing attention-grabbing, so let’s g for binary files whose exclaim material matches /ftp/, ignoring some files we don’t care about.

tigerblood:~c/ng/squashfs-root$ g -la ftp -v '.(html?|js|gif)$|www/|bin/'
usr/and so on/sftp-ssh.carrier

g recursively scans essentially the latest working list by default. -l is to most productive print file names (as these will be mainly binary), -a to scan binary files, ftp for text to match, and -v '.(html?|js|gif)$|www/|bin/' to push aside net files and executables (sitting in (s)bin/).

Any lib/lib*.{a,so}{.*,} (bash structure) files are wearisome, so let’s scan again with much less:

tigerblood:~c/ng/squashfs-root$ g -la ftp -v '.(html?|js|gif)$|www/|bin/|lib.*.(so|a)(.|$)'
usr/and so on/sftp-ssh.carrier

Exploring Potentially Well-known Capabilities

K, two files of pastime – lib/modules/tdts.ko could per chance very neatly be linked, and lib/modules/ could per chance very neatly be now not linked but sounds attention-grabbing! May per chance seemingly additionally just compare that later.

tigerblood:~c/ng/squashfs-root$ file lib/modules/tdts.ko
lib/modules/tdts.ko: ELF 32-bit LSB relocatable, ARM, EABI5 model 1 (SYSV), BuildID[sha1]=0aa35748e245e60273ceb5a48641e424d069235b, now not stripped
tigerblood:~c/ng/squashfs-root$ strings lib/modules/tdts.ko | g ftp

Good! A kernel object (.ko) with ftp capabilities, and with phrases like “port”, it be seemingly linked to an FTP ALG. The FTP RFC 959 explains the which implies of the PORT exclaim:


The argument is a HOST-PORT specification for the information port
to be worn in recordsdata connection.  There are defaults for each and every
the person and server recordsdata ports, and under customary
conditions this exclaim and its reply are now not main.  If
this exclaim is worn, the argument is the concatenation of a
32-bit net host deal with and a 16-bit TCP port deal with.
This deal with recordsdata is broken into 8-bit fields and the
price of each and every field is transmitted as a decimal number (in
character string illustration).  The fields are separated
by commas.  A port exclaim would be:
    PORT h1,h2,h3,h4,p1,p2
where h1 is the excessive narrate 8 bits of the on-line host
deal with.

Ports / Companies and products to Overview

While we’ve came upon some FTP capabilities, we’re extra drawn to ports that we can employ. In model browsers quit outbound HTTP(S) connections to a different of restricted ports, including FTP, so abusing the FTP ALG is seemingly a no-lunge.

In 2010, when I first demonstrated NAT Pinning, I worn port 6667 (IRC) via the DCC CHAT/FILE messages. Hasty, browser distributors blocked port 6667…though some worn a uint32 (32 bit unsigned integer) to retailer the port, check if the port became as soon as blocked, and if now not, join. To evade this, it be main to illustrate TCP ports are 16 bits long, so while you happen so that that you just must per chance add 216 (65536) to the “restricted” port of different, in this case 65536+6667=72203, the browser would retailer 72203, it could perhaps most likely glide the port restriction (72203 !=6667), then would procure despatched off to the TCP stack where it gets truncated to 16 bits which is the restricted port we wanted!

My uncomplicated defective calculator, 3 reveals this (db=dec -> bin):

tigerblood:/Users/samy/d$ 3 db 65536 6667 65536+6667

We are able to witness it higher the employ of my diffbits tool, a straightforward tool for viewing similarities and differences between bit strings, apart from to between extra than one teams of bit strings, invaluable for reversing proprietary, binary protocols.


Reversing the Kernel Object

Bound forward and open your disassembler of different. I’ve worn Ghidra from our chums on the NSA because it’s free and open source.

A few of the capabilities we noticed in tdts.ko via strings became as soon as ftp_decode and ftp_decoder, so it be imaginable other ALGs could per chance have faith a _decode characteristic. Let’s peek…

Ghidra _decode

Alright, a bunch of _decode capabilities…scrolling down, an enticing one is sip_decode.

Ghidra tdts.ko

Checking our restricted browser ports, we witness 5060, the default SIP port, is now not restricted in Chrome 🙂

Making an try SIP Packet in HTTP POST

SIP lives on TCP/UDP 5060, but media like RTP (audio) is distributed on alternate ports that are generated on the wing. When sending a seek recordsdata from for a SIP call, your SIP client chooses a random port, opens it, and entails it in the SIP header. Your NAT must always aloof also witness it and open it up, assuming the SIP ALG is enabled (and is on most routers by default).

Assuming NATs reader SIP packets line by line (SIP is newline-based entirely like HTTP and is now not a binary protocol), perhaps this could per chance ignore the HTTP header and as soon because it gets to the POST recordsdata, read the REGISTER and imagine it be a SIP packet. This worked in our 2010 model for the IRC DCC. The NAT neglected the HTTP header and neatly-behaved parsed the IRC DCC exclaim.

Silly ingredient, this also allowed us to truly develop users who talk over with our space join to a legit IRC server, join a channel, and send a message from their IP without them knowing! 😛 I demo’d this system fo sending email to mail servers with client IP addresses before port 25 became as soon as blocked by browsers and before SPF recordsdata were classic…craziness.

Now, in a transient take a look at, sending a SIP REGISTER packet over port 5060 via an HTTP POST doesn’t appear to work…perhaps we’re missing something from the packet.

// our sip message
var sipmsg='REGISTER;transport=TCP SIP/2.0rn' +
             'Contact: rnrn'

// load create in an iframe so person doesn't se it
var iframe=file.createElement('iframe')'iframe'
iframe.model.demonstrate='none' // veil the iframe

// manufacture create
var create=file.createElement('create')
create.setAttribute('target', 'iframe') // load into iframe
create.setAttribute('scheme', 'POST') // need the POST space where we can add CRLFs
create.setAttribute('action', ' 5060') // "http" server on SIP port 5060
create.setAttribute('enctype', 'multipart/create-recordsdata') // be obvious our recordsdata doesn't procure encoded

var textarea=file.createElement('textarea')
textarea.setAttribute('name', 'textname') // required

If we sniff, we witness (parsed via h2b):

$ unbuffer tcpdump -X port 5060 | h2b
Host: 5060
Connection: preserve-alive
Direct-Dimension: 191
Cache-Alter: max-age=0
Upgrade-Terrified-Requests: 1
Direct-Form: multipart/create-recordsdata; boundary=----WebKitFormBoundaryhcoAd2iSAx3TJA7A
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.66 Safari/537.36
Obtain: text/html,software program/xhtml+xml,software program/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,software program/signed-alternate;v=b3
Obtain-Encoding: gzip, deflate
Obtain-Language: en-US,en;q=0.9

Direct-Disposition: create-recordsdata; name="textname"

REGISTER;transport=TCP SIP/2.0


However, this doesn’t open the port, neither is the IP rewritten which we’d seek recordsdata from (extra on this later), so we’ve to be missing something.

Proceed Reversing Kernel Object Extra

Let’s preserve digging in the kernel object. Within the diassembly, we witness the “SIP/2.0” designate from a SIP packet, so it’s seemingly parsing here (which “decode” sounds like).

Ghidra sip_decode

Ah, here’s why we fail. Looks like it be working strncasecmp on INVITE (same parsing on REGISTER) – matching (case-insensitive, which is attention-grabbing as SIP INVITEs are higher case) the note “INVITE” first and foremost set of the packet and branches if not equal (ARM meeting bne) to 0, so if the phrases assemble match, the lexicographical narrate will be 0 and we’ll continue to ct_sip_get_header which sounds stress-free, and looks to bail in any other case.

That is the difficulty…while we can employ a net browser to form outbound sockets (TCP via HTTP(S), UDP via TURN w/WebRTC), we assemble now not have faith ample control over the browser to begin the TCP recordsdata half with the note “INVITE”, which this module expects. Within the 2010 IRC model, the IRC ALG most productive regarded line by line, ignoring the overall HTTP header recordsdata, then the employ of newlines in the POST recordsdata to send a legit “IRC DCC”. However, this SIP ALG is noteworthy extra strict and controlling the starting up set of the seek recordsdata from is now not imaginable. If the employ of TLS, encrypted header will start the packet. If the employ of HTTP, the HTTP scheme will start the packet (GET, POST, and so on). Can we exploit this any other manner?

Connection Tracking / Utility Stage Gateway Investigation

Linux Netfilter

To raised perceive connection tracking and Utility Stage Gateways, we can peek to witness how they behave in netfilter, Linux’s community stack. I’ve created a chart of essentially the most long-established ALGs and the scheme they behave based entirely off of parsing the Linux source.

Linux ALG

From this chart, essentially the most attention-grabbing ones (that Chrome doesn’t block) are sane (backup), sip (voip), pptp (vpn), and h323 (voip). We will clutch SIP because it’s one in all the extra ubiquitous of these protocols, and we already witness it in some routers’ firmware.

Linux particularly has nf_conntrack_*.c files for dealing with connection tracking on a per protocol foundation, and nf_nat_*.c f

Read More

Recent Content