Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
slipstream — NAT Slipstreaming consente a un attaccante di accedere da remoto a qualsiasi servizio TCP/UDP associato a una macchina vittima, bypassando il NAT/firewall della vittima, semplicemente se qualcuno nella rete della vittima visita un sito web. | Kitploit
Strumenti/GitHubGitHub/samyk/slipstream
RicognizioneExploitSicurezza WebSicurezza di RetePenetration Testing
GitHubsamyk/slipstream

slipstream

NAT Slipstreaming consente a un attaccante di accedere da remoto a qualsiasi servizio TCP/UDP associato a una macchina vittima, bypassando il NAT/firewall della vittima, semplicemente se qualcuno nella rete della vittima visita un sito web.

Vedi Repository
2.0k21473 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Sito web

NAT Slipstreaming

NAT Slipstreaming permette a un attaccante di accedere da remoto a qualsiasi servizio TCP/UDP associato a qualsiasi sistema dietro il NAT della vittima, bypassando il NAT/firewall della vittima (controllo remoto arbitrario dei fori del firewall), semplicemente visitando un sito web.

v1 sviluppato da: @SamyKamkar // https://samy.pl
v2 sviluppato da: Samy Kamkar && (Ben Seri && Gregory Vishnipolsky di Armis).

Leggi l'eccellente descrizione tecnica di Ben & Gregory sulla v2 qui che approfondisce i loro aggiornamenti della v2 con molti dettagli aggiuntivi.

v1 rilasciata: 31 ottobre 👻, 2020
v2 rilasciata: 26 gennaio 2021

Codice sorgente: https://github.com/samyk/slipstream

Architettura NAT Slipstreaming versione animata qui generata con il mio fork di draw.io, che permette flusso di contesto sui bordi esportabile e controllo nelle animazioni

Sommario

  • Sommario
  • I dettagli
    • Network Address Translation (NAT)
      • Connection Tracking
      • Application Level Gateway
    • Indagine sul router / Dumping del firmware
    • Reverse Engineering del firmware
      • Trovare file interessanti
      • Esplorare funzioni interessanti
      • Porte / Servizi da investigare
      • Reverse engineering dell'oggetto kernel
    • Indagine su Connection Tracking / Application Level Gateway
      • Linux Netfilter
    • Controllo dei confini dei pacchetti / Frammentazione
    • Attacco temporale TCP / Scoperta della sottorete interna e dell'IP
      • Attacco temporale
    • Confusione dei protocolli del browser
      • Alterazione live dei pacchetti del browser
  • Altri risultati
  • Download
  • Contatti

Sommario

NAT Slipstreaming sfrutta il browser dell'utente insieme al meccanismo di connection tracking Application Level Gateway (ALG) integrato in NAT, router e firewall, concatenando l'estrazione dell'IP interno tramite attacco temporale o WebRTC, la scoperta automatica remota dell'MTU e della frammentazione IP, il massaggio della dimensione dei pacchetti TCP, l'uso improprio dell'autenticazione TURN, il controllo preciso dei confini dei pacchetti e la confusione dei protocolli attraverso l'abuso del browser. Poiché è il NAT o il firewall ad aprire la porta di destinazione, ciò bypassa qualsiasi restrizione sulle porte basata sul browser.

Questo attacco sfrutta il controllo arbitrario della porzione dati di alcuni pacchetti TCP e UDP senza includere intestazioni HTTP o altre; l'attacco esegue questa nuova tecnica di iniezione di pacchetti su tutti i principali browser moderni (e meno recenti), ed è una versione modernizzata della mia originale tecnica NAT Pinning del 2010 (presentata al DEFCON 18 + Black Hat 2010). Inoltre, sono incluse nuove tecniche per la scoperta dell'indirizzo IP locale.

Questo attacco richiede che il NAT/firewall supporti ALG (Application Level Gateways), che sono obbligatori per i protocolli che possono utilizzare più porte (canale di controllo + canale dati) come SIP e H.323 (protocolli VoIP), FTP, IRC DCC, ecc.

Ad alto livello, NAT Slipstreaming funziona così:

  • la vittima visita un sito malevolo (o un sito con un annuncio malevolo)
  • l'IP interno della vittima deve prima essere estratto dal browser e inviato al server
    • si tenta di estrarre l'IP interno tramite WebRTC data channel su https
      • alcuni browser (Chrome) rivelano l'IP locale solo tramite WebRTC su HTTPS, ma alcuni dei nostri attacchi richiedono HTTP, quindi prima reindirizziamo alla versione HTTPS del software di attacco per estrarre l'IP locale
      • quindi reindirizziamo alla versione HTTP con l'IP locale incluso nell'URL se siamo riusciti ad ottenerlo per bypassare altri meccanismi di protezione cross-origin (l'indirizzo .local mDNS/Bonjour presentato non sarà utile per l'attacco)
    • se l'IP interno non viene rivelato da WebRTC (Safari) o non c'è WebRTC (<= IE11), viene eseguito attacco temporale TCP basato sul web
      • tag img nascosti verso tutti i gateway comuni (es. 192.168.0.1) vengono caricati in background
      • eventi onerror/onsuccess associati ai tag img
      • se viene restituito un TCP RST dal gateway (o SYN + risposta HTTP), abbiamo rilevato una sottorete valida
      • ripetere l'attacco temporale su tutti gli IP delle sottoreti rilevate (/24), misurando il tempo di attivazione di onerror/onsuccess
      • la risposta più rapida è probabilmente l'IP interno, anche se tutte le risposte sono considerate candidati IP interni della vittima e attaccate
  • viene inviato un grande beacon TCP tramite un modulo nascosto e un HTTP POST automatico al "server HTTP" dell'attaccante associato a una porta non standard per forzare la segmentazione TCP e la scoperta della dimensione MTU massima dello stack IP della vittima
    • il server TCP dell'attaccante invia l'opzione TCP Maximum Segment Size per massaggiare le dimensioni dei pacchetti in uscita della vittima (), permettendo di controllare quanto saranno grandi i pacchetti TCP del browser

pacchetto riuscito suddiviso in un pacchetto SIP valido

I Dettagli

Network Address Translation (NAT)

Usiamo i NAT (Network Address Translation) per diverse ragioni. La caratteristica più utile del NAT è che permette di condividere un singolo indirizzo IP pubblico tra più sistemi. Lo fa creando una rete locale, fornendo indirizzi IP locali a tutte le macchine che si connettono, e quando uno di questi sistemi contatta Internet, riscrive i pacchetti in uscita per utilizzare l'IP pubblico in modo che le risposte tornino al NAT, e viceversa, riscrivendo l'IP di destinazione sull'IP specifico del client.

È responsabilità del NAT differenziare le connessioni agli stessi indirizzi/porte (google.com:443) dagli host interni, poiché alla fine la loro porta di uscita, IP di destinazione e IP sorgente saranno tutti uguali. Se due peer interni diversi tentano di connettersi dalla stessa porta di origine, i NAT moderni altereranno una delle porte di origine (alcune reti lo fanno per tutte le porte di origine TCP/UDP).

NAT

Connection Tracking

Da Wikipedia ala Wikiwand:``` One of the important features built on top of the Netfilter framework is connection tracking. Connection tracking allows the kernel to keep track of all logical network connections or sessions, and thereby relate all of the packets which may make up that connection. NAT relies on this information to translate all related packets in the same way, and iptables can use this information to act as a stateful firewall.

root@kitploit:~
Se una macchina dietro il tuo NAT invia un pacchetto in uscita e il tuo router si aspetta che l'host remoto possa rispondere, tiene traccia delle informazioni, in particolare delle porte di origine e destinazione, degli indirizzi IP di origine e destinazione e del tuo IP interno, poi restituisce eventuali pacchetti corrispondenti al tuo IP interno.

Se un altro host sulla tua LAN tenta di stabilire la stessa connessione con le stesse porte di origine e destinazione e gli stessi IP, il tuo NAT non sarebbe in grado di discriminarla (gli IP di origine sulla tua LAN sono diversi ma vengono riscritti con lo stesso IP pubblico sul lato WAN), quindi modifica la porta di origine, ma la riscrive quando ti invia la risposta.

### Application Level Gateway

Gli ALG consentono al NAT di tracciare un protocollo multi-porta come l'FTP che esce dal tuo sistema verso un server FTP, poi tracciare quando richiedi un file da inviare al tuo IP interno su una porta specifica, l'ALG può riscrivere il pacchetto per includere il tuo IP pubblico, quindi inoltrare la connessione del server FTP di ritorno a te. Se non avesse riscritto il tuo IP, il server FTP proverebbe a riconnettersi a te sul tuo IP interno (o non ci proverebbe affatto se si aspetta che l'IP di origine sia lo stesso della connessione di segnalazione).

Da [Wikipedia](https://www.wikiwand.com/en/Application-level_gateway):```
In the context of computer networking, an application-level 
gateway consists of a security component that augments a 
firewall or NAT employed in a computer network. It allows 
customized NAT traversal filters to be plugged into the 
gateway to support address and port translation for certain 
application layer "control/data" protocols such as FTP, 
BitTorrent, SIP, RTSP, file transfer in IM applications, etc. 
In order for these protocols to work through NAT or a 
firewall, either the application has to know about an address/
port number combination that allows incoming packets, or the 
NAT has to monitor the control traffic and open up port 
mappings (firewall pinhole) dynamically as required. 
Legitimate application data can thus be passed through the 
security checks of the firewall or NAT that would have 
otherwise restricted the traffic for not meeting its limited 
filter criteria.

Analisi del Router / Dump del Firmware

Prima di tutto vorrei vedere come i gateway comuni trattano effettivamente i pacchetti e i protocolli multi-porta come FTP, SIP, ecc. Per farlo, vorremo fare reverse engineering del firmware dei router comuni. Potremmo dumpare la flash dai router fisici, ma se riusciamo a ottenere firmware non crittografato dai produttori, saremo in grado di investigare più modelli di router e molto più velocemente.

Inizieremo con un router comune, il Netgear Nighthawk R7000. Una ricerca rapida ci aiuta a trovare un articolo di Netgear con un firmware recente. Una volta scaricato il firmware e decompresso, troviamo un file da 30MB chiamato R7000-V1.0.9.64_10.2.64.chk.```sh tigerblood:~c/ng$ wget http://www.downloads.netgear.com/files/GDC/R7000/R7000-V1.0.9.64_10.2.64.zip --2019-05-19 19:21:13-- http://www.downloads.netgear.com/files/GDC/R7000/R7000-V1.0.9.64_10.2.64.zip Resolving www.downloads.netgear.com (www.downloads.netgear.com)... 104.69.65.243 Connecting to www.downloads.netgear.com (www.downloads.netgear.com)|104.69.65.243|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 31705064 (30M) [application/zip] Saving to: ‘R7000-V1.0.9.64_10.2.64.zip’

R7000-V1.0.9.64_10.2.64.zip 100%[=============================================>] 30.24M 6.25MB/s in 11s

2019-05-19 19:21:24 (2.83 MB/s) - ‘R7000-V1.0.9.64_10.2.64.zip’ saved [31705064/31705064]

tigerblood:~c/ng$ unzip R7000-V1.0.9.64_10.2.64.zip Archive: R7000-V1.0.9.64_10.2.64.zip 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: data tigerblood:~c/ng$ ls -lh R7000-V1.0.9.64_10.2.64.chk -rw-r--r-- 1 samy staff 30M Mar 26 11:46 R7000-V1.0.9.64_10.2.64.chk

root@kitploit:~
![R7000-V1.0.9.64_10.2.64.chk](https://assets.kitploit.com/production/public/readmes/3946/ff37a83fee71d670f7d0298b6c22182a4e55d0e3ec949d82256b532820438723.png)

Il comando `file` non rileva alcuna [informazione magica](https://www.wikiwand.com/en/Magic_number_(programming)), quindi possiamo usare [`binwalk`](https://github.com/ReFirmLabs/binwalk) per scansionare il file alla ricerca di dati annidati.```sh
tigerblood:~c/ng$ binwalk R7000-V1.0.9.64_10.2.64.chk

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
58            0x3A            TRX firmware header, little endian, image size: 31703040 bytes, CRC32: 0xBEF1BB2F, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x21E3F0, rootfs offset: 0x0
86            0x56            LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5436416 bytes
2221098       0x21E42A        Squashfs filesystem, little endian, version 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

Uso macOS e binwalk dipende da alcune app Linux di default che causerebbero il fallimento di binwalk -e (che estrae file) quindi estraggo manualmente (e <3 perl golf).```sh tigerblood:~c/ng$ perl -ne'$@.=$_}{print+substr$@,2221098' R7000-V1.0.9.64_10.2.64.chk > squash.fs

root@kitploit:~
Oppure usa [`inout`](https://github.com/samyk/samytools/blob/master/inout), ad esempio `inout R7000-V1.0.9.64_10.2.64.chk 2221098`.

Potresti usare `dd`, ma vorresti un `bs` (dimensione blocco) grande in modo che produca output rapidamente, ad esempio 1024; tuttavia l'attributo `skip` (per dirgli di iniziare alla posizione del blob squashfs) rispetterebbe la dimensione del blocco e 2221098 non è ovviamente divisibile in modo rapido a mente se non per 2... ora sono curioso.```sh
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 records in
14741000+0 records out
29482000 bytes transferred in 78.363403 secs (376222 bytes/sec)

real	1m18.385s
user	0m12.553s
sys  	1m4.451s

Ora scompattiamo il filesystem squash. Ho creato un fork di un fork di squashfs-tools che gira su macOS e ha il supporto per lzo. Potresti aver bisogno di installare anche xz e lzo. In alternativa, potresti usare sasquatch su Linux.```sh tigerblood:~c/ng$ sudo port install xz lzo ... tigerblood:~c/ng$ git clone https://github.com/samyk/squashfs-tools && cd squashfs-tools/squashfs-tools && make && sudo make install && cd ../..

root@kitploit:~
E infine possiamo decomprimere il squash fs.```sh
tigerblood:~c/ng$ unsquashfs -l -no squash.fs
Parallel unsquashfs: Using 8 processors
1881 inodes (2535 blocks) to write

squashfs-root
squashfs-root/bin
squashfs-root/bin/addgroup
... (many more files) ...

tigerblood:~c/ng$ cd squashfs-root && ls
bin   data  dev   etc   lib   media mnt   opt   proc  sbin  share sys   tmp   usr   var   www

Ora abbiamo il sistema operativo grezzo da esplorare!

Reverse Engineering del Firmware

Trovare File Interessanti

Ora vediamo se riusciamo a trovare file rilevanti per FTP, dato che era un protocollo molto usato, quindi il supporto ALG sarà diffuso tra i router. Uso il mio g tool che è solo un comodo wrapper attorno a egrep.```sh tigerblood:~c/ng/squashfs-root$ find . | g ftp ./usr/bin/tftp ./usr/sbin/bftpd ./usr/sbin/ftp ./usr/sbin/ftpc ./usr/etc/sftp-ssh.service

root@kitploit:~
Niente di interessante, quindi eseguiamo `g` per i file binari il cui contenuto corrisponde a /ftp/, ignorando alcuni file di cui non ci importa.```sh
tigerblood:~c/ng/squashfs-root$ g -la ftp -v '\.(html?|js|gif)$|www/|bin/'
lib/libsmbd-base-samba4.so
lib/libavformat.so.55
lib/libavutil.so.52
lib/libavcodec.so.55
lib/modules/tdts.ko
lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko
lib/libcrypto.so.1.0.0
opt/xagent/certs/ca-bundle-mega.crt
usr/etc/sftp-ssh.service
usr/lib/libnvram.so
usr/lib/libcurl.a
usr/lib/libcurl.so.4.3.0
usr/lib/libcurl.so
usr/share/avahi/service-types
usr/share/libcrypto.so.1.0.0

g scansiona ricorsivamente la directory di lavoro corrente per impostazione predefinita. -l serve per stampare solo i nomi dei file (poiché questi saranno per lo più binari), -a per scansionare file binari, ftp per il testo da trovare, e -v '\.(html?|js|gif)$|www/|bin/' per ignorare file web ed eseguibili (che si trovano in (s)bin/).

I file lib/lib*.{a,so}{.*,} (formato bash) non sono interessanti, quindi scansioniamo di nuovo con meno:```sh tigerblood:~c/ng/squashfs-root$ g -la ftp -v '.(html?|js|gif)$|www/|bin/|lib.*.(so|a)(.|$)' lib/modules/tdts.ko lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko opt/xagent/certs/ca-bundle-mega.crt usr/etc/sftp-ssh.service usr/share/avahi/service-types

root@kitploit:~
### Esplorando Funzioni Potenzialmente Utili

Ok, due file di interesse -- `lib/modules/tdts.ko` potrebbero essere correlati, e `lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko` probabilmente non è correlato ma sembra interessante! Potrei indagare su quello più tardi.```sh
tigerblood:~c/ng/squashfs-root$ file lib/modules/tdts.ko
lib/modules/tdts.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=0aa35748e245e60273ceb5a48641e424d069235b, not stripped
tigerblood:~c/ng/squashfs-root$ strings lib/modules/tdts.ko | g ftp
ftp_decoder_open
ftp_decoder_close
ftp_decode_epsv_resp
ftp_decode_eprt_cmd
ftp_decode_pasv_resp
ftp_decode
ftp_decode_port_cmd
ftp_decoder
check_ftp_ft_rule

Ottimo! Un kernel object (.ko) con funzioni ftp, e con parole come "port", è probabilmente correlato a un ALG FTP. L'FTP RFC 959 spiega il significato del comando PORT:``` DATA PORT (PORT)

The argument is a HOST-PORT specification for the data port to be used in data connection. There are defaults for both the user and server data ports, and under normal circumstances this command and its reply are not needed. If this command is used, the argument is the concatenation of a 32-bit internet host address and a 16-bit TCP port address. This address information is broken into 8-bit fields and the value of each field is transmitted as a decimal number (in character string representation). The fields are separated by commas. A port command would be: PORT h1,h2,h3,h4,p1,p2 where h1 is the high order 8 bits of the internet host address.

root@kitploit:~
### Porte / Servizi da Investigare

Sebbene abbiamo trovato alcune funzioni FTP, siamo più interessati alle porte che possiamo utilizzare. I browser moderni impediscono le connessioni HTTP(S) in uscita verso un certo numero di [porte riservate](https://github.com/samyk/chromium/blob/2d57e5b8afc6d01b344a8d95d3470d46b35845c5/net/base/port_util.cc#L20-L90), incluso FTP, quindi abusare dell'ALG FTP è probabilmente inutile.

Nel 2010, quando [ho dimostrato per la prima volta il NAT Pinning](https://samy.pl/natpin/), ho usato la porta 6667 (IRC) tramite i messaggi DCC CHAT/FILE. Rapidamente, i fornitori di browser hanno bloccato la porta 6667...anche se alcuni usavano un `uint32` (intero senza segno a 32 bit) per memorizzare la porta, verificare se la porta era bloccata e, in caso contrario, connettersi. Per aggirare ciò, è importante notare che le porte TCP sono lunghe 16 bit, quindi se aggiungi 2**16 (65536) alla porta "riservata" scelta, in questo caso 65536+6667=72203, il browser memorizzerebbe 72203, supererebbe la restrizione sulla porta (72203 != 6667), quindi verrebbe inviato allo stack TCP dove viene troncato a 16 bit, che è la porta riservata che volevamo!

Il mio semplice [`base calculator, 3`](https://github.com/samyk/samytools/blob/master/3) mostra questo (db = dec -> bin):```sh
tigerblood:/Users/samy/d$ 3 db 65536 6667 65536+6667
000000010000000000000000
000000000001101000001011
000000010001101000001011

Possiamo vederlo meglio usando il mio strumento diffbits, un semplice strumento per visualizzare somiglianze e differenze tra stringhe di bit, così come tra più gruppi di stringhe di bit, utile per fare reverse engineering di protocolli binari proprietari.

diffbits

Reverse engineering dell'oggetto Kernel

Apri il tuo disassemblatore preferito. Io ho usato Ghidra dei nostri amici della NSA poiché è gratuito e open source.

Alcune delle funzioni che abbiamo visto in tdts.ko tramite strings erano ftp_decode e ftp_decoder, quindi è possibile che altri ALG abbiano una funzione _decode. Diamo un'occhiata...

Ghidra _decode

Bene, un sacco di funzioni _decode... scorrendo verso il basso, una interessante è sip_decode.

Ghidra tdts.ko

Controllando le porte del browser limitate, vediamo che la 5060, la porta SIP predefinita, non è limitata in Chrome :)

Tentativo di inviare un pacchetto SIP in una richiesta HTTP POST

SIP risiede su TCP/UDP 5060, ma i media come RTP (audio) vengono inviati su porte alternative generate al volo. Quando si invia una richiesta per una chiamata SIP, il client SIP sceglie una porta casuale, la apre e la include nell'intestazione SIP. Il tuo NAT dovrebbe vederla e aprirla, assumendo che il SIP ALG sia abilitato (ed è attivo sulla maggior parte dei router per impostazione predefinita).

Supponendo che i NAT leggano i pacchetti SIP riga per riga (SIP è basato su nuove righe come HTTP e non è un protocollo binario), forse ignoreranno l'intestazione HTTP e, una volta arrivati ai dati POST, leggeranno il comando REGISTER e crederanno che si tratti di un pacchetto SIP. Questo ha funzionato nella nostra versione del 2010 per l'IRC DCC. Il NAT ignorava l'intestazione HTTP e analizzava solo il comando IRC DCC.

Cosa divertente, questo ci ha anche permesso di far sì che gli utenti che visitavano il nostro sito si connettessero a un server IRC legittimo, si unissero a un canale e inviassero un messaggio dal loro IP senza che loro lo sapessero! :P Ho dimostrato questa tecnica per inviare email a server di posta con indirizzi IP client prima che la porta 25 fosse bloccata dai browser e prima che i record SPF fossero comuni... pazzia.

Ora, in un test rapido, l'invio di un pacchetto SIP REGISTER sulla porta 5060 tramite una richiesta HTTP POST non sembra funzionare... forse ci sfugge qualcosa dal pacchetto.```javascript // our sip message var sipmsg = 'REGISTER sip:samy.pl;transport=TCP SIP/2.0\r\n' + 'Contact: sip:[email protected]:1234;transport=TCP\r\n\r\n'

// load form in an iframe so user doesn't see it var iframe = document.createElement('iframe') iframe.name = 'iframe' iframe.style.display = 'none' // hide the iframe

// create form var form = document.createElement('form') form.setAttribute('target', 'iframe') // load into iframe form.setAttribute('method', 'POST') // need the POST area where we can add CRLFs form.setAttribute('action', 'http://samy.pl:5060') // "http" server on SIP port 5060 form.setAttribute('enctype', 'multipart/form-data') // ensure our data doesn't get encoded

var textarea = document.createElement('textarea') textarea.setAttribute('name', 'textname') // required textarea.innerHTML = sipmsg form.appendChild(textarea) document.body.appendChild(iframe) document.body.appendChild(form) form.submit()

root@kitploit:~
Se sniffiamo, vediamo (analizzato tramite [`h2b`](https://github.com/samyk/samytools/blob/master/h2b)):```sh
$ unbuffer tcpdump -X port 5060 | h2b
POST / HTTP/1.1
Host: samy.pl:5060
Connection: keep-alive
Content-Length: 191
Cache-Control: max-age=0
Origin: http://samy.pl
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; 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
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://samy.pl/o/sp.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

------WebKitFormBoundaryhcoAd2iSAx3TJA7A
Content-Disposition: form-data; name="textname"

REGISTER sip:samy.pl;transport=TCP SIP/2.0
Contact: <sip:[email protected]:1234;transport=TCP>


------WebKitFormBoundaryhcoAd2iSAx3TJA7A--

Tuttavia, questo non apre la porta, né l'IP viene riscritto come ci aspetteremmo (ne parleremo più avanti), quindi ci deve mancare qualcosa.

Continuare a fare reverse engineering dell'oggetto kernel

Continuiamo a scavare nell'oggetto kernel. Nel disassembly, vediamo il tag "SIP/2.0" da un pacchetto SIP, quindi è probabile che faccia il parsing qui (che "decode" suggerisce).

Ghidra sip_decode

Ah, ecco perché falliamo. Sembra che esegua strncasecmp su INVITE (parsing simile su REGISTER) -- confrontando (case-insensitive, il che è interessante poiché gli INVITE SIP sono in maiuscolo) la parola "INVITE" all'inizio del pacchetto e branches if not equal (assembly ARM bne) a 0, quindi se le parole corrispondono, l'ordine lessicografico sarà 0 e continueremo con ct_sip_get_header che sembra interessante, e altrimenti sembra uscire.

Questo è il problema... mentre possiamo usare un browser web per produrre socket in uscita (TCP via HTTP(S), UDP via TURN con WebRTC), non abbiamo abbastanza controllo sul browser per far iniziare la porzione di dati TCP con la parola "INVITE", come questo modulo si aspetta. Nella versione IRC del 2010, l'ALG IRC guardava solo riga per riga, ignorando tutti i dati dell'intestazione HTTP, poi usava i newline nei dati POST per inviare un valido "IRC DCC". Tuttavia, questo ALG SIP è molto più restrittivo e controllare l'inizio della richiesta non è possibile. Se si usa TLS, l'intestazione crittografata inizierà il pacchetto. Se si usa HTTP, il metodo HTTP inizierà il pacchetto (GET, POST, ecc.). Possiamo sfruttarlo in qualche altro modo?

Investigazione sul Connection Tracking / Application Level Gateway

Netfilter di Linux

Per comprendere meglio il connection tracking e gli Application Level Gateway, possiamo vedere come si comportano in netfilter, lo stack di rete di Linux. Ho creato un grafico degli ALG più comuni e di come si comportano basandomi sul parsing del sorgente Linux.

Linux ALG

Da questo grafico, i più interessanti (che Chrome non blocca) sono sane (backup), sip (voip), pptp (vpn) e h323 (voip). Sceglieremo SIP poiché è uno dei più diffusi tra questi protocolli e lo vediamo già nel firmware di alcuni router.

Linux ha specificamente file nf_conntrack_*.c per gestire il connection tracking per protocollo, e nf_nat_*.c per il packet mangling (modifica).

Diamo una rapida occhiata al modulo di connection tracking SIP

  • module_init(nf_conntrack_sip_init) inizializza questo connection tracker, chiamando nf_conntrack_sip_init
  • nf_ct_helper_init(...AF_INET, IPPROTO_TCP, "sip", SIP_PORT...) ci aspettiamo che la segnalazione arrivi da IPv4 AF_INET TCP IPPROTO_TCP porta 5060 SIP_PORT...questo avviene per UDP, TCP, IPv4 e IPv6
  • sip_help_tcp(...) chiamato quando arriva un pacchetto SIP TCP corrispondente
    • process_sip_msg(...) se questo sembra un potenziale pacchetto SIP
      • se questa è una richiesta

Controllo dei Confini dei Pacchetti

Per quanto ne sappiamo, non possiamo far sì che il browser forzi una connessione TCP in uscita con il traffico che vogliamo, ed è necessario per noi creare un pacchetto TCP/UDP che inizi con un metodo SIP come REGISTER o INVITE.

Flash permetteva socket in uscita, ma in un formato su cui non avevamo pieno controllo. Java richiede permessi. I WebSocket sono ancora HTTP. TLS è crittografato. WebRTC (RFC 7742) è crittografato. STUN (RFC 3489) e TURN (RFC 5766) hanno formati fissi, e TURNS (RFC 7065) è crittografato.

Segmentazione TCP

Ad alto livello, non possiamo controllare l'inizio del pacchetto TCP, ma cosa succede se inviamo un pacchetto troppo grande? Deve esserci una dimensione massima del pacchetto...a quel punto, un pacchetto deve essere frammentato in più pacchetti. Se possiamo superare la dimensione del pacchetto TCP e controllare con precisione parte dei dati, potremmo causare la segmentazione del pacchetto e avere i nostri dati all'inizio del nostro prossimo pacchetto eccedente?

Beh, avremmo bisogno di sapere quanti dati invierà il browser, che sarà diverso per ogni browser, e anche per utente poiché potrebbero inviare intestazioni HTTP diverse. HTTPS non funzionerà poiché la maggior parte del contenuto è crittografata, mentre un HTTP POST ci permette di controllare una grande porzione dell'intestazione.

Per ottenere la dimensione generale del pacchetto, inviamo un HTTP POST grande (6000 byte) con un ID e dati di riempimento tramite un modulo web nascosto al nostro http://our.attack.server:5060/pktsize. Sul server attaccante, eseguiamo un packet sniffer che cerca i confini del nostro pacchetto per determinare la dimensione MTU (Maximum Transmission Unit), la dimensione dell'intestazione IP, eventuali opzioni IP, la dimensione dell'intestazione TCP, eventuali opzioni TCP, la dimensione del pacchetto dati e quale porzione del pacchetto controlliamo.

Eseguiamo anche un server personalizzato che ascolta sulla porta TCP 5060 e risponde con traffico HTTP per accontentare il browser in modo che nulla sembri sospetto dal lato client (un server con una risposta malformata causerebbe errori nella console, o un server che risponde in modo errato terrebbe attivo lo spinner di stato).

POST large form to measure MTU and TCP data size

Cerchiamo inoltre di controllare la dimensione dei dati del pacchetto TCP inviando un'opzione TCP Maximum Segment Size (mss) durante la risposta SYN iniziale per manipolare le dimensioni dei pacchetti in uscita della vittima (RFC 793 x3.1). Questo dice alla macchina vittima di mantenere i pacchetti TCP a una certa dimensione.

Custom Maximum Segment Size (img/sniff1.png)

Puoi farlo su Linux aggiungendo advmss <size> a ip route. Useremo 1500.```sh ip route replace default via [gateway] dev eth0 advmss 1500

root@kitploit:~
Una volta ottenuti i pacchetti, inviamo i dati sulla dimensione al client vittima tramite una POST separata, che invia l'ID della vittima in modo da poterlo correlare con la richiesta originale della vittima. A questo punto, il client ha una buona idea di come riempire i pacchetti per far sì che dati arbitrari finiscano in una posizione specifica all'interno di un pacchetto TCP.

### Frammentazione IP con UDP e TURN

Alcuni NAT consentono l'accesso alle porte UDP solo se la connessione SIP era originariamente UDP, quindi in questo caso usiamo TURN. TURN è un protocollo che supporta il relay per comunicazioni peer-to-peer come SIP e WebRTC. TURN è UDP mentre TURNS (TURN+TLS) è TCP. I browser moderni supportano TURN per WebRTC nel caso non possano stabilire una connessione diretta peer-to-peer per la condivisione di media.

TURN consente l'autenticazione tramite nome utente e password; il nome utente viene inviato in chiaro. È interessante notare che il nome utente non ha limiti di dimensione o caratteri, quindi possiamo usarlo per eseguire lo stesso tipo di overflow di pacchetti.

Poiché TURN utilizza UDP, il pacchetto IP stesso verrà frammentato se supera la dimensione MTU (UDP non supporta la segmentazione). Il secondo pacchetto non avrà solo la porzione di dati sotto il nostro controllo, ma anche l'intestazione UDP! Questo non è importante per il nostro attacco, ma è interessante e può sicuramente generare attacchi alternativi. In definitiva, possiamo eseguire lo stesso attacco tramite UDP allineando il nostro confine di pacchetto in base alla dimensione MTU calcolata anziché MSS, facendo sì che il nostro pacchetto SIP UDP si trovi al confine del secondo pacchetto (con un'intestazione UDP fittizia preposta) consentendoci di inoltrare le porte UDP alla nostra vittima.

## Attacco temporale TCP / Scoperta della sottorete interna e dell'IP

Oh, ancora non funziona! Affinché l'ALG lo tratti come un pacchetto SIP legittimo, l'indirizzo IP a cui stai richiedendo che i dati tornino (nella riga [`Contact`](https://tools.ietf.org/html/rfc2543#section-6.13) del SIP) deve essere l'IP interno (vittima) da cui proviene il pacchetto SIP, che non conosciamo. Solo l'indirizzo IP pubblico del router viene trasmesso al nostro server (poiché il NAT riscrive l'IP sorgente quando esce dal lato pubblico).

Vediamo questo controllo in `nf_conntrack_sip.c` di Linux, nella funzione [process\_sip\_request](https://github.com/samyk/linux/blob/ea2cec24c8d429ee6f99040e4eb6c7ad627fe777/net/netfilter/nf_conntrack_sip.c#L1260):

![Convalida IP SIP REGISTER Via](https://assets.kitploit.com/production/public/readmes/3946/46b6a320ab0e8972a37c8e057cebb36d5fb32905ef2894ea6a06bfe508e7db59.png)

Nel [2010](https://samy.pl/natpin/), abbiamo usato [LiveConnect](https://developer.mozilla.org/en-US/docs/Archive/Web/LiveConnect) che consentiva di eseguire codice Java da Javascript in alcune condizioni, estraendo l'IP locale dell'utente. È diventato obsoleto abbastanza rapidamente.

Su alcuni browser (Chrome, Firefox), possiamo usare [WebRTC](https://www.w3.org/TR/webrtc/) per ottenere l'IP interno della vittima tramite [ICE](https://tools.ietf.org/html/rfc5245) (che usa STUN/TURN/TURNS). Questi sono protocolli per aiutare i peer dietro NAT a determinare informazioni su se stessi. Ironia della sorte, non è necessario utilizzare alcun server nella "richiesta" ICE poiché il browser conosce già il proprio IP interno, e un server STUN/TURN remoto non lo saprebbe comunque a meno che il client non lo invii. Il problema è che non tutti i browser forniscono questo meccanismo.

Oggi, per ottenere l'indirizzo IP locale tramite WebRTC su Chrome, anziché un indirizzo `.local` mDNS/Bonjour, è necessario usare HTTPS, ma per il resto degli attacchi è necessario HTTP, quindi prima rileviamo se siamo su HTTP e, in caso contrario, reindirizziamo a HTTPS. Tentiamo quindi di usare WebRTC per estrarre l'indirizzo IP locale. In ogni caso, reindirizziamo poi a HTTP con gli IP aggiunti all'URL per bypassare le restrizioni cross-origin tramite altri metodi di comunicazione.

### Attacco temporale

Se si utilizza Safari, IE <= 11 o altri che non supportano WebRTC o intenzionalmente non rivelano l'IP interno (Safari), possiamo usare un attacco temporale web per rivelare l'indirizzo IP interno della vittima.

Lo gestiamo creando prima tag HTML `` nascoste nella pagina, tutte indirizzate a gateway comuni (192.168.*.1, 10.0.0.1 e [altri](https://github.com/samyk/slipstream/blob/main/server#L159)), insieme a eventi Javascript `onsuccess` e `onerror`. Ogni volta che un img viene scritto nella pagina, viene avviato un timer e se `onsuccess` si carica, significa che l'IP ha risposto con un server web; se nessun server web è in esecuzione ma l'IP è sulla rete, invierà un TCP RST (reset, che indica porta non aperta), attivando `onerror`. Se nessun IP esiste, non viene inviato alcun RST e la risposta richiede più di 1 secondo, a quel punto sappiamo che l'IP non esiste sulla nostra rete.

Una volta che osserviamo uno di questi eventi attivarsi, conosciamo una potenziale sottorete interna su cui ci troviamo, quindi eseguiamo lo stesso attacco per ogni IP sulla sottorete (es., 192.168.0.[2-255]), e questa volta eseguiamo un timing più preciso per determinare quale IP risponde **più velocemente**. Questo è molto probabilmente il nostro IP interno (vittima), poiché non dobbiamo nemmeno uscire dall'interfaccia di rete. Anche se per qualche motivo non siamo i primi, tentiamo comunque il nostro attacco su tutti gli IP che hanno risposto sulla rete.

## Confusione del protocollo nel browser

Una volta che il client ottiene le dimensioni dei pacchetti e l'indirizzo IP interno, costruisce un modulo web appositamente progettato che riempie i dati POST fino a quando riteniamo che il pacchetto si frammenterà, a quel punto viene aggiunto il nostro REGISTER SIP contenente l'indirizzo IP interno. Il modulo viene inviato tramite Javascript senza il consenso della vittima. :)

[![Pacchetto riuscito trasformato in un pacchetto SIP valido](https://assets.kitploit.com/production/public/readmes/3946/9d8133cafc497975e4bfc89034da0246e8bdd460f73b213e91d71bf14dd097e6.png)](img/pinpkt.png)

### Alterazione live del pacchetto nel browser

Sul nostro server di attacco, poiché possiamo vedere i pacchetti in arrivo, controlliamo se il pacchetto SIP è stato riscritto con l'indirizzo IP pubblico. Se non lo è, comunichiamo automaticamente al client che il pacchetto SIP non si trovava sul confine di pacchetto previsto e non è stato riscritto, e forniamo la nuova posizione del confine dal nostro sniffer.

Il codice client regola automaticamente la dimensione del pacchetto alla nuova dimensione solo dopo due fallimenti consecutivi. Alcuni browser (Firefox) a volte hanno una dimensione del pacchetto leggermente diversa a causa del multipart-boundary che generano per il modulo, che, a differenza della maggior parte degli altri browser, non ha una lunghezza fissa. Ho scoperto che dopo circa 10 tentativi, verrà utilizzata la stessa dimensione e l'attacco avrà successo.

Una volta che il pacchetto SIP si posiziona sul confine del pacchetto, il NAT verrà ingannato, credendo che si tratti di una registrazione SIP legittima proveniente da un client SIP sulla macchina della vittima. Una volta che il nostro server risponde con una corretta risposta SIP (annidata all'interno di una corretta risposta HTTP per evitare che il browser rilevi qualcosa di sospetto), il NAT aprirà la porta nel pacchetto originale che abbiamo fatto inviare alla vittima e il router ora **inoltrerà qualsiasi porta scelta dall'attaccante verso la vittima interna, tutto semplicemente navigando su un sito web**.

Attacco completato. L'attaccante può ora connettersi a servizi TCP/UDP arbitrari in esecuzione sulla vittima.

# Altre scoperte

Queste non sono utilizzate in questo attacco, ma sono comunque interessanti e potrebbero potenzialmente essere usate per altri attacchi.

- La frammentazione IP consente il controllo completo di tutti i dati nella sezione dati IP, il che significa il controllo completo di un'intestazione UDP inclusi porte sorgente/destinazione nel pacchetto overflow
  - Lo stack IP della vittima riassembla e non analizzerà i dati, tuttavia il NAT attraverso cui passa il pacchetto sarà vulnerabile
  - Consente di bypassare il firewall del browser o di sistema poiché solo la porta UDP del pacchetto originale viene ispezionata, non quella del pacchetto frammentato in overflow
- DoS su un client SIP inviando `Expires: 0` e rimuovendo il conntrack per qualcun altro
- Se una porta è già occupata, la porta ascoltata viene incrementata fino a quando la porta non va in overflow a 0
- STUN non ha autenticazione implementata in nessun browser moderno

# Download

Grazie per aver letto! Puoi scaricare il codice proof of concept dal mio [github di NAT Slipstream](https://github.com/samyk/slipstream).

# Contatti

**Punto di contatto:** [@SamyKamkar](https://twitter.com/samykamkar)

Trova altri miei progetti su <https://samy.pl> o eventualmente contattami a <[email protected]>.
Scarica lo strumento
RFC 793 x3.1
  • viene inviato un grande beacon UDP dal browser tramite il meccanismo di autenticazione TURN di WebRTC su una porta non standard al server dell'attaccante per forzare la frammentazione IP con il campo username TURN riempito
    • eseguiamo un attacco simile alla nostra segmentazione TCP, ma su UDP poiché la frammentazione IP avverrà e fornirà valori diversi dalla segmentazione TCP
    • dimensione MTU della vittima, dimensione dell'intestazione IP, dimensione del pacchetto IP, dimensione dell'intestazione TCP, dimensioni dei segmenti TCP rilevate dal server e inviate al browser della vittima, utilizzate successivamente per il riempimento dei pacchetti
  • (v1) viene generato un "pacchetto SIP" in un nuovo modulo nascosto, contenente l'IP interno per attivare il connection tracking dell'Application Level Gateway
    • viene avviato un "HTTP POST" al server sulla porta TCP 5060 (porta SIP), evitando le porte del browser bloccate
    • i dati POST vengono "riempiti" per adattarsi esattamente alla dimensione del segmento TCP / confine del pacchetto, quindi il "pacchetto SIP" viene aggiunto e pubblicato tramite modulo web
    • lo stack IP della vittima divide il POST in più pacchetti TCP, lasciando il "pacchetto SIP" (parte dei dati POST) nel proprio pacchetto TCP senza alcuna intestazione HTTP di accompagnamento
    • se il browser altera la dimensione del boundary multipart/form (Firefox) o la dimensione del pacchetto cambia per qualsiasi altro motivo, la modifica di dimensione viene comunicata al client e il client reinvia automaticamente con la nuova dimensione
    • quando si apre la porta UDP, il pacchetto SIP viene inviato tramite il protocollo TURN all'interno del campo username appositamente costruito per forzare la frammentazione IP e un controllo preciso dei confini
  • (v2) viene generato un "pacchetto H.323" utilizzando una connessione STUN basata su TCP (bypassando le patch per la v1 e le restrizioni sulle porte del browser), contenente l'IP interno per attivare il connection tracking dell'Application Level Gateway, ma forzando un reindirizzamento a qualsiasi altro host sulla rete in un pacchetto di "inoltro chiamata"
    • viene avviato un "inoltro chiamata H.323" al server sulla porta TCP 1720 (porta H.323), evitando le porte del browser bloccate, nonostante la porta sia bloccata -- l'evasione della porta viene eseguita utilizzando la funzione STUN di WebRTC che non rispetta l'elenco delle porte bloccate
    • il campo username viene "riempito" per adattarsi esattamente alla dimensione del segmento TCP / confine del pacchetto, quindi il “pacchetto H.323” viene aggiunto e pubblicato tramite modulo web
    • lo stack IP della vittima divide il POST in più pacchetti TCP, lasciando il "pacchetto H.323" (parte dei dati STUN) nel proprio pacchetto TCP senza alcuna intestazione HTTP di accompagnamento
    • se il browser altera la dimensione del boundary multipart/form (Firefox) o la dimensione del pacchetto cambia per qualsiasi altro motivo, la modifica di dimensione viene comunicata al client e il client reinvia automaticamente con la nuova dimensione
  • il NAT della vittima vede un corretto pacchetto SIP REGISTER sulla porta SIP o un corretto pacchetto di inoltro chiamata H.323 (senza dati HTTP), attivando l'ALG per aprire qualsiasi porta TCP/UDP definita nel pacchetto verso qualsiasi host della vittima sulla rete
    • il NAT della vittima riscrive il pacchetto SIP o H.323, sostituendo l'IP interno con l'IP pubblico, segnalando all'attaccante che lo sfruttamento è riuscito
    • (v2) poiché l'inoltro chiamata H.323 può dirigere verso qualsiasi altro IP, il pacchetto può contenere qualsiasi IP interno di qualsiasi altro host sulla rete della vittima, inducendo il NAT a inoltrare la porta verso qualsiasi sistema sulla rete
    • anche se il NAT della vittima normalmente riscrive le porte di origine, l'ALG sarà comunque costretto a inoltrare la porta verso la porta scelta dall'attaccante poiché crede che la macchina della vittima (o un'altra macchina sulla rete, interamente determinata dall'attaccante) abbia aperto quella porta e l'attaccante vede la nuova porta di origine nel pacchetto SIP/H.323 in arrivo
    • l'attaccante può ora bypassare il NAT della vittima e connettersi direttamente a qualsiasi porta su qualsiasi macchina sulla rete, esponendo servizi e sistemi precedentemente protetti/nascosti
  • da investigare...forse da te?
    • uso non malevolo: questa tecnica fornisce essenzialmente ai browser la piena capacità di socket TCP e UDP per comunicare con qualsiasi protocollo localmente sul sistema; la connessione può essere astratta tramite un server cloud che si riconnette ma il browser comunica solo con il server cloud come se fosse il socket, rendendo i browser molto più potenti per comunicare su protocolli non web-friendly
    • se si testa in una macchina virtuale (VM) utilizzando la rete condivisa (usata per proteggere un host dagli attacchi instradandoli attraverso l'host, non permettendogli di andare direttamente sulla rete), se i pacchetti riescono a uscire, la macchina host genitore è dove le porte vengono aperte, non la VM ;)
    • la frammentazione IP permette il controllo completo di tutti i dati nella sezione dati IP, il che significa controllo completo dell'intestazione UDP, incluse le porte di origine/destinazione nel pacchetto overflow...cos'altro potrebbe abusare di questo?
  • process_sip_request(...)
  • strncasecmp(*dptr, handler->method, ...) il gestore uscirà a meno che il metodo (es. REGISTER) non si trovi all'inizio della porzione di dati del pacchetto (TCP o UDP) come abbiamo visto con INVITE sopra...REGISTER è solo un altro comando SIP
  • questa è una sfida perché se usiamo solo un browser web, non possiamo produrre una connessione TCP grezza e far iniziare un pacchetto con i nostri dati, poiché sarà riempito con intestazioni HTTP/TLS...o possiamo?
  • process_register_request(...)nf_ct_expect_init(...) via sip_handlers inizializziamo il pinhole del firewall (porta per permettere a una persona remota di riconnettersi), ma non lo apriamo ancora
  • nf_nat_sip_hooks -> nf_nat_sip(...) il NAT modifica (riscrive) l'indirizzo IP interno del client nell'IP pubblico del NAT in modo che la destinazione possa raggiungerlo correttamente
  • sip_help_tcp(...) -> process_sip_msg(...) ->
    • process_sip_response(...) ora stiamo guardando la risposta SIP dal server SIP
      • process_register_response(...) -> refresh_signalling_expectation(...) la porta viene inoltrata dal NAT solo dopo che una valida risposta SIP viene inviata dal server SIP