3 Punkte von GN⁺ 2025-04-04 | 1 Kommentare | Auf WhatsApp teilen
  • 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 libcurl genutzt 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, --curves und 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_chrome116 aus; bei der Integration als Bibliothek kann man curl_easy_impersonate() oder unter Linux LD_PRELOAD und CURL_IMPERSONATE verwenden, um es auf bestehende Apps anzuwenden, die libcurl nutzen

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 libcurl integriert 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

  • curl wird 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, --curves und 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.json enthalten
  • 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 chrome116 wird über das Wrapper-Script curl_chrome116 ausgeführt
    • Beispiel: Das Target ff117 wird über das Wrapper-Script curl_ff117 ausgeführt

Grundlegende Nutzung

  • Für jeden unterstützten Browser gibt es ein Wrapper-Script, das curl-impersonate mit 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-impersonate als Bibliothek enthalten

Installation und Bereitstellung

  • Aus technischen Gründen gibt es curl-impersonate in 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
  • 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
  • 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.so ist libcurl, kompiliert mit denselben Änderungen wie das Kommandozeilen-Tool curl-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 chrome116 aufgerufen, setzt sie intern die Optionen und Header, die sonst das Wrapper-Script setzen würde
  • Wenn default_headers 0 ist, wird die eingebaute Liste von HTTP-Headern nicht gesetzt
    • Nutzer müssen Header dann selbst über die normale libcurl-Option CURLOPT_HTTPHEADER bereitstellen
  • curl_easy_impersonate() setzt mehrere libcurl-Optionen
    • CURLOPT_HTTP_VERSION
    • CURLOPT_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 von curl_easy_impersonate() gesetzten Wert

Anwendung auf bestehende libcurl-Apps

  • Wenn eine Anwendung bereits libcurl nutzt, kann man unter Linux mit LD_PRELOAD zur Laufzeit die bestehende Bibliothek ersetzen
  • Durch Setzen der Umgebungsvariable CURL_IMPERSONATE wird die automatische Nachahmung angewendet
    LD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 my_app
    
  • CURL_IMPERSONATE hat zwei Effekte
    • Wenn mit curl_easy_init() ein neuer curl handle erzeugt wird, wird automatisch curl_easy_impersonate() aufgerufen
    • Auch nach curl_easy_reset() wird automatisch curl_easy_impersonate() aufgerufen
  • Wenn HTTP-Header exakt kontrolliert werden müssen, deaktiviert man mit CURL_IMPERSONATE_HEADERS=no die eingebaute Header-Liste und setzt sie selbst
    LD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 CURL_IMPERSONATE_HEADERS=no my_app
    
  • Die Methode mit LD_PRELOAD funktioniert 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
    • chrome: Scripts und Patches zum Bauen der Chrome-Version von curl-impersonate
    • firefox: Scripts und Patches zum Bauen der Firefox-Version von curl-impersonate
  • Das Firefox-Verzeichnis enthält unter anderem folgende Dateien
    • Dockerfile: wird verwendet, um curl-impersonate mit 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
  • 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

1 Kommentare

 
GN⁺ 2025-04-04
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

    • Dass ein Programm, das „curl wie einen Browser aussehen lässt“, von einem Dienst zum Umgehen von Bot-Erkennung gesponsert wird, ist gewissermaßen naheliegend
    • Es gibt auch ein Modul, das dies vollständig in die Python-requests-Bibliothek integriert: https://github.com/el1s7/curl-adapter
    • Es ist schon seltsam, dass man mit „fortgeschrittenen“ Techniken Schritt halten muss, die sich schneller ändern, als man den Kopf drehen kann, nur um eine simple Anfrage zu bauen, die wie einer der drei „zertifizierten“ großen Webbrowser aussieht
      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

    • Ich hoffe, dass Ladybirds Nutzung von cURL dazu beiträgt, cURL selbst zu verbessern, etwa bei dem erwähnten WebSocket über h2
      Es ist auch ein guter Prüfstand, um zu sehen, welche Funktionen cURL gemessen an echten Browser-Workflows fehlen
    • Der Teil „wenn eine wachsende Browser-Engine entsteht, könnte dieser Fingerprinting-Pfad verschwinden“ ist nach dem, was ich bei CloudFlare und ähnlichen Anbietern gesehen habe, eher das genaue Gegenteil
      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
    • Als ich mit diesen Leuten gesprochen habe [0], ging es um mehrere seltsame Implementierungsunterschiede, die Signaturen erzeugen, darunter sogar Elemente des TCP-Stacks, die eine User-Space-App nicht kontrollieren kann
      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
    • Ich hoffe, dass Ladybird dadurch ftp-URLs unterstützt
    • Ladybird hat nicht die Ressourcen, um mit aktuellen Browsern zu konkurrieren. Die PR war gut, aber gegenüber Chromium fehlen Vorteile oder ein Existenzgrund
      Außerdem birgt es ein großes Sicherheitsrisiko, weil es in nachweislich unsicherem C++ neu entworfen wurde
  • Ob sie wohl auch IP_TTL setzen, 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

    • Schwierig ist es nur, wenn man PaaS/IaaS nutzt, das keinen Low-Level-Zugriff auf den TCP/IP-Stack bietet. Wenn man eigene Server betreibt, ist Fingerprinting über alle möglichen TCP/IP-Eigenschaften sehr einfach
      https://en.wikipedia.org/wiki/TCP/IP_stack_fingerprinting
    • Hängt der TTL-Wert eingehender Pakete nicht vom Netzwerkzustand ab? Kann der Server den ursprünglichen Wert des Clients rekonstruieren?
    • Warum wurde TTL eigentlich so entworfen, dass es herunterzählt statt hochzählt? Erwartet man im Allgemeinen nicht, dass die Stelle, die Traffic routet, entscheidet, ob und wie geroutet wird?
  • 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

    • Cloudflare verwendet JA3/JA4-TLS-Fingerprints, also Hashes mehrerer TLS-Handshake-Parameter
      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
    • Im Grunde machen Sicherheitsanbieter wie Cloudflare genau das, und zusätzlich betreiben sie noch mehr Fingerprinting, etwa JavaScript-Challenges, die JavaScript-Interpreter/DOM prüfen
    • Das ist möglich und reale Sites machen es auch, aber es ist wirklich schlecht. Es ist unzuverlässig und blockiert am Ende alle, die nicht das neueste Chrome auf aktuellem Windows verwenden
      Wenn man nicht gerade tatsächlich angegriffen wird, sollte man keine Allowlist für TLS-Fingerprints verwenden
    • Das Tool aus dem Artikel scheint genau dazu gedacht zu sein, solche Sperren zu umgehen
  • 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.

    • Vor etwa sechs Monaten war ich auf einer staatlichen Auktionsseite, die Internet Explorer verlangte. Es war wirklich Internet Explorer, und die Seite war auch aktiv, die Auktionsdaten waren also aktuell.
      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.
    • Man darf unsere Seite nur mit der von uns genehmigten Software betreten. Alles andere gilt als bösartig. Papiere bitte!
      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 -H zum Vortäuschen von Headern kann man weiterhin unverändert nutzen.

  • Der damalige Show-HN-Beitrag: https://news.ycombinator.com/item?id=30378562

    • Damals, 2022, war es nur für Firefox.
  • 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.

    • Das klingt, als wollten Browser-Entwickler, dass Browser fingerprintbar sind, aber es ist eher etwas, das von selbst entsteht, weil unterschiedliche Leute Dinge unterschiedlich implementieren.
      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.

    • Damals verbrauchten Websites nicht so viele Ressourcen wie heute. Die negative Gegenreaktion auf Bots sehe ich eher als Nebenwirkung davon, dass die Erwartungen an das Web-Erlebnis übermäßig schwergewichtig geworden sind.
  • 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.