Domen-fronting bazuar në TLS 1.3. Pjesa 2

Hyrje

Në pjesën e parë artikulli ne dhamë një përshkrim të shkurtër të mekanizmit të SNI të enkriptuar (eSNI). Të treguam se si mbi të mund të shmangim zbulimin nga sistemet moderne të DPI (me shembuj si DPI i Beeline dhe ruxhja e ndaluar RKN), si dhe kërkuam një variant të ri të domen-fronit që bazohet në këtë mekanizëm.

Në pjesën e dytë të artikullit do të kalojmë në aspekte më praktike, të cilat do të jenë të dobishme për specialistët e RedTeam në punën e tyre të ndërlikuar. Më në fund, qëllimi ynë nuk është të marrim akses në burimet e bllokuara (për këto gjëra ka VPN-in e mirë të vjetër). Ka shumë ofrues VPN, siç thuhet, për çdo shije, ngjyrë dhe buxhet.

Ne do të përpiqemi të aplikojmë mekanizmin e domen-fronting për mjetet moderne të RedTeam, siç janë Cobalt Strike, Empire etj., dhe t'u japim atyre mundësi të shtesë për mimikrim dhe shmangie nga sistemet moderne të filtrimit të përmbajtjes.

Herën e fundit implementuam mekanizmin e eSNI në bibliotekën OpenSSL dhe e përdorëm me sukses në utilitarin e njohur për të gjithë curl. Por vetëm me curl, siç thonë, nuk ngopesh. Sigurisht, do të dëshironim të realizonim diçka të ngjashme në gjuhët e nivelit të lartë. Por, fatkeqësisht, një kërkim i shpejtë në hapësirën e internetit na bën të zhgënjehemi, sepse mbështetje të plote për mekanizmin e eSNI është realizuar vetëm në GOLANG. Kështu, zgjedhja jonë nuk është shumë e madhe: ose shkruajmë në C të pastër ose C++ duke përdorur bibliotekën e përmirësuar OpenSSL, ose përdorim një fork të veçantë të GOLANG nga CloudFlare dhe përpiqemi ta portojmë mjetin tonë atje. Në parim, ka edhe një mundësi tjetër, më klasike, por njëkohësisht e lodhshme – të implementojmë mbështetje për eSNI për Python. Më në fund, Python gjithashtu përdor OpenSSL për të punuar me https. Por këtë mundësi do ta lëmë për t'u zhvilluar nga dikush tjetër, ndërsa ne do të jemi të kënaqur me realizimin në GOLANG, sidomos që Cobalt Strike ynë i preferuar e di mirë se si të punojë me një kanal komunikimi të ndërtuar nga mjete të jashtme (kanali External C2) – për këtë do të flasim në fund të artikullit.

Try Harder…

Një nga mjetet e realizuara në Go – zhvillimi ynë për pivoting brenda rrjetit – tuneluesi rsockstun, i cili, për t'iu referuar, aktualisht detektohet nga mjetet e kompanive Microsoft dhe Symantec si një software shumë i dëmshëm, i orientuar drejt shkeljes së stabilitetit global…

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Do të ishte e shkëlqyer të përdornim zhvillimin e mëparshëm edhe në këtë rast. Por këtu lind një problem i vogël. Problemi është se fillimisht rsockstun parashikon përdorimin e një kanali të zakonshëm SSL për lidhjen me serverin. Kjo do të thotë se lidhja krijohet një herë dhe ekziston gjatë gjithë kohës së funksionimit të tunelit. Dhe, siç e kuptoni, protokolli https paksa nuk është i dizajnuar për këtë mod përdorimi – ai punon në modin kërkesë- përgjigje, ku çdo kërkesë e re http ekziston brenda kuadrit të një lidhjeje të re tcp.

Defekti kryesor i këtij skeme është se serveri nuk mund të transmetojë të dhëna klientit, derisa klienti të dërgojë një kërkesë të re http. Megjithatë, për fat të mirë, ekzistojnë shumë opsione për zgjidhjen e këtij problemi – transmetimi i të dhënave nëpërmjet protokollit http (mjerë që arrijmë siç e bëjmë të shikojmë serialet tona të preferuara dhe të dëgjojmë muzikë nga portalet që punojnë në https, dhe transmetimi i videos dhe audios – nuk është asgjë tjetër përveç transmetimit të të dhënave). Një nga teknologjitë për të emuluar funksionimin e një lidhjeje të plotë tcp mbi protokollin http është teknologjia e web-socket-ëve (WebSockets), thelbi i së cilës është organizimi i një lidhjeje të plotë në rrjet midis klientit dhe serverit web.

Për fatin tonë (hurra-hurra!!!), kjo teknologji është e përfshirë siç duhet në të gjitha planet tarifore të CloudFlare dhe funksionon shkëlqyer së bashku me eSNI. Pikërisht këtë do ta përdorim për të mësuar tuneluesin tonë të përdorë domenin e përparshëm dhe të fshihet nga DPI-të moderne.

Pak për WebSockets

Së pari, do të flasim shkurtimisht dhe me fjalë të thjeshta për web-socket-et, në mënyrë që të gjithë të kenë një ide për atë me çfarë do të punojmë.

Teknologjia e web-socket-ëve lejon kalimin përkohësisht nga lidhja http në transmetim standard të të dhënave përmes një socket-i rrjeti, pa ndarë lidhjen tcp të krijuar. Kur klienti dëshiron të kalojë në web-socket, ai në kërkesën e tij http vendos disa headers http. Dy headers të detyrueshëm janë Connection: Upgrade dhe Upgrade: websocket. Ai gjithashtu mund të tregojë me forcë versionin e protokollit websocket (Sec-Websockset-Version: 13) dhe diçka si identifikuesi base64 i web-socket (Sec-WebSocket-Key: DAGDJSiREI3+KjDfwxm1FA==). Serveri përgjigjet me kodi http 101 Switching Protocols dhe gjithashtu vendos headerët Connection, Upgrade dhe Sec-WebSocket-Accept. Procesi i kalimit është ilustruar në screenshotin më poshtë:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Pas kësaj, vendosja e lidhjes WebSocket mund të konsiderohet e përfunduar. Çdo të dhënë, si nga klienti ashtu edhe nga serveri, tani do të dërgohet me headerë të WebSocket (fillojnë me bajtin 0x82). Tani serveri nuk ka nevojë të presë një kërkesë nga klienti për të dërguar të dhëna, pasi lidhja tcp nuk ndërpritet.

Në Golang, ka disa biblioteka për punën me web-sockets. Më të njohurat janë Gorilla WebSocket dhe standardi WebSocket. Ne do të përdorim të fundit, pasi është më e thjeshtë, më e vogël dhe funksionon, siç thuhet, pak më shpejt.

Në kodin e klientit rsockstun, ne duhet të zëvendësojmë thirrjet net.dial ose tls.dial me thirrjet përkatëse të WebSocket:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Ne duam të bëjmë pjesën klient të tunelit tonë universale dhe të aftë të funksionojë si përmes një lidhjeje të drejtpërdrejtë ssl, ashtu edhe përmes protokollit WebSocket. Për këtë, ne do të krijojmë një funksion të veçantë func connectForWsSocks(address string, proxy string) error {…} me analogji me connectForSocks() dhe do ta përdorim atë për të punuar me web-sockets në rast se adresa e serverit, e cila është caktuar gjatë fillimit të klientit, fillon me ws: ose wss: (në rastin e WebSocket-it të Sigurt).

Për pjesën server të tunelit, ne gjithashtu do të krijojmë një funksion të veçantë për punën me web-sockets. Në të, do të krijohet një instancë e klasës http dhe do t'i caktohet një trajtues i lidhjes http (funksioni wsHandler):

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Dhe të gjitha logjikat e trajtimit të lidhjes (autorizimi i klientit me fjalëkalim, vendosja dhe përfundimi i sesionit yamux) do t'i vendosim te trajtuesi i lidhjes WebSocket:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Kompilojmë projektin, fillojmë pjesën server:

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

Dhe pastaj pjesën klient:

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

Dhe verifikojmë funksionimin në hostin lokal:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Kalo në domain-fronting

Me web-sockets duket se e kemi kuptuar situatën. Tani le të kalojmë drejtpërdrejt në eSNI dhe domain-fronting. Siç u tha më parë, për të punuar me DoH dhe eSNI, na nevojitet një degë speciale golang nga kompania CloudFlare. Na nevojitet një degë me mbështetje eSNI (pwu/esni).

Klonojmë atë lokalisht ose e shkarkojmë dhe e çzipojmë zip-in përkatës:

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

Pastaj duhet të kopjojmë katalogun GOROOT, të zëvendësojmë skedarët përkatës nga dega e klonuar dhe ta vendosim atë si kryesor. Për të shpëtuar zhvilluesin nga kjo dhimbje koke, ekipi në CloudFlare ka përgatitur një skenar të veçantë – _dev/go.sh. Thjesht e aktivizojmë atë. Skripti, së bashku me makefile, do të bëjë gjithçka vetë. Për kuriozitet, mund të shikoni brenda makefile për detaje.

Pas përfundimit të skriptit, gjatë kompilimit të projektit, na nevojitet të specifikojmë katalogun lokal si GOROOT, i përgatitur nga skripti. Në rastin tonë, kjo duket kështu:

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

Më pas, na nevojitet të zbatojmë në tunelimin e funksionalitetit për kërkimin dhe analizimin e çelësave publikë eSNI për domenin e nevojshëm. Në rastin tonë, këta do të jenë çelësat publikë eSNI nga serverët frontend të CloudFlare. Për këtë, do të krijojmë tre funksione:

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

Emrat e funksioneve, në parim, e thonë vetë. Përmbajtja do ta marrim nga skedari esni_query.go, që është pjesë e tls-tris. Funksioni i parë krijon një paketë rrjeti me një kërkesë për serverin DNS të CloudFlare, duke përdorur protokollin DoH (DNS-over-HTTPS), i dyti – analizojnë rezultatet e kërkesës dhe marrin vlerat e çelësave publikë të domenit, ndërsa i treti është një kontejner për të parët dy.

Më pas, ne e shtojmë në funksionin tonë të sapo krijuar lidhjen e web-socket-it connectForWsSocks funksionalitetin për kërkimin e çelësave eSNI për domenin. Atje ku funksionon pjesa server, vendosim parametrat TLS, si dhe caktuam emrin e domenit të rremë:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Këtu duhet të theksohet se fillimisht, dega tls-tris nuk është projektuar për përdorimin e domenit të maskuar. Prandaj, nuk i është kushtuar vëmendje emrit të rremë të serverit (në paketën client-hello, transmetohet një fushë e zbrazët serverName). Për ta korrigjuar këtë, na nevojitet të shtojmë në strukturën TlsConfig fushën e duhur FakeServerName. Nuk mund ta përdorim fushën standarde ServerName të strukturës, pasi e përdorin mekanizmat e brendshëm tls dhe nëse ajo ndryshon nga origjinali, atëherë tls-handshake do të përfundojë me një gabim. Përshkrimi i strukturës TlsConfig ndodhet në skedarin tls/common.go – dhe atë do ta kemi për të korrigjuar:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Shtesë, na nevojitet të bëjmë ndryshime në skedarin tls/handshake_client.go, për të përdorur fushën tonë FakeServerName gjatë formimit të TLS handshakes:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Këtu përfundon! Tani mund të kompilohet projekti dhe të kontrollohet funksionaliteti. Por para se të filloni kontrollet, është e nevojshme të konfiguroni llogarinë CloudFlare. Si të thuash ta konfiguroni – vetëm krijoni një llogari në CloudFlare dhe lidheni domenin tuaj me të. Të gjitha veçoritë lidhur me DoH, WebSocket dhe ESNI janë të aktivizuara në CloudFlare si parazgjedhje. Pas përditësimit të rekordeve DNS – mund të kontrolloni funksionimin e domenit duke bërë një kërkesë për çelësat e eSNI:

dig +short txt _esni.df13tester.info 

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Nëse shihni diçka të ngjashme për domenin tuaj – atëherë gjithçka funksionon dhe mund të kaloni në testim.

Nisim një Ubuntu VPS, për shembull, në DigitalOcean. P.S. Në rastin tonë, adresa IP e ofruar nga provider-i për VPS ishte në listat e zeza të RKN. Pra, mos u habitni nëse ndodh diçka e ngjashme me ju. Duhej të përdorim një VPN për të aksesuar VPS-në tonë.

Kopjojmë në VPS rsockstun të kompiliuar më parë (në këtë, ndonjëherë, është një tjetër kënaqësi e Golang – mund të kompilohet projekti tuaj dhe ta ekzekutoni në çdo Linux, për sa kohë që përmbushni vetëm arkitekturën e sistemit) dhe nisim pjesën server:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Dhe pastaj pjesën klient:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Siç e shohim, klienti u lidh me sukses me serverin përmes serverit frontend të CloudFlare duke përdorur websockets. Për të kontrolluar nëse tuneli funksionon si një tunel, mund të bëni një kërkesë curl përmes socks5 lokal, të hapur në server:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Tani le të shohim se çfarë sheh DPI në kanal:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Së pari, tuneluesi, duke përdorur mekanizmin DoH, i drejtohet serverit DNS të Cloudflare për çelësat e eSNI për domenin e destinacionit (paketat #1-19), dhe pastaj i drejtohet serverit frontend dhe krijon një lidhje TLS, duke u mbuluar me domenin www.google.com (kjo është vlera parazgjedhje, kur klienti niset pa përcaktuar një domen fals). Për të caktuar domenin tuaj fals, duhen përdorur parametra -fronfDomain:

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Tani një pikë tjetër. Sipas parazgjedhjes, në cilësimet e llogarisë në CloudFlare është vendosur regjimi Flexible SSL. Kjo do të thotë se kërkesat https nga klientët ndaj serverëve frontend të Cloudflare do të redirektohen në mënyrë të pa enkriptuar (http) tek serveri ynë. Pikërisht për këtë shkak, ne e nisëm pjesën server të tuneluesit në modin non-ssl (-listen ws:0.0.0.0), dhe jo (-listen wss:0.0.0.0).

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Për të kaluar në regjimin e enkriptimit të plotë, është e nevojshme të zgjidhni Full, ose Full (strict) në rast se ka një certifikatë të vërtetë në server. Pasi të kalojmë në modalitet tjetër, do të jemi në gjendje të pranojmë lidhje nga CloudFlare përmes protokollit https. Mos harroni të gjeneroni një certifikatë self-signed për pjesën server të tunelit.

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Një lexues i kujdesshëm do të pyesë: "Si qëndron puna me klientin për Windows? Sigurisht, aplikimi kryesor i tunelit është ngushtimi i një lidhjeje mbrapa nga makinat dhe serverët korporatë, dhe aty zakonisht është gjithmonë Windows. Si ta kompiloje tunelin për Windows, duke e pasur parasysh strukturën specifike të TLS?" Tani do të paraqesim një tjetër veçori që tregon sa e lehtë është Go. Kompilohet për Windows direkt nga Kali, thjesht duke shtuar parametrin GOOS=windows:

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

Ose varianti 32-bit:

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

Kaq! Dhe asnjë problem tjetër nuk nevojitet. Kjo do të thotë se funksionon!

Domen-fronting bazuar në TLS 1.3. Pjesa 2

Flamujt e kompilatorit –w dhe –s janë të nevojshme për të hequr mbetje të panevojshme nga skedari ekzekutiv, duke e bërë atë më të vogël për disa megabajt. Së fundi, mund të paketoni gjithashtu me ndihmën e UPX për të zvogëluar akoma më shumë madhësinë.

Në përfundim

Në këtë artikull, ne, përmes shembullit të tunelit të shkruar në Go, demonstruam aplikimin e teknologjisë së re të domain-fronting, e realizuar në një veçori mjaft interesante të protokollit TLS 1.3. Në mënyrë të ngjashme, mund të adaptohet mjetet ekzistues të shkruara në Go për të punuar përmes serverëve CloudFlare, për shembull, Merlin — një C2 i njohur, ose të detyrojë CobaltStrike Beacon të përdorë domain-fronting eSNI kur punon me Teamserver përmes Kanali C2 të Jashtëm, i realizuar në Go, ose në standardin C++ duke përdorur versionin e patchuar të OpenSSL, për të cilin folëm në pjesën e kaluar të artikullit. Në përgjithësi, imagjinata nuk ka limite.

Shembulli me tunelin dhe CloudFlare është i paraqitur si një koncept dhe deri tani është e vështirë të flasim për perspektivat e tilla në të ardhmen. Në këtë moment, mbështetja e eSNI është realizuar vetëm nga CloudFlare dhe, në parim, asgjë nuk i pengon ata të çaktivizojnë këtë lloj fronti dhe, për shembull, të ndërpresin lidhjet tls në rast të mos përputhjes midis SNI dhe eSNI. Në përgjithësi, e ardhmja do ta tregojë. Por për momentin, perspektiva e punës nën "mbrojtjen e kremlin.ru" duket mjaft joshëse. A nuk është kështu?

Kodi i azhurnuar i tunnelerit, si dhe skedarët ekzekutivë exe të kompiluara janë vendosur në një degë të veçantë të projektit në github. Për çdo problem të mundshëm me tunnelerin, më mirë të shkruani një problem në faqen e projektit në GitHub.

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster