Domain-Fronting basierend auf TLS 1.3. Teil 2

Einführung

Der erste Abschnitt Artikel Wir haben eine kurze Beschreibung des verschlüsselten SNI-Mechanismus (eSNI) gegeben. Sie zeigten, wie es auf dieser Grundlage möglich ist, der Erkennung durch moderne DPI-Systeme zu entgehen (am Beispiel von Beeline DPI und dem verbotenen RKN-Root-Tracker) und untersuchten auch eine neue Version des Domain-Frontings, die auf diesem Mechanismus basiert.

Im zweiten Teil des Artikels gehen wir auf praktischere Dinge ein, die den RedTeam-Spezialisten bei ihrer schwierigen Arbeit nützlich sein werden. Letztlich geht es uns nicht darum, Zugang zu gesperrten Ressourcen zu erhalten (für so triviale Dinge gibt es das gute alte VPN). Glücklicherweise gibt es, wie man sagt, eine große Auswahl an VPN-Anbietern für jeden Geschmack, jede Farbe und jedes Budget.

Wir werden versuchen, den Domain-Fronting-Mechanismus beispielsweise auf moderne RedTeam-Tools wie Cobalt Strike, Empire usw. anzuwenden und ihnen zusätzliche Fähigkeiten zu geben, um moderne Content-Filtersysteme nachzuahmen und zu umgehen.

Beim letzten Mal haben wir den eSNI-Mechanismus in die OpenSSL-Bibliothek implementiert und ihn erfolgreich im bekannten Curl-Dienstprogramm verwendet. Aber wie heißt es so schön: Mit nur einem Huhn wird man sich nicht zufrieden geben. Natürlich würde ich gerne etwas Ähnliches in Hochsprachen implementieren. Leider enttäuscht uns eine schnelle Suche im Internet, da die Unterstützung für den eSNI-Mechanismus nur in GOLANG vollständig implementiert ist. Wir haben also keine große Wahl: Entweder wir schreiben in reinem C oder C++ unter Verwendung der gepatchten OpenSSL-Bibliothek, oder wir verwenden einen separaten GOLANG-Fork von CloudFlare und versuchen, unsere Tools dorthin zu portieren. Im Prinzip gibt es eine andere, klassischere, aber gleichzeitig zeitaufwändigere Möglichkeit – die Implementierung der eSNI-Unterstützung für Python. Schließlich verwendet Python auch OpenSSL, um mit https umzugehen. Aber wir werden diese Option jemand anderem überlassen und uns selbst mit der Implementierung in Golang begnügen, zumal unser geliebter Cobalt Strike perfekt mit einem von Drittanbieter-Tools erstellten Kommunikationskanal (externer C2-Kanal) zusammenarbeiten kann. - Darüber werden wir am Ende des Artikels sprechen.

Versuchen Sie es mehr...

Eines der in Go implementierten Tools ist unsere Entwicklung zur Einbindung in das Netzwerk – ein Tunneler rsockstun, die übrigens mittlerweile von Tools von Microsoft und Symantec als sehr bösartige Software erkannt wird, die darauf abzielt, die globale Stabilität zu stören ...

Domain-Fronting basierend auf TLS 1.3. Teil 2

Auch in diesem Fall wäre es toll, die bisherige Entwicklung zu nutzen. Aber hier entsteht ein kleines Problem. Tatsache ist, dass rsockstun zunächst die Verwendung eines synchronen SSL-Kommunikationskanals mit dem Server impliziert. Dies bedeutet, dass die Verbindung einmalig hergestellt wird und für die gesamte Dauer des Tunnelbetriebs besteht. Und wie Sie verstehen, ist das https-Protokoll nicht für diesen Betriebsmodus gedacht – es funktioniert im Request-Response-Modus, bei dem jede neue http-Anfrage innerhalb einer neuen TCP-Verbindung existiert.

Der Hauptnachteil dieses Schemas besteht darin, dass der Server keine Daten an den Client übertragen kann, bis der Client eine neue HTTP-Anfrage sendet. Aber glücklicherweise gibt es viele Möglichkeiten, dieses Problem zu lösen – Datenstreaming über das http-Protokoll (schließlich schaffen wir es irgendwie, unsere Lieblingsfernsehsendungen anzusehen und Musik von Portalen zu hören, die auf https laufen, aber die Übertragung von Video und Audio ist nichts anderes als Streaming-Daten). Eine der Technologien zur Emulation des Betriebs einer vollwertigen TCP-Verbindung über das HTTP-Protokoll ist die WebSockets-Technologie, deren Hauptinhalt darin besteht, eine vollwertige Netzwerkverbindung zwischen dem Client und dem Webserver zu organisieren.

Zu unserem Glück (Hurra!!!) ist diese Technologie standardmäßig in allen CloudFlare-Tarifen enthalten und funktioniert hervorragend in Kombination mit eSNI. Genau das werden wir nutzen, um unserem Tunneler beizubringen, Domain-Fronting zu verwenden und sich vor modernen DPIs zu verstecken.

Ein wenig über WebSockets

Zunächst werden wir WebSockets kurz und einfach erklären, damit jeder eine Vorstellung davon hat, womit wir arbeiten werden.

Mit der Websocket-Technologie können Sie vorübergehend von einer HTTP-Verbindung zu einem Standard-Netzwerk-Socket-Streaming wechseln, ohne die bestehende TCP-Verbindung zu unterbrechen. Wenn ein Client zu einem Websocket wechseln möchte, setzt er in seiner http-Anfrage mehrere http-Header. Zwei erforderliche Header - Verbindung: Upgrade и Upgrade: WebSocket. Er kann auch die Version des WebSocket-Protokolls zwangsweise angeben (Sec-Websockset-Version: 13) und so etwas wie eine Base64-Websocket-ID (Sec-WebSocket-Schlüssel: DAGDJSiREI3+KjDfwxm1FA==). Der Server antwortet ihm mit dem http-Code 101 Switching Protocols und setzt auch die Header Verbindung, Upgrade и Sec-WebSocket-Accept. Der Umschaltvorgang wird im folgenden Screenshot deutlich veranschaulicht:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Danach kann die Installation der WebSocket-Verbindung als abgeschlossen betrachtet werden. Alle Daten sowohl vom Client als auch vom Server werden nun nicht mit http, sondern mit WebSocket-Headern bereitgestellt (sie beginnen mit Byte 0x82). Jetzt muss der Server nicht mehr auf eine Anfrage des Clients warten, um Daten zu übertragen, denn Die TCP-Verbindung ist nicht unterbrochen.

Golang verfügt über mehrere Bibliotheken für die Arbeit mit Websockets. Die beliebtesten davon sind Gorilla-WebSocket und Standard WebSocket. Wir werden Letzteres verwenden, weil... Es ist einfacher, kleiner und funktioniert, wie man sagt, etwas schneller.

Im rsockstun-Clientcode müssen wir die net.dial- oder tls.dial-Aufrufe durch die entsprechenden WebSocket-Aufrufe ersetzen:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Domain-Fronting basierend auf TLS 1.3. Teil 2

Wir möchten, dass der Client Teil unseres Tunnels ist, der universell ist und sowohl über eine direkte SSL-Verbindung als auch über das WebSockset-Protokoll funktionieren kann. Dafür erstellen wir eine separate Funktion func connectForWsSocks(address string, Proxy string) Fehler {…} in Analogie zu connectForSocks() und wir werden es verwenden, um mit Web-Sockets zu arbeiten, wenn die beim Starten des Clients angegebene Serveradresse mit ws: oder wss: (im Fall von Secure WebSocket) beginnt.

Für die Serverseite des Tunnels werden wir außerdem eine separate Funktion für die Arbeit mit Web-Sockets erstellen. Es wird eine Instanz der http-Klasse erstellt und der http-Verbindungshandler (wsHandler-Funktion) festgelegt:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Und wir werden die gesamte Verbindungsverarbeitungslogik (Client-Autorisierung mit einem Passwort, Einrichten und Beenden einer Yamux-Sitzung) im WebSocket-Verbindungshandler platzieren:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Wir kompilieren das Projekt und starten den Serverteil:

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

Und dann der Client-Teil:

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

Und wir überprüfen die Arbeit auf dem lokalen Host:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Domain-Fronting basierend auf TLS 1.3. Teil 2

Kommen wir zum Domain-Fronting

Wir scheinen Websockets herausgefunden zu haben. Kommen wir nun direkt zu eSNI und Domain-Fronting. Wie bereits erwähnt, müssen wir für die Zusammenarbeit mit DoH und eSNI einen speziellen Golang-Zweig des Unternehmens übernehmen CloudFlare. Wir benötigen eine Zweigstelle mit eSNI-Unterstützung (pwu/esni).

Wir klonen es lokal oder laden die entsprechende Zip-Datei herunter und entpacken sie:

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

Dann müssen wir das GOROOT-Verzeichnis kopieren, die entsprechenden Dateien aus dem geklonten Zweig ersetzen und ihn als Master festlegen. Um dem Entwickler diese Kopfschmerzen zu ersparen, haben die Jungs von CloudFlare ein spezielles Skript vorbereitet – _dev/go.sh. Wir starten es einfach. Das Skript erledigt zusammen mit dem Makefile alles selbst. Nur zum Spaß können Sie im Makefile nach Details suchen.

Nachdem wir das Skript ausgeführt haben, müssen wir beim Kompilieren des Projekts das vom Skript vorbereitete lokale Verzeichnis als GOROOT angeben. In unserem Fall sieht es so aus:

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

Als nächstes müssen wir im Tunnel die Funktionalität zum Anfordern und Parsen öffentlicher eSNI-Schlüssel für die gewünschte Domäne implementieren. In unserem Fall handelt es sich dabei um öffentliche eSNI-Schlüssel von CloudFlare-Frontend-Servern. Dazu erstellen wir drei Funktionen:

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

Die Namen der Funktionen sprechen im Prinzip für sich. Wir übernehmen den Inhalt aus der Datei esni_query.go, die Teil von tls-tris ist. Die erste Funktion erstellt ein Netzwerkpaket mit einer Anfrage an den CloudFlare-DNS-Server unter Verwendung des DoH-Protokolls (DNS-over-HTTPS), die zweite analysiert die Abfrageergebnisse und ruft die Werte der öffentlichen Schlüssel der Domäne ab und die dritte ist a Container für die ersten beiden.

Als nächstes fügen wir unserer neu erstellten Funktion eine Web-Socket-Verbindung hinzu connectForWsSocks Funktionalität zum Anfordern von eSNI-Schlüsseln für eine Domain. Wo der Serverteil arbeitet, legen wir die TLS-Parameter fest und legen auch den Namen der gefälschten „Cover-Domain“ fest:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Hierbei ist zu beachten, dass der TLS-Tris-Zweig ursprünglich nicht für die Verwendung von Domain-Fronting konzipiert war. Daher wird der gefälschte Servername nicht berücksichtigt (ein leeres ServerName-Feld wird als Teil des Client-Hello-Pakets gesendet). Um dies zu beheben, müssen wir das entsprechende FakeServerName-Feld zur TlsConfig-Struktur hinzufügen. Wir können das Standardfeld „ServerName“ der Struktur nicht verwenden, weil Es wird von den internen TLS-Mechanismen verwendet und wenn es vom Original abweicht, endet der TLS-Handshake mit einem Fehler. Eine Beschreibung der TlsConfig-Struktur ist in der Datei enthalten tls/common.go - Wir müssen es beheben:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Domain-Fronting basierend auf TLS 1.3. Teil 2

Darüber hinaus müssen wir Änderungen an der Datei vornehmen tls/handshake_client.goSo verwenden Sie unser FakeServerName-Feld beim Erstellen eines TLS-Handshakes:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Das ist alles! Sie können das Projekt kompilieren und die Arbeit überprüfen. Bevor Sie den Scan ausführen, müssen Sie jedoch ein CloudFlare-Konto einrichten. Nun, wie soll ich sagen, richten Sie es ein – erstellen Sie einfach ein Konto bei Cloudflare und verknüpfen Sie Ihre Domain damit. Alle Funktionen im Zusammenhang mit DoH, WebSocket und ESNI sind standardmäßig in CloudFlare enthalten. Nachdem die DNS-Einträge aktualisiert wurden, können Sie den Betrieb der Domain überprüfen, indem Sie die eSNI-Schlüssel abfragen:

dig +short txt _esni.df13tester.info 

Domain-Fronting basierend auf TLS 1.3. Teil 2

Wenn Sie bei Ihrer Domain etwas Ähnliches sehen, bedeutet das, dass bei Ihnen alles funktioniert und Sie mit dem Testen fortfahren können.

Rennen Ubuntu Ein VPS, beispielsweise bei DigitalOcean. PS: In unserem Fall landete die VPS-IP-Adresse, die wir gerade von unserem Provider erhalten hatten, auf der Blacklist von Roskomnadzor. Wundern Sie sich also nicht, wenn Ihnen etwas Ähnliches passiert. Ich musste ein VPN verwenden, um auf meinen VPS zugreifen zu können.

Wir kopieren den bereits kompilierten rsockstun auf den VPS (das ist übrigens eine weitere Schönheit von Golang – Sie können das Projekt selbst kompilieren und auf jedem Linux ausführen, wobei wir nur die Bitkapazität des Systems beachten) und starten den Serverteil:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Und dann der Client-Teil:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Wie wir sehen können, hat der Client über den CloudFlare-Frontend-Server mithilfe eines Websockets erfolgreich eine Verbindung zum Server hergestellt. Um zu überprüfen, ob der Tunnel genau wie ein Tunnel funktioniert, können Sie über lokale Socks5, die auf dem Server geöffnet sind, eine Curl-Anfrage stellen:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Sehen wir uns nun an, was DPI im Kommunikationskanal sieht:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Zuerst kontaktiert der Tunneler mithilfe des DoH-Mechanismus den Cloudflare-DNS-Server für eSNI-Schlüssel für die Zieldomäne (Pakete Nr. 1–19), kontaktiert dann den Frontend-Server und stellt eine TLS-Verbindung her, die sich hinter der Domäne versteckt www.google.com (Dies ist der Standardwert, wenn beim Starten des Clients keine gefälschte Domäne angegeben wird.) Um Ihre Fake-Domain anzugeben, müssen Sie den Parameter -fronfDomain verwenden:

Domain-Fronting basierend auf TLS 1.3. Teil 2

Domain-Fronting basierend auf TLS 1.3. Teil 2

Nun noch etwas. Standardmäßig sind die CloudFalre-Kontoeinstellungen auf Flexibles SSL eingestellt. Das bedeutet, dass https-Anfragen an Cloudflare-Frontend-Server von Clients unverschlüsselt (http) an unseren Server weitergeleitet werden. Aus diesem Grund haben wir den Serverteil des Tunnels im Nicht-SSL-Modus ( -listen ws:0.0.0.0) und nicht ( -listen wss:0.0.0.0) gestartet.

Domain-Fronting basierend auf TLS 1.3. Teil 2

Um in den vollständigen Verschlüsselungsmodus zu wechseln, müssen Sie auswählen VollständigerOder Voll (streng) ob ein echtes Zertifikat auf dem Server vorhanden ist. Nach dem Umschalten des Modus können wir Verbindungen von CloudFlare über das https-Protokoll akzeptieren. Vergessen Sie nicht, ein selbstsigniertes Zertifikat für die Serverseite des Tunnels zu generieren.

Domain-Fronting basierend auf TLS 1.3. Teil 2

Der neugierige Leser wird fragen: „Was ist mit dem Kunden unter Windows„Letztendlich besteht der Haupteinsatzzweck eines Tunnelers wahrscheinlich darin, eine Backend-Verbindung von Firmenrechnern und -servern herzustellen, und diese laufen in der Regel unter Windows. Wie kompiliere ich einen Tunneler für Windows, insbesondere mit einem bestimmten TLS-Stack?“ Nun stellen wir eine weitere Funktion vor, die die Benutzerfreundlichkeit von Golang demonstriert. Wir kompilieren direkt unter Kali für Windows, indem wir einfach den Parameter GOOS=windows hinzufügen:

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

Oder die 32-Bit-Version:

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

Alle! Und es ist kein Ärger mehr nötig. Es funktioniert wirklich!

Domain-Fronting basierend auf TLS 1.3. Teil 2

Die Compiler-Flags –w und –s werden benötigt, um unnötigen Müll aus der ausführbaren Datei zu entfernen und sie um ein paar Megabyte kleiner zu machen. Darüber hinaus kann es dann mit UPX verpackt werden, um die Größe weiter zu reduzieren.

Statt einer Schlussfolgerung

In dem Artikel haben wir am Beispiel eines in Golang geschriebenen Tunnels deutlich die Verwendung der neuen Domain-Fronting-Technologie demonstriert, die auf einer recht interessanten Funktion des TLS 1.3-Protokolls implementiert ist. Auf ähnliche Weise können Sie vorhandene, in Golang geschriebene Tools so anpassen, dass sie beispielsweise über CloudFlare-Server funktionieren Merlin - berühmtes C2, oder erzwingen Sie CobaltStrike Beacon, eSNI-Domain-Fronting zu verwenden, wenn Sie mit Teamserver arbeiten über Externer C2-Kanal, implementiert in Golang oder in Standard-C++ unter Verwendung einer gepatchten Version von OpenSSL, worüber wir im letzten Teil des Artikels gesprochen haben. Generell sind der Fantasie keine Grenzen gesetzt.

Das Beispiel mit dem Tunneler und CloudFlare wird in Form eines Konzepts dargestellt und es ist noch schwierig, eine Aussage über die langfristigen Perspektiven dieser Art von Domain-Fronting zu treffen. Derzeit unterstützt nur CloudFlare eSNI und theoretisch hindert sie nichts daran, diese Art von Fronting zu deaktivieren und beispielsweise TLS-Verbindungen zu unterbrechen, wenn SNI und eSNI nicht übereinstimmen. Im Allgemeinen wird die Zukunft es zeigen. Aber im Moment scheint die Aussicht, unter dem „Creme von kremlin.ru“ zu arbeiten, recht verlockend. Nicht wahr?

Der aktualisierte Tunneler-Code sowie kompilierte ausführbare Exe-Dateien befinden sich in einem separaten Zweig des Projekts github. Es ist besser, einen Issue über alle möglichen Tunneler-Probleme auf der Projektseite auf GitHub zu schreiben.

Source: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz und VPS-VDS-Servern 🔥 Kaufen Sie zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server | ProHoster