curl-impersonate: Ein spezieller curl-Build, der gängige Browser nachahmen kann
(github.com/lwthiker)- curl-impersonate ist ein modifizierter curl-Build, der TLS- und HTTP-Handshakes so ausführt, dass sie wie Chrome, Edge, Safari oder Firefox aussehen, und kann als CLI-Tool sowie als Ersatzbibliothek für
libcurlgenutzt werden - Die Client-Hello-Nachrichten und HTTP/2-Einstellungen normaler HTTP-Clients und -Bibliotheken unterscheiden sich deutlich von echten Browsern, sodass einige Webdienste Clients anhand des TLS-/HTTP-Handshakes identifizieren und unterschiedliche Inhalte ausliefern
- Die Implementierung besteht aus NSS für Firefox, BoringSSL für Chrome-basierte Browser, Änderungen an TLS-Erweiterungen, SSL-Optionen und HTTP/2-Einstellungen sowie der Anwendung nicht standardmäßiger Flags wie
--ciphers,--curvesund Headern - Unterstützt werden Chrome 99–116, Android Chrome 99, Edge 99 und 101, Firefox 91 ESR–117 sowie Safari 15.3 und 15.5; für jedes Ziel werden ein Wrapper-Script und ein Target Name bereitgestellt
- Auf der Kommandozeile führt man
curl_chrome116aus; bei der Integration als Bibliothek kann mancurl_easy_impersonate()oder unter LinuxLD_PRELOADundCURL_IMPERSONATEverwenden, um es auf bestehende Apps anzuwenden, dielibcurlnutzen
Das Problem, das curl-impersonate löst
- curl-impersonate ist ein Projekt, das curl speziell so baut, dass es die vier großen Browser Chrome, Edge, Safari und Firefox nachahmen kann
- TLS- und HTTP-Handshakes können identisch zu echten Browsern ausgeführt werden
- Es gibt zwei Nutzungsarten
- ein Kommandozeilen-Tool, ähnlich dem normalen curl
- eine Bibliothek, die statt des bestehenden
libcurlintegriert werden kann
Warum das nötig ist
- Wenn ein HTTP-Client eine TLS-Website aufruft, führt er zunächst einen TLS-Handshake aus
- Die erste Nachricht des TLS-Handshakes ist Client Hello; das Client Hello, das die meisten HTTP-Clients und -Bibliotheken erzeugen, unterscheidet sich deutlich von dem echter Browser
- Verwendet der Server HTTP/2, wird zusätzlich zum TLS-Handshake auch ein HTTP/2-Handshake ausgeführt, bei dem mehrere Einstellungen ausgetauscht werden
- Auch die HTTP/2-Einstellungen der meisten HTTP-Clients und -Bibliotheken unterscheiden sich von echten Browsern
- Einige Webdienste nutzen diese Unterschiede, um den zugreifenden Client zu identifizieren und je nach Client unterschiedliche Inhalte auszuliefern
- Diese Methoden werden TLS fingerprinting und HTTP/2 fingerprinting genannt
- Das README erklärt, dass die breite Nutzung solcher Verfahren das Web weniger offen, weniger privat und stärker auf bestimmte Web-Clients beschränkt gemacht hat
Funktionsweise
curlwird umfangreich gepatcht, damit es wie ein Browser aussieht- Die wichtigsten Änderungen sind:
- Die Firefox-Version kompiliert curl nicht mit OpenSSL, sondern mit NSS, der von Firefox verwendeten TLS-Bibliothek
- Die Chrome-Version wird mit Googles TLS-Bibliothek BoringSSL kompiliert
- Die Art, wie curl verschiedene TLS-Erweiterungen und SSL-Optionen setzt, wird geändert
- Unterstützung für neue TLS-Erweiterungen wird hinzugefügt
- Die für HTTP/2-Verbindungen verwendeten Einstellungen werden geändert
- curl wird mit nicht standardmäßigen Flags wie
--ciphers,--curvesund bestimmten-H-Headern ausgeführt
- Dadurch sieht curl aus Netzwerksicht identisch zu einem echten Browser aus
- Die vollständige technische Erklärung findet sich in part a und part b
Unterstützte Browser und Target-Namen
- Die Liste der unterstützten Browser ist auch in
browsers.jsonenthalten - Unterstützte Ziele der Chrome-Familie
- Chrome 99, 100, 101, 104, 107, 110, 116 on Windows 10
- Chrome 99 on Android 12
- Edge 99, 101 on Windows 10
- Safari 15.3 on MacOS Big Sur
- Safari 15.5 on MacOS Monterey
- Unterstützte Firefox-Ziele
- Firefox 91 ESR, 95, 98, 100, 102, 109, 117 on Windows 10
- Jedes unterstützte Ziel hat einen Target Name und ein Wrapper-Script
- Beispiel: Das Target
chrome116wird über das Wrapper-Scriptcurl_chrome116ausgeführt - Beispiel: Das Target
ff117wird über das Wrapper-Scriptcurl_ff117ausgeführt
- Beispiel: Das Target
Grundlegende Nutzung
- Für jeden unterstützten Browser gibt es ein Wrapper-Script, das
curl-impersonatemit den nötigen Headern und Flags ausführt - Beispielausführung
curl_chrome116 https://www.wikipedia.org - Zusätzliche Kommandozeilen-Flags werden an curl weitergereicht
- Manche Flags können die TLS signature von curl verändern und dadurch erkennbar machen
- Das Wrapper-Script verwendet einen Standardsatz von HTTP-Headern
- Um Header zu ändern, kann man das Wrapper-Script je nach Zweck anpassen
- Weitere Optionen sind in der fortgeschrittenen Nutzung von
libcurl-impersonateals Bibliothek enthalten
Installation und Bereitstellung
- Aus technischen Gründen gibt es
curl-impersonatein zwei Versionen- chrome-Version: zur Nachahmung von Chrome, Edge und Safari
- firefox-Version: zur Nachahmung von Firefox
- Vorkompilierte Binärdateien für Linux und macOS Intel sind über GitHub releases verfügbar
- Vor der Nutzung der vorkompilierten Binärdateien müssen NSS und CA-Zertifikate installiert werden
- Ubuntu:
sudo apt install libnss3 nss-plugin-pem ca-certificates - Red Hat/Fedora/CentOS:
yum install nss nss-pem ca-certificates - Archlinux:
pacman -S nss ca-certificates - macOS:
brew install nss ca-certificates
- Ubuntu:
- Außerdem wird zlib auf dem System benötigt
- zlib ist fast immer vorhanden, kann aber auf manchen minimalen Systemen fehlen
- Die vorkompilierten Linux-Binärdateien werden für Ubuntu-Systeme gebaut
- Wenn auf anderen Distributionen Fehler bei der Zertifikatsprüfung auftreten, muss man curl gegebenenfalls den Pfad zu den CA-Zertifikaten mitteilen
curl_chrome116 https://www.wikipedia.org --cacert /etc/ssl/certs/ca-bundle.crt - Für den Build aus dem Quellcode siehe INSTALL.md
Docker und Pakete
- Docker-Images auf Basis von Alpine Linux und Debian sind auf Docker Hub verfügbar
- Die Docker-Images enthalten die Binärdateien und alle Wrapper-Scripts
- Beispiele
# Firefox version, Alpine Linux docker pull lwthiker/curl-impersonate:0.6-ff docker run --rm lwthiker/curl-impersonate:0.6-ff curl_ff109 https://www.wikipedia.org # Chrome version, Alpine Linux docker pull lwthiker/curl-impersonate:0.6-chrome docker run --rm lwthiker/curl-impersonate:0.6-chrome curl_chrome110 https://www.wikipedia.org - Archlinux-Nutzer können AUR-Pakete verwenden
- Vorkompilierte Pakete: curl-impersonate-bin, libcurl-impersonate-bin
- Pakete zum Build aus dem Quellcode: curl-impersonate-chrome, curl-impersonate-firefox
- Eine inoffizielle Homebrew formula für Mac wird nur für Chrome bereitgestellt
brew tap shakacode/brew brew install curl-impersonate
Fortgeschrittene Nutzung von libcurl-impersonate
libcurl-impersonate.soist libcurl, kompiliert mit denselben Änderungen wie das Kommandozeilen-Toolcurl-impersonate- Es gibt eine zusätzliche API-Funktion
CURLcode curl_easy_impersonate(struct Curl_easy *data, const char * target, int default_headers); - Wird sie mit einem Target Name wie
chrome116aufgerufen, setzt sie intern die Optionen und Header, die sonst das Wrapper-Script setzen würde - Wenn
default_headers0 ist, wird die eingebaute Liste von HTTP-Headern nicht gesetzt- Nutzer müssen Header dann selbst über die normale libcurl-Option
CURLOPT_HTTPHEADERbereitstellen
- Nutzer müssen Header dann selbst über die normale libcurl-Option
curl_easy_impersonate()setzt mehrere libcurl-OptionenCURLOPT_HTTP_VERSIONCURLOPT_SSLVERSION,CURLOPT_SSL_CIPHER_LIST,CURLOPT_SSL_EC_CURVES,CURLOPT_SSL_ENABLE_NPN,CURLOPT_SSL_ENABLE_ALPN- die projektspezifische, nicht standardmäßige Option
CURLOPT_HTTPBASEHEADER - die projektspezifischen, nicht standardmäßigen HTTP/2-Optionen
CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER,CURLOPT_HTTP2_NO_SERVER_PUSH - die projektspezifischen, nicht standardmäßigen TLS-Optionen
CURLOPT_SSL_ENABLE_ALPS,CURLOPT_SSL_SIG_HASH_ALGS,CURLOPT_SSL_CERT_COMPRESSION,CURLOPT_SSL_ENABLE_TICKET - die projektspezifische, nicht standardmäßige TLS-Option
CURLOPT_SSL_PERMUTE_EXTENSIONS
- Ruft man danach mit
curl_easy_setopt()eine dieser Optionen auf, überschreibt dies den voncurl_easy_impersonate()gesetzten Wert
Anwendung auf bestehende libcurl-Apps
- Wenn eine Anwendung bereits
libcurlnutzt, kann man unter Linux mitLD_PRELOADzur Laufzeit die bestehende Bibliothek ersetzen - Durch Setzen der Umgebungsvariable
CURL_IMPERSONATEwird die automatische Nachahmung angewendetLD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 my_app CURL_IMPERSONATEhat zwei Effekte- Wenn mit
curl_easy_init()ein neuer curl handle erzeugt wird, wird automatischcurl_easy_impersonate()aufgerufen - Auch nach
curl_easy_reset()wird automatischcurl_easy_impersonate()aufgerufen
- Wenn mit
- Wenn HTTP-Header exakt kontrolliert werden müssen, deaktiviert man mit
CURL_IMPERSONATE_HEADERS=nodie eingebaute Header-Liste und setzt sie selbstLD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 CURL_IMPERSONATE_HEADERS=no my_app - Die Methode mit
LD_PRELOADfunktioniert nicht für curl selbst- Grund ist, dass das curl-Tool die TLS-Einstellungen überschreibt
- Für curl muss man das Wrapper-Script verwenden
Repository-Struktur und Beiträge
- Das Repository enthält zwei Hauptordner
- Das Firefox-Verzeichnis enthält unter anderem folgende Dateien
- Dockerfile: wird verwendet, um
curl-impersonatemit allen Abhängigkeiten zu bauen - curl_ff91esr, curl_ff95, curl_ff98: Wrapper-Scripts zur Ausführung mit den richtigen Flags
- curl-impersonate.patch: der zentrale Patch, der curl dazu bringt, dieselben TLS-Erweiterungen wie Firefox zu verwenden, und es statisch mit libnghttp2 und libnss kompilieren lässt
- Dockerfile: wird verwendet, um
- tests/signatures ist eine YAML-Datenbank bekannter Browser signatures, die nachgeahmt werden können
- Die eigentlichen curl-Patches werden in einem separaten Repository gepflegt, das von upstream curl geforkt wurde
- Die Firefox-Änderungen befinden sich im Branch impersonate-firefox
- Die Chrome-Änderungen befinden sich im Branch impersonate-chrome
1 Kommentare
Meinungen auf Hacker News
Es gibt einen Fork mit ziemlich vielen Verbesserungen gegenüber dem Original, der aktiv gepflegt wird: https://github.com/lexiforest/curl-impersonate
Außerdem gibt es Bindings für Python-Nutzer: https://github.com/lexiforest/curl_cffi
Ironischerweise würde diese Anfrage den Server wohl weniger belasten als ein zertifizierter Browser; man fragt sich, ob das die Dystopie ist, vor der in den 90ern gewarnt wurde. Ich frage mich, wer hier das eine Unternehmen beim Namen nennen kann, das sich als guter Open-Source-/Hacker-Community-Beitragender positioniert und zugleich diese Situation geschaffen hat
Ich hoffe, dass Ladybird künftig an Fahrt gewinnt. Aktuell nutzt es für Networking das reguläre cURL, was mit Schwierigkeiten verbunden sein könnte
Soweit ich weiß, hat cURL zum Beispiel noch einige Einschränkungen und kann WebSocket über h2 nicht verarbeiten. Wenn dagegen eine wachsende Browser-Engine entsteht, könnte auch legitimer Traffic denselben Fingerprint wie Standard-cURL haben, wodurch dieser Fingerprinting-Pfad verschwinden könnte
Es ist auch ein guter Prüfstand, um zu sehen, welche Funktionen cURL gemessen an echten Browser-Workflows fehlen
In den letzten Monaten hat das Ausmaß an Fingerprinting und der „Ausnutzung“ implementierungsdefinierten Verhaltens deutlich zugenommen, vermutlich als Versuch, andere Browser-Engines zu erledigen. Die etablierten Platzhirsche mögen Konkurrenz überhaupt nicht
Die Gegenseite versucht, das als „DDoS durch KI-Bots“ darzustellen, aber ich frage mich, wie viel davon von ihnen selbst verursacht wurde
Ich mag dieses curl, aber ich mache mir Sorgen, dass sich eine schwer wartbare „Kompatibilitäts“-Last ansammelt, wenn irgendeine Komponente die Rolle des Tricksens übernimmt, um „mitzuhalten“
Idealerweise sollte man einfach sagen können: „Hallo, ich bin curl, lass mich rein“
Natürlich liegt das Problem bei Servern mit strengem Dresscode, und dieses Problem entsteht wiederum durch Betrüger, die verkleidet hineinkommen; es ist also ein Henne-Ei-Kreislauf
[0] https://cybershow.uk/episodes.php?id=39
Außerdem birgt es ein großes Sicherheitsrisiko, weil es in nachweislich unsicherem C++ neu entworfen wurde
Ob sie wohl auch
IP_TTLsetzen, damit der TTL-Wert zur Plattform passt, als die sie sich ausgeben wollen?Falls nicht, ist bis zu einem gewissen Grad auch auf IP-Ebene Fingerprinting möglich. Wenn der TTL-Wert auf IP-Ebene unter 64 liegt, ist klar, dass es entweder nicht auf modernem Windows läuft oder ein modernes Windows mit geändertem Standard-TTL ist. Denn der Standard-TTL von Paketen unter modernem Windows beginnt bei 128, während die meisten anderen Plattformen bei 64 beginnen
Da auch andere Plattformen problemlos über das Internet kommunizieren können, werden IP-Pakete von modernem Windows auf der Gegenseite immer mit einem TTL von 64 oder höher, wahrscheinlich etwas über 64, erscheinen. Fingerprinting auf IP-Ebene ist allerdings schwierig, aber nicht unmöglich
https://en.wikipedia.org/wiki/TCP/IP_stack_fingerprinting
Moment, wenn der TLS-Handshake anders aussieht, könnte man dann Traffic, der behauptet, ein Webbrowser zu sein, in Wirklichkeit aber ein Python-/PHP-Skript ist, nicht auf nginx-Ebene filtern?
Zum Beispiel Fälle mit Chrome-User-Agent, die aber kein echter Browser sind. Ein Großteil des bösartigen Bot-Traffics dürfte darunter fallen, also wäre es schön, wenn man ihn einfach blockieren könnte
Wie das funktioniert, ist ausführlich unter https://github.com/FoxIO-LLC/ja4/blob/main/technical_details... beschrieben, und es gibt auch ein Nginx-Modul: https://github.com/FoxIO-LLC/ja4-nginx-module
Wenn man nicht gerade tatsächlich angegriffen wird, sollte man keine Allowlist für TLS-Fingerprints verwenden
Ein tolles Tool, aber es sollte keine Rolle spielen, ob der Client ein Browser ist oder nicht. Es ist bitter, dass man in der Realität solche Tools braucht.
Ich habe in Chrome eine User-Agent-Erweiterung hinzugefügt, auf IE umgestellt und es erneut versucht; dann funktionierte es, und auch alle Funktionen der Seite liefen einwandfrei. Das war zugleich bitter und ärgerlich. Vermutlich hat diese Behörde ihre Website vor 25 Jahren gebaut und seitdem nicht mehr aktualisiert.
Diese Art von Gatekeeping finde ich ebenfalls bitter. Soweit ich es verstehe, werden selbstgebaute Custom-Browser oder User-Agents auf Cloudflare-artigen Websites niemals funktionieren, bis sie genug Einfluss, Geld, Nutzerzahlen oder Ähnliches haben, um diese Anbieter zu überzeugen.
Dieses Tool ist bei Red-Team-Arbeiten in Kombination mit kleinen bash-Skripten und GNU parallel ziemlich nützlich.
Es war hilfreich, um in als Bereich angegebenen Adressräumen HTTPS-Endpunkte zu kartieren, die aus verschiedenen Gründen nur auf richtige Browser reagieren oder nur bei passender SNI-Konfiguration antworten. Normale curl-Optionen wie
-Hzum Vortäuschen von Headern kann man weiterhin unverändert nutzen.Der damalige Show-HN-Beitrag: https://news.ycombinator.com/item?id=30378562
Jedes Mal, wenn so etwas hier auftaucht, habe ich gemischte Gefühle. Einerseits ist es schön zu sehen, dass unter den Leuten noch ein bisschen Widerspruchsgeist und Unabhängigkeit vorhanden ist.
Andererseits könnte, wie bei anderen Projekten, bei denen „Freiheit ist instabil“ behandelt wird, unerwünschte Aufmerksamkeit die Lage für die Menschen verschlechtern, die darauf angewiesen sind. Browser zu schreiben ist schwer, und die etablierten Platzhirsche machen es immer schwerer.
Ich sehe das nicht als Frage von Widerspruchsgeist. Dass Software fingerprintbar wird, untergräbt Datenschutz und Software-Vielfalt.
Ich vermisse ein wenig die einfachen Zeiten, in denen Websites Bots zuließen, wenn sie damit einverstanden waren, und User-Agents blockierten, wenn sie sie nicht mochten.
Wenn es nur drei Patches und ein Shell-Wrapper sind, könnte Daniel durchaus selbst Hand anlegen. Persönlich finde ich, dass das unbedingt in Mainline-curl gehört.