Domæne-forfrontning baseret på TLS 1.3. Del 2

Introduktion

I den første del artikler gav vi en kort beskrivelse af mekanismen encrypted SNI (eSNI). Vi viste, hvordan man kan undgå detektion af moderne DPI-systemer (ved hjælp af Beeline's DPI og det forbudte RKN ruTracker), samt undersøgte en ny variant af domæne-fronting baseret på denne mekanisme.

I den anden del af artiklen vil vi gå videre til mere praktiske emner, der vil være nyttige for RedTeam-specialister i deres vanskelige arbejde. I sidste ende er vores mål ikke at få adgang til blokkerede ressourcer (til sådanne banale ting har vi den gamle gode VPN). Heldigvis findes der mange VPN-udbydere, som man siger, til enhver smag, farve og budget.

Vi vil forsøge at anvende domæne-fronting-mekanismen til moderne RedTeam-værktøjer, såsom Cobalt Strike, Empire osv., og give dem yderligere muligheder for at efterligne og undgå moderne indholdsfileringssystemer.

Sidste gang implementerede vi eSNI-mekanismen i OpenSSL-biblioteket og brugte den med succes i det velkendte værktøj curl. Men man kan ikke leve af curl alene, som man siger. Selvfølgelig ønsker man at realisere noget lignende i høj-niveau programmeringssprog. Desværre skuffer en hurtig søgning på nettet os, da eSNI-mekanismen kun er fuldt ud implementeret i GOLANG. Så vores valg er ikke særlig stort: enten skriver vi i rent C eller C++ ved hjælp af den patchede OpenSSL-bibliotek, eller vi bruger en separat fork af GOLANG fra CloudFlare og forsøger at portere vores værktøjer dertil. Principielt er der også en anden, mere klassisk, men samtidig ressourcekrævende mulighed - at implementere eSNI-support for Python. I sidste ende bruger Python også OpenSSL til at arbejde med https. Men denne mulighed vil vi lade nogen andre udvikle, og selv vil vi nøjes med implementeringen i golang, især fordi vores elskede Cobalt Strike kan arbejde med forbindelseskaneler, der er oprettet af tredjeparts værktøjer (External C2 channel) – dette vil vi forklare i slutningen af artiklen.

Prøv hårdere…

Et af de implementerede værktøjer i Go – vores udvikling til pivoting ind i netværket – tunneler rsockstun, som for øvrigt nu bliver registreret af virksomhederne Microsoft og Symantec som meget skadelig software, der er rettet mod at understøtte global ustabilitet…

Domæne-forfrontning baseret på TLS 1.3. Del 2

Det ville være fantastisk at anvende den tidligere udvikling i denne situation. Men her opstår der et lille problem. Det viser sig, at rsockstun oprindeligt forudsætter brugen af en synkron SSL-forbindelse til serveren. Det betyder, at forbindelsen oprettes én gang og eksisterer hele tiden, mens tunnelen er aktiv. Som du forstår, er HTTPS-protokollen ikke rigtig designet til denne driftsform – den fungerer i en anmodnings-respons-tilstand, hvor hver ny HTTP-anmodning eksisterer inden for en ny TCP-forbindelse.

Den primære ulempe ved en sådan ordning er, at serveren ikke kan sende data til klienten, før klienten sender en ny HTTP-anmodning. Men heldigvis findes der mange løsninger på dette problem – streaming af data gennem HTTP-protokollen (for vi formår jo at se vores yndlingsserier og lytte til musik fra portaler, der kører på HTTPS, og overførsel af video og lyd er i bund og grund blot streaming af data). En af teknologierne til at emulere en fuldt udbygget TCP-forbindelse på toppen af HTTP-protokollen er WebSockets, hvis hovedidé er at oprette et realtidsforbindelse mellem klienten og webserveren.

Til vores held (hurra-hurra!!!) er denne teknologi aktiveret som standard i alle CloudFlare-abonnementer og fungerer perfekt sammen med eSNI. Det er netop denne, vi vil bruge til at lære vores tunneler at anvende domain fronting og skjule sig for moderne DPI.

Lidt om WebSockets

Først og fremmest vil vi kort og enkelt forklare, hvad web-sockets er, så alle har en idé om, hvad vi arbejder med.

WebSocket-teknologien gør det muligt midlertidigt at skifte fra en HTTP-forbindelse til standard streaming via et netværkssocket uden at afbryde den etablerede TCP-forbindelse. Når klienten ønsker at skifte til WebSocket, angiver den i sin HTTP-anmodning flere HTTP-headere. To obligatoriske headere er Connection: Upgrade og Upgrade: websocket. Desuden kan den tvinge versionen af WebSocket-protokollen (Sec-WebSocket-Version: 13) og noget som en base64 identifikator for webSocket (Sec-WebSocket-Key: DAGDJSiREI3+KjDfwxm1FA==). Serveren svarer med http-koden 101 Switching Protocols og sætter desuden overskrifterne Connection, Upgrade og Sec-WebSocket-Accept. Overgangen er vist i billedet nedenfor:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Efter dette kan WebSocket-forbindelsen betragtes som afsluttet. Fremover vil al data, både fra klienten og serveren, blive forsynet med WebSocket-overskrifter (de starter med byte 0x82). Serveren behøver ikke længere vente på en anmodning fra klienten for at sende data, da tcp-forbindelsen ikke brydes.

I Go findes der flere biblioteker til arbejde med webSockets. De mest populære er Gorilla WebSocket og den standard WebSocket. Vi vil bruge sidstnævnte, da den er enklere, mindre og fungerer, som det siges, lidt hurtigere.

I rsockstun-klientkoden skal vi erstatte kald til net.dial eller tls.dial med de tilsvarende WebSocket-kald:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Domæne-forfrontning baseret på TLS 1.3. Del 2

Vi ønsker at gøre klientdelen af vores tunnel universel og i stand til at fungere både gennem direkte ssl-forbindelse og gennem WebSocket-protokollen. For dette formål opretter vi en separat funktion func connectForWsSocks(address string, proxy string) error {…} analogous to connectForSocks() og vi vil bruge den til at arbejde med webSockets, hvis serverens adresse, angivet ved klientens start, starter med ws: eller wss: (i tilfælde af Secure WebSocket).

For serverdelen af tunnelen vil vi også lave en separat funktion til at arbejde med webSockets. Her vil der blive oprettet et http-klasse eksempel og angivet en http-forbindelse behandler (funktionen wsHandler):

Domæne-forfrontning baseret på TLS 1.3. Del 2

Og al logik til håndtering af forbindelsen (godkendelse af klienten via adgangskode, oprettelse og afslutning af yamux-sessionen) vil vi placere i WebSocket-forbindelsesbehandleren:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Vi kompilere projektet, starter serverdelen:

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

Og derefter klientdelen:

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

Og vi tester det på localhost:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Domæne-forfrontning baseret på TLS 1.3. Del 2

Lad os gå videre til domæne-fremføring

Vi har tilsyneladende forstået webSockets. Lad os nu gå videre til eSNI og domæne-fremføring. Som tidligere nævnt, for at arbejde med DoH og eSNI, skal vi tage en speciel Go-gren fra virksomheden CloudFlare. Vi har brug for en gren med støtte for eSNI (pwu/esni).

Klon den lokalt eller download og udpakk den relevante zip:

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

Derefter skal vi kopiere GOROOT-katalogen, erstatte de relevante filer fra den klonede gren og installere den som primær. For at befri udvikleren for dette hovedbrud har folkene fra CloudFlare forberedt et specielt script – _dev/go.sh. Vi kører det simpelthen. Scriptet sammen med makefile vil klare det hele. For nysgerrighedens skyld — du kan kigge ind i makefile for detaljer.

Efter scriptet er kørt, skal vi angive den lokale mappe, som scriptet forberedte, som GOROOT, når vi kompilere projektet. I vores tilfælde ser det således ud:

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

Dernæst skal vi implementere funktionen i tunnelen til at anmode om og parset eSNI-nøgler for det ønskede domæne. I vores tilfælde vil det være de offentlige eSNI-nøgler fra CloudFlare frontend-servere. For dette vil vi oprette tre funktioner:

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

Funktionsnavnene taler i princippet for sig selv. Indholdet vil vi tage fra filen esni_query.go, som er en del af tls-tris. Den første funktion opretter en netværkspakke med en anmodning til CloudFlare DNS-serveren, ved at bruge DoH-protokollen (DNS-over-HTTPS), den anden parser anmodningens resultater og henter værdierne for de offentlige domænenøgler, mens den tredje fungerer som en container for de to første.

Derefter tilføjer vi i vores nyoprettede funktion til at oprette en websockets-forbindelse connectForWsSocks funktionen til at anmode om eSNI-nøgler for domænet. Hvor serverdelen fungerer, indstiller vi TLS-parametrene samt angiver navnet på en falsk "dække-domæne":

Domæne-forfrontning baseret på TLS 1.3. Del 2

Det skal bemærkes, at tls-tris-grenen ikke oprindeligt er designet til at anvende domæne-frontering. Derfor er der ikke taget højde for det falske servernavn (i client-hello-pakken bliver serverName-feltet sendt som tomt). For at rette dette, skal vi tilføje det relevante felt FakeServerName til TlsConfig-strukturen. Det standard ServerName-felt i strukturen kan vi ikke bruge, da det anvendes af interne tls-mekanismer, og hvis det adskiller sig fra det oprindelige, vil tls-handshake mislykkes med en fejl. Beskrivelsen af TlsConfig-strukturen findes i filen tls/common.go – som vi også skal ændre:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Domæne-forfrontning baseret på TLS 1.3. Del 2

Derudover skal vi ændre filen tls/handshake_client.go, for at bruge vores felt FakeServerName ved dannelsen af TLS handshake:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Det var det! Nu kan du kompilere projektet og tjekke funktionaliteten. Men før du starter kontrollen, skal du konfigurere din CloudFlare-konto. Tja, hvordan skal jeg sige det, konfigurere - bare oprette en konto på CloudFlare og knytte dit domæne til det. Alle funktioner relateret til DoH, WebSocket og ESNI er som standard aktiveret i CloudFlare. Når DNS-posterne er opdateret, kan du kontrollere domænets funktionalitet ved at udføre en anmodning om eSNI-nøgler:

dig +short txt _esni.df13tester.info 

Domæne-forfrontning baseret på TLS 1.3. Del 2

Hvis du ser noget lignende for dit domæne, betyder det, at alt fungerer, og du kan gå videre til testning.

Vi starter en Ubuntu VPS, for eksempel på DigitalOcean. P.S. I vores tilfælde var den lige tildelte IP-adresse fra udbyderen sortlistet af RKN. Så vær ikke overrasket, hvis du oplever noget lignende. Vi måtte bruge en VPN for at få adgang til vores VPS.

Vi kopierer den allerede kompilerede rsockstun til VPS (i øvrigt en anden fordel ved Go - du kan kompilere projektet på din egen maskine og køre det på enhver Linux, så længe du overholder systemets arkitektur) og starter serverdelen:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Og derefter klientdelen:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Som vi kan se, har klienten oprettet forbindelse til serveren gennem CloudFlare front-end serveren ved hjælp af websockets. For at kontrollere, at tunnelen fungerer som en tunnel, kan du lave en curl-anmodning gennem den lokale socks5, der er åbnet på serveren:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Lad os nu se, hvad DPI ser i kommunikationskanalen:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Først anmoder tunneleringsværktøjet ved hjælp af DoH-mekanismen DNS-serveren Cloudflare om eSNI-nøgler for måldomænet (pakker #1-19), og derefter anmoder det om front-end serveren og opretter en TLS-forbindelse, skjult bag domænet www.google.com (dette er standardværdien, når der ikke er angivet et falsk domæne ved klientens opstart). For at angive dit eget falske domæne skal du bruge parameteren -fronfDomain:

Domæne-forfrontning baseret på TLS 1.3. Del 2

Domæne-forfrontning baseret på TLS 1.3. Del 2

Der er også et sidste punkt. Som standard er indstillingen for kontoen på CloudFlare indstillet til Flexible SSL. Det betyder, at https-anmodninger til Cloudflares front-end servere fra klienter vil blive omdirigeret til vores server i ukrypteret (http) format. Derfor startede vi den serverdel af tunnelen i non-ssl-tilstand (-listen ws:0.0.0.0), i stedet for (-listen wss:0.0.0.0).

Domæne-forfrontning baseret på TLS 1.3. Del 2

For at skifte til fuld krypteringstilstand skal du vælge Full, eller Full (strict) hvis der er et gyldigt certifikat på serveren. Efter at have skiftet tilstand vil vi kunne modtage forbindelser fra CloudFlare via https-protokollen. Glem ikke at generere et self-signed certifikat til serverdelen af tunnelen.

Domæne-forfrontning baseret på TLS 1.3. Del 2

Den nysgerrige læser vil spørge: «Hvad med klienten til Windows? Det primære brug af tunnelen er sikkert at etablere back-connect med virksomhedsmaskiner og servere, som normalt kører Windows. Hvordan kan jeg kompilere tunnelen til Windows og samtidig bruge en specifik TLS-stak?» Lad os nu præsentere endnu et trick, der viser, hvor praktisk Go er. Vi kompilere til Windows direkte fra Kali ved blot at tilføje parameteret GOOS=windows:

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

Eller 32-bit versionen:

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

Det er det! Og så er der ingen flere problemer. Det fungerer virkelig!

Domæne-forfrontning baseret på TLS 1.3. Del 2

Kompilationsflaggene -w og -s er nødvendige for at fjerne unødvendigt affald fra den eksekverbare fil, hvilket gør den et par megabyte mindre. Yderligere kan den pakkes med UPX for at reducere størrelsen yderligere.

Afslutning

I artiklen har vi med eksemplet på tunnelen skrevet i Go tydeligt vist anvendelsen af den nye teknologi domain-fronting, realiseret gennem en temmelig interessant egenskab ved TLS 1.3-protokollen. På samme måde kan det eksisterende værktøjssæt skrevet i Go tilpasses til at arbejde gennem CloudFlare-servere, for eksempel Merlin — en velkendt C2, eller få CobaltStrike Beacon til at bruge eSNI domain-fronting ved at arbejde med Teamserver via External C2 Channel, realiseret i Go, eller på standard C++ ved hjælp af den patch-version af OpenSSL, som vi har beskrevet i den forrige del af artiklen. I det hele taget er der ikke nogen grænser for fantasien.

Eksemplet med tunnelen og CloudFlare præsenteres i form af et koncept, og det er stadig svært at sige noget om de langtidsudsigter for denne form for domain-fronting. På nuværende tidspunkt er eSNI-understøttelse kun implementeret af CloudFlare, og teoretisk set er der intet, der forhindrer dem i at deaktivere denne form for fronting og for eksempel bryde tls-forbindelser, når SNI og eSNI ikke stemmer overens. I det hele taget vil fremtiden vise det. Men indtil videre ser perspektivet for at arbejde under “dækket af kremlin.ru” ret tiltalende ud. Er det ikke?

Den opdaterede tunnelkodes samt de kompilerede eksekverbare exe-filer er placeret i en separat gren af projektet på github. For alle mulige problemer med tunnelen anbefales det bedst at oprette en issue på projektets side på GitHub.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster