Fronting de domini basat en TLS 1.3. Part 2

Introducció

A la primera part Article Hem fet una breu descripció del mecanisme SNI xifrat (eSNI). Van mostrar com, a partir d'això, és possible evadir la detecció dels sistemes DPI moderns (utilitzant l'exemple de Beeline DPI i el rastrejador d'arrel RKN prohibit), i també van explorar una nova versió del fronting de domini basada en aquest mecanisme.

A la segona part de l'article, passarem a coses més pràctiques que seran útils als especialistes de RedTeam en la seva tasca difícil. Al final, el nostre objectiu no és accedir als recursos bloquejats (per a coses tan trivials tenim la bona VPN antiga). Afortunadament, hi ha una gran varietat de proveïdors de VPN, com diuen, per a tots els gustos, color i pressupost.

Intentarem aplicar el mecanisme de front del domini a les eines modernes de RedTeam, per exemple, com Cobalt Strike, Empire, etc., i donar-los capacitats addicionals per imitar i evadir els sistemes moderns de filtratge de contingut.

La darrera vegada vam implementar el mecanisme eSNI a la biblioteca OpenSSL i el vam utilitzar amb èxit a la utilitat curl familiar. Però, com diuen, no et satisfaràs només amb un pollastre. Per descomptat, m'agradaria implementar alguna cosa semblant en llenguatges d'alt nivell. Però, malauradament, una cerca ràpida a través d'Internet ens decep, perquè el suport per al mecanisme eSNI només s'implementa completament a GOLANG. Per tant, no tenim gaire opció: o escrivim en C o C++ pur utilitzant la biblioteca OpenSSL pegada, o fem servir una forquilla GOLANG separada de CloudFlare i intentem portar les nostres eines allà. En principi, hi ha una altra opció, més clàssica, però alhora que requereix molt de temps: implementar el suport eSNI per a Python. Després de tot, Python també utilitza OpenSSL per gestionar https. Però deixarem aquesta opció per al desenvolupament d'una altra persona, i nosaltres mateixos ens contentarem amb la implementació a Golang, sobretot perquè el nostre estimat Cobalt Strike és perfectament capaç de treballar amb un canal de comunicació construït per eines de tercers (canal C2 extern). - En parlarem al final de l'article.

Esforçar-se més...

Una de les eines implementades a Go és el nostre desenvolupament per pivotar a la xarxa: un tunelador rsockstun, que, per cert, ara és detectat per eines de Microsoft i Symantec com a programari molt maliciós destinat a interrompre l'estabilitat global...

Fronting de domini basat en TLS 1.3. Part 2

Seria fantàstic utilitzar el desenvolupament anterior també en aquest cas. Però aquí sorgeix un petit problema. El fet és que inicialment rsockstun implica l'ús d'un canal de comunicació SSL síncron amb el servidor. Això vol dir que la connexió s'estableix una vegada i existeix durant tota la durada de l'explotació del túnel. I, com enteneu, el protocol https no està pensat per a aquest mode d'operació: funciona en mode petició-resposta, on cada nova sol·licitud http existeix dins d'una nova connexió TCP.

El principal desavantatge d'aquest esquema és que el servidor no pot transferir dades al client fins que el client envia una nova sol·licitud http. Però, afortunadament, hi ha moltes opcions per resoldre aquest problema: transmetre dades mitjançant el protocol http (al cap i a la fi, d'alguna manera aconseguim veure els nostres programes de televisió preferits i escoltar música des de portals que funcionen amb https, però transmetre vídeo i àudio no és una altra cosa). que la transmissió de dades). Una de les tecnologies per emular el funcionament d'una connexió TCP completa a través del protocol HTTP és la tecnologia WebSockets, l'essència principal de la qual és organitzar una connexió de xarxa completa entre el client i el servidor web.

Afortunadament per a nosaltres (hurra!!!), aquesta tecnologia s'inclou de manera predeterminada a tots els plans de tarifes de CloudFlare i funciona molt bé en combinació amb eSNI. Això és exactament el que farem servir per ensenyar al nostre tunelador a utilitzar el front de domini i amagar-nos dels DPI moderns.

Una mica sobre WebSockets

En primer lloc, explicarem breument i senzillament els websockets perquè tothom tingui una idea de què treballarem.

La tecnologia Websocket us permet canviar temporalment d'una connexió http a una connexió de xarxa estàndard sense trencar la connexió TCP establerta. Quan un client vol canviar a un websocket, estableix diverses capçaleres http a la seva sol·licitud http. Dues capçaleres necessàries - Connexió: Actualització и Actualització: websocket. També pot especificar amb força la versió del protocol websocket (Sec-Websockset-Versió: 13) i alguna cosa així com un identificador de base64 websocket (Sec-WebSocket-Key: DAGDJSiREI3+KjDfwxm1FA==). El servidor li respon amb el codi http 101 Switching Protocols i també estableix les capçaleres Connexió, actualització и Sec-WebSocket-Acceptar. El procés de canvi es mostra clarament a la captura de pantalla següent:

Fronting de domini basat en TLS 1.3. Part 2

Després d'això, la instal·lació de la connexió WebSocket es pot considerar completa. Qualsevol dada tant del client com del servidor no es subministrarà amb http, sinó amb capçaleres WebSocket (comencen amb el byte 0x82). Ara el servidor no necessita esperar una sol·licitud del client per transferir dades, perquè La connexió tcp no està trencada.

Golang té diverses biblioteques per treballar amb websockets. Els més populars d'ells són Gorilla WebSocket i estàndard websocket. Utilitzarem aquest últim, perquè... és més senzill, més petit i, com diuen, funciona una mica més ràpid.

Al codi de client rsockstun, hem de substituir les trucades net.dial o tls.dial per les trucades WebSocket corresponents:

Fronting de domini basat en TLS 1.3. Part 2

Fronting de domini basat en TLS 1.3. Part 2

Volem que el client sigui part del nostre túnel universal i capaç de funcionar tant mitjançant una connexió SSL directa com mitjançant el protocol WebSockset. Per a això crearem una funció separada func connectForWsSocks (cadena d'adreça, cadena de proxy) {…} per analogia amb connectForSocks() i l'utilitzarem per treballar amb sockets web si l'adreça del servidor especificada en iniciar el client comença amb ws: o wss: (en el cas de Secure WebSocket).

Per al costat del servidor del túnel, també farem una funció independent per treballar amb sockets web. Crearà una instància de la classe http i establirà el controlador de connexió http (funció wsHandler):

Fronting de domini basat en TLS 1.3. Part 2

I col·locarem tota la lògica de processament de connexió (autorització del client mitjançant una contrasenya, configuració i finalització d'una sessió de yamux) al gestor de connexions WebSocket:

Fronting de domini basat en TLS 1.3. Part 2

Compilem el projecte i iniciem la part del servidor:

./rsockstun –listen ws:127.0.0.1:8080 –pass P@ssw0rd

I després la part del client:

./rsockstun -connect ws:127.0.0.1:8080 –pass P@ssw0rd

I comprovem el treball a l'amfitrió local:

Fronting de domini basat en TLS 1.3. Part 2

Fronting de domini basat en TLS 1.3. Part 2

Passem al fronting del domini

Sembla que hem descobert els websockets. Ara passem directament a eSNI i fronting de domini. Com s'ha esmentat anteriorment, per treballar amb DoH i eSNI hem d'agafar una sucursal especial de golang de l'empresa. CloudFlare. Necessitem una branca amb suport eSNI (pwu/esni).

El clonem localment o descarreguem i descomprimim el zip corresponent:

git clone -b pwu/esni https://github.com/cloudflare/tls-tris.git

Aleshores hem de copiar el directori GOROOT, substituir els fitxers corresponents de la branca clonada i establir-lo com a mestre. Per salvar el desenvolupador d'aquest mal de cap, els nois de CloudFlare han preparat un script especial: _dev/go.sh. Acabem de llançar-lo. L'script juntament amb el fitxer makefile ho faran tot ells mateixos. Només per diversió, podeu mirar dins del makefile per obtenir-ne més detalls.

Després d'executar l'script, en compilar el projecte, haurem d'especificar el directori local preparat per l'script com a GOROOT. En el nostre cas es veu així:

GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" go build ….

A continuació, hem d'implementar al túnel la funcionalitat de sol·licitar i analitzar claus eSNI públiques per al domini desitjat. En el nostre cas, aquestes seran claus eSNI públiques dels servidors frontend de CloudFlare. Per fer-ho, crearem tres funcions:

func makeDoTQuery(dnsName string) ([]byte, error)
func parseTXTResponse(buf []byte, wantName string) (string, error)
func QueryESNIKeysForHost(hostname string) ([]byte, error)

Els noms de les funcions, en principi, parlen per si mateixos. Prendrem el contingut del fitxer esni_query.go, que forma part de tls-tris. La primera funció crea un paquet de xarxa amb una sol·licitud al servidor DNS de CloudFlare mitjançant el protocol DoH (DNS-over-HTTPS), la segona analitza els resultats de la consulta i obté els valors de les claus públiques del domini, i la tercera és un recipient per als dos primers.

A continuació, afegim una connexió de connexió web a la nostra funció de nova creació connectForWsSocks funcionalitat per sol·licitar claus eSNI per a un domini. On opera la part del servidor, establim els paràmetres TLS i també establim el nom del "domini de cobertura" fals:

Fronting de domini basat en TLS 1.3. Part 2

Cal assenyalar aquí que inicialment, la branca tls-tris no estava dissenyada per a l'ús de fronting de domini. Per tant, no presta atenció al nom del servidor fals (un camp serverName buit s'envia com a part del paquet client-hello). Per solucionar-ho, haurem d'afegir el camp FakeServerName corresponent a l'estructura TlsConfig. No podem utilitzar el camp ServerName estàndard de l'estructura, perquè l'utilitzen els mecanismes interns de tls i si és diferent de l'original, l'encaix de tls acabarà amb un error. Al fitxer hi ha una descripció de l'estructura TlsConfig tls/common.go - l'hem d'arreglar:

Fronting de domini basat en TLS 1.3. Part 2

Fronting de domini basat en TLS 1.3. Part 2

A més, haurem de fer canvis al fitxer tls/handshake_client.goper utilitzar el nostre camp FakeServerName en formar una encaixada de mans TLS:

Fronting de domini basat en TLS 1.3. Part 2

Això és tot! Podeu compilar el projecte i comprovar el treball. Però abans d'executar l'exploració, heu de configurar un compte de CloudFlare. Bé, com puc dir que configureu-lo: només heu de crear un compte a Cloudflare i enllaçar-hi el vostre domini. Totes les funcions relacionades amb DoH, WebSocket i ESNI s'inclouen a CloudFlare de manera predeterminada. Un cop actualitzats els registres DNS, podeu comprovar el funcionament del domini consultant les claus eSNI:

dig +short txt _esni.df13tester.info 

Fronting de domini basat en TLS 1.3. Part 2

Si veieu alguna cosa semblant per al vostre domini, vol dir que tot us funciona i podeu procedir a la prova.

Llançament Ubuntu Un VPS, per exemple, a DigitalOcean. PD: En el nostre cas, l'adreça IP del VPS que acabàvem de rebre del nostre proveïdor va acabar a la llista negra de Roskomnadzor. Així que no us estranyeu si us passa alguna cosa similar. Vaig haver de fer servir una VPN per accedir al meu VPS.

Copiem el rsockstun ja compilat al VPS (això, per cert, és una altra bellesa de Golang: podeu compilar el projecte pel vostre compte i executar-lo a qualsevol Linux, observant només la capacitat de bits del sistema) i llançar la part del servidor:

Fronting de domini basat en TLS 1.3. Part 2

I després la part del client:

Fronting de domini basat en TLS 1.3. Part 2

Com podem veure, el client es va connectar correctament al servidor mitjançant el servidor frontend de CloudFlare mitjançant un websocket. Per comprovar que el túnel funciona exactament com un túnel, podeu fer una sol·licitud de curl a través de local socks5, obert al servidor:

Fronting de domini basat en TLS 1.3. Part 2

Ara vegem què veu DPI al canal de comunicació:

Fronting de domini basat en TLS 1.3. Part 2

En primer lloc, el tunelador, mitjançant el mecanisme DoH, contacta amb el servidor DNS de Cloudflare per obtenir claus eSNI per al domini de destinació (paquets núm. 1-19) i després es posa en contacte amb el servidor frontend i estableix una connexió TLS, amagant-se darrere del domini. www.google.com (aquest és el valor per defecte quan no s'especifica cap domini fals quan s'inicia el client). Per especificar el vostre domini fals, heu d'utilitzar el paràmetre -fronfDomain:

Fronting de domini basat en TLS 1.3. Part 2

Fronting de domini basat en TLS 1.3. Part 2

Ara una cosa més. De manera predeterminada, la configuració del compte de CloudFalre s'estableix en SSL flexible. Això vol dir que les sol·licituds https als servidors frontend de Cloudflare dels clients s'enviaran sense xifrar (http) al nostre servidor. És per això que hem llançat la part del servidor del túnel en mode no ssl ( -listen ws:0.0.0.0) i no ( -listen wss:0.0.0.0).

Fronting de domini basat en TLS 1.3. Part 2

Per canviar al mode de xifratge complet, heu de seleccionar CompletO Complet (estricte) si hi ha un certificat real al servidor. Després de canviar el mode, podrem acceptar connexions de CloudFlare mitjançant el protocol https. No oblideu generar un certificat autofirmat per al costat del servidor del túnel.

Fronting de domini basat en TLS 1.3. Part 2

El lector curiós preguntarà: "Què passa amb el client que està sota la seva Windows"Al cap i a la fi, l'ús principal d'un tunelador és probablement establir una connexió de backend des de màquines i servidors corporatius, i aquests solen ser sempre Windows. Com puc compilar un tunelador per a Windows, especialment amb una pila TLS específica?" Ara introduirem una altra característica que demostra com de convenient és Golang. Compilem per a Windows directament des de Kali simplement afegint el paràmetre GOOS=windows:

GOARCH=amd64 GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" GOOS=windows  go build -ldflags="-s -w"

O la versió de 32 bits:

GOARCH=386 GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" GOOS=windows  go build -ldflags="-s -w"

Tot! I no calen més molèsties. Realment funciona!

Fronting de domini basat en TLS 1.3. Part 2

Els indicadors del compilador –w i –s són necessaris per eliminar les escombraries innecessàries del fitxer executable, fent-lo un parell de megabytes més petit. A més, es pot empaquetar amb UPX per reduir encara més la mida.

En lloc d'una conclusió

A l'article, utilitzant l'exemple d'un túnel escrit en Golang, vam demostrar clarament l'ús de la nova tecnologia de front de domini, implementada en una característica força interessant del protocol TLS 1.3. De la mateixa manera, podeu adaptar les eines existents escrites a Golang perquè funcionin a través dels servidors CloudFlare, per exemple Esmerla - famós C2, o forçar CobaltStrike Beacon a utilitzar el domini eSNI quan es treballa amb Teamserver mitjançant Canal C2 extern, implementat a Golang, o en C++ estàndard utilitzant una versió pegada d'OpenSSL, de la qual vam parlar a l'última part de l'article. En general, no hi ha límits a la imaginació.

L'exemple amb el tunneler i CloudFlare es presenta en forma de concepte i encara és difícil dir sobre les perspectives a llarg termini d'aquest tipus de fronting de domini. De moment, només CloudFlare admet eSNI i, en teoria, res els impedeix desactivar aquest tipus de fronting i, per exemple, trencar les connexions tls si SNI i eSNI no coincideixen. En general, el futur ho dirà. Però de moment, la perspectiva de treballar sota la "coberta de kremlin.ru" sembla força temptadora. No és això?

El codi del tunelador actualitzat, així com els fitxers exe executables compilats, es troben en una branca separada del projecte a GitHub. És millor escriure un problema sobre tots els possibles problemes del tunelador a la pàgina del projecte a GitHub.

Font: www.habr.com

Compreu allotjament fiable per a llocs amb protecció DDoS, servidors VPS VDS 🔥 Compra allotjament web fiable amb protecció DDoS, servidors VPS VDS | ProHoster