curl-impersonate: Başlıca tarayıcıları taklit edebilen özel bir curl derlemesi
(github.com/lwthiker)- curl-impersonate, Chrome, Edge, Safari ve Firefox gibi görünen TLS ve HTTP handshake’leri gerçekleştirecek şekilde değiştirilmiş bir curl derlemesidir; CLI aracı ve
libcurlyerine geçebilen bir kütüphane olarak kullanılabilir - Genel HTTP istemcileri ve kütüphanelerinin Client Hello ve HTTP/2 ayarları gerçek tarayıcılardan büyük ölçüde farklıdır; bu yüzden bazı web servisleri istemciyi TLS/HTTP handshake üzerinden tanımlayıp farklı içerik sunar
- Uygulama, Firefox için NSS, Chrome tabanlı tarayıcılar için BoringSSL kullanır; TLS uzantıları, SSL seçenekleri ve HTTP/2 ayarlarını değiştirir ve
--ciphers,--curves, header’lar gibi varsayılan dışı bayraklar uygular - Desteklenen hedefler Chrome 99~116, Android Chrome 99, Edge 99·101, Firefox 91 ESR~117 ve Safari 15.3·15.5’tir; her hedef için bir wrapper script ve target name sağlanır
- Komut satırında
curl_chrome116çalıştırılır; kütüphane entegrasyonunda isecurl_easy_impersonate()ya da Linux’taLD_PRELOADveCURL_IMPERSONATEile mevcutlibcurlkullanan uygulamalara uygulanabilir
curl-impersonate’ın çözdüğü sorun
- curl-impersonate, curl’ün Chrome, Edge, Safari ve Firefox olmak üzere dört büyük tarayıcıyı taklit edebilmesi için özel olarak derlendiği bir projedir
- TLS ve HTTP handshake’lerini gerçek tarayıcılarla aynı şekilde gerçekleştirebilir
- İki kullanım biçimi vardır
- Normal curl’a benzer bir komut satırı aracı
- Mevcut
libcurlyerine entegre edilebilen bir kütüphane
Neden gerekli
- Bir HTTP istemcisi TLS web sitesine bağlandığında önce bir TLS handshake gerçekleştirir
- TLS handshake’in ilk mesajı Client Hello’dur ve çoğu HTTP istemcisi ile kütüphanenin oluşturduğu Client Hello gerçek tarayıcılardan ciddi biçimde farklıdır
- Sunucu HTTP/2 kullanıyorsa TLS handshake’e ek olarak bir HTTP/2 handshake de yapılır ve burada çeşitli ayarlar değiş tokuş edilir
- Çoğu HTTP istemcisi ve kütüphanesinin HTTP/2 ayarları da gerçek tarayıcılardan farklıdır
- Bazı web servisleri bu farkları kullanarak bağlanan istemciyi tanımlar ve istemciye göre farklı içerik sunar
- Bu yöntem TLS fingerprinting ve HTTP/2 fingerprinting olarak adlandırılır
- README’ye göre bu yöntemlerin yaygın kullanımı web’i daha az açık, daha az özel ve belirli web istemcilerine daha kısıtlı hale getirmiştir
Nasıl çalışır
curl, tarayıcı gibi görünecek şekilde yoğun biçimde yamalanmıştır- Başlıca değişiklikler şunlardır
- Firefox sürümü, OpenSSL yerine Firefox’un kullandığı TLS kütüphanesi NSS ile derlenir
- Chrome sürümü, Google’ın TLS kütüphanesi BoringSSL ile derlenir
- curl’ün çeşitli TLS uzantıları ve SSL seçeneklerini ayarlama biçimi değiştirilir
- Yeni TLS uzantıları desteği eklenir
- HTTP/2 bağlantılarında kullanılan ayarlar değiştirilir
- curl,
--ciphers,--curvesve bazı-Hheader’ları gibi varsayılan dışı bayraklarla çalıştırılır
- Sonuç olarak ağ perspektifinden bakıldığında curl gerçek bir tarayıcıyla aynı görünür
- Tam teknik açıklama part a ve part b içinde yer alır
Desteklenen tarayıcılar ve hedef adları
- Desteklenen tarayıcı listesi
browsers.jsoniçinde de sunulur - Chrome tabanlı desteklenen hedefler
- Windows 10 üzerinde Chrome 99, 100, 101, 104, 107, 110, 116
- Android 12 üzerinde Chrome 99
- Windows 10 üzerinde Edge 99, 101
- MacOS Big Sur üzerinde Safari 15.3
- MacOS Monterey üzerinde Safari 15.5
- Firefox desteklenen hedefleri
- Windows 10 üzerinde Firefox 91 ESR, 95, 98, 100, 102, 109, 117
- Her desteklenen hedef için bir target name ve wrapper script vardır
- Örn:
chrome116hedeficurl_chrome116wrapper script’i ile çalıştırılır - Örn:
ff117hedeficurl_ff117wrapper script’i ile çalıştırılır
- Örn:
Temel kullanım
- Her desteklenen tarayıcı için gerekli header ve bayrakları içeren bir wrapper script ile
curl-impersonateçalıştırılır - Çalıştırma örneği
curl_chrome116 https://www.wikipedia.org - Ek komut satırı bayrakları verilirse curl’e aktarılır
- Bazı bayraklar curl’ün TLS signature’ını değiştirerek tespit edilmesine neden olabilir
- Wrapper script varsayılan bir HTTP header seti kullanır
- Header’ları değiştirmek istenirse wrapper script amaca göre düzenlenebilir
- Daha fazla seçenek,
libcurl-impersonate’ın kütüphane olarak kullanıldığı gelişmiş kullanım bölümünde yer alır
Kurulum ve dağıtım biçimi
- Teknik nedenlerle
curl-impersonateiki sürümden oluşur- chrome sürümü: Chrome, Edge ve Safari taklidi için kullanılır
- firefox sürümü: Firefox taklidi için kullanılır
- Linux ve macOS Intel için önceden derlenmiş binary’ler GitHub releases üzerinden sağlanır
- Önceden derlenmiş binary’leri kullanmadan önce NSS ve CA sertifikalarının kurulması gerekir
- 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:
- Sistemde ayrıca zlib de gerekir
- zlib neredeyse her zaman bulunur, ancak bazı minimal sistemlerde olmayabilir
- Önceden derlenmiş Linux binary’leri Ubuntu sistemleri için oluşturulmuştur
- Diğer dağıtımlarda sertifika doğrulama hatası alınırsa CA sertifikalarının konumunu curl’e belirtmek gerekebilir
curl_chrome116 https://www.wikipedia.org --cacert /etc/ssl/certs/ca-bundle.crt - Kaynaktan derleme için INSTALL.md dosyasına bakılabilir
Docker ve paketler
- Alpine Linux ve Debian tabanlı Docker imajları Docker Hub üzerinde sunulur
- Docker imajları binary’leri ve tüm wrapper script’leri içerir
- Örnek
# 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 kullanıcıları AUR paketlerini kullanabilir
- Önceden derlenmiş paketler: curl-impersonate-bin, libcurl-impersonate-bin
- Kaynaktan derleme paketleri: curl-impersonate-chrome, curl-impersonate-firefox
- Mac için gayriresmî Homebrew formula yalnızca Chrome sürümü için sunulur
brew tap shakacode/brew brew install curl-impersonate
libcurl-impersonate gelişmiş kullanım
libcurl-impersonate.so, komut satırındakicurl-impersonateile aynı değişikliklerle derlenmiş bir libcurl sürümüdür- Ek bir API fonksiyonu vardır
CURLcode curl_easy_impersonate(struct Curl_easy *data, const char * target, int default_headers); chrome116gibi bir target name ile çağrıldığında, wrapper script’in ayarladığı seçenekleri ve header’ları içeride ayarlardefault_headers0 ise yerleşik HTTP header listesi ayarlanmaz- Bu durumda kullanıcı header’ları normal
CURLOPT_HTTPHEADERlibcurl seçeneği ile kendisi sağlamalıdır
- Bu durumda kullanıcı header’ları normal
curl_easy_impersonate()birden çok libcurl seçeneği ayarlarCURLOPT_HTTP_VERSIONCURLOPT_SSLVERSION,CURLOPT_SSL_CIPHER_LIST,CURLOPT_SSL_EC_CURVES,CURLOPT_SSL_ENABLE_NPN,CURLOPT_SSL_ENABLE_ALPN- Projeye özgü standart dışı seçenek
CURLOPT_HTTPBASEHEADER - Projeye özgü standart dışı HTTP/2 seçenekleri
CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER,CURLOPT_HTTP2_NO_SERVER_PUSH - Projeye özgü standart dışı TLS seçenekleri
CURLOPT_SSL_ENABLE_ALPS,CURLOPT_SSL_SIG_HASH_ALGS,CURLOPT_SSL_CERT_COMPRESSION,CURLOPT_SSL_ENABLE_TICKET - Projeye özgü standart dışı TLS seçeneği
CURLOPT_SSL_PERMUTE_EXTENSIONS
- Sonrasında bu seçeneklerden biri
curl_easy_setopt()ile çağrılırsa,curl_easy_impersonate()tarafından ayarlanan değer geçersiz kılınır
Mevcut libcurl uygulamalarına uygulama
- Uygulama hâlihazırda
libcurlkullanıyorsa Linux üzerindeLD_PRELOADile mevcut kütüphane çalışma zamanında değiştirilebilir - Otomatik taklit uygulamak için
CURL_IMPERSONATEortam değişkeni ayarlanırLD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 my_app CURL_IMPERSONATEiki etkiye sahiptircurl_easy_init()ile yeni bir curl handle oluşturulduğundacurl_easy_impersonate()otomatik olarak çağrılırcurl_easy_reset()sonrasında dacurl_easy_impersonate()otomatik çağrılır
- HTTP header’ları üzerinde hassas kontrol gerekirse yerleşik header listesi
CURL_IMPERSONATE_HEADERS=noile devre dışı bırakılıp elle ayarlanabilirLD_PRELOAD=/path/to/libcurl-impersonate.so CURL_IMPERSONATE=chrome116 CURL_IMPERSONATE_HEADERS=no my_app LD_PRELOADyöntemi curl’ün kendisinde çalışmaz- Çünkü curl aracı TLS ayarlarını üzerine yazar
- curl için wrapper script kullanılmalıdır
Depo yapısı ve katkı
- Depoda iki ana klasör bulunur
- Firefox dizini örnek olarak şu dosyaları içerir
- Dockerfile: Tüm bağımlılıklarla birlikte
curl-impersonatederlemek için kullanılır - curl_ff91esr, curl_ff95, curl_ff98: Doğru bayraklarla çalışan wrapper script’ler
- curl-impersonate.patch: curl’ün Firefox ile aynı TLS uzantılarını kullanmasını sağlayan ana yamadır ve
libnghttp2ilelibnsskullanacak şekilde statik derleme yapar
- Dockerfile: Tüm bağımlılıklarla birlikte
- tests/signatures, taklit edilebilen bilinen tarayıcı signature’larının YAML veritabanıdır
- Gerçek curl yamaları, upstream curl’den fork edilmiş ayrı bir depoda tutulur
- Firefox değişiklikleri impersonate-firefox branch’inde bulunur
- Chrome değişiklikleri impersonate-chrome branch’inde bulunur
1 yorum
Hacker News yorumları
Orijinaline göre epey fazla iyileştirme içeren ve aktif olarak bakımı yapılan bir fork var: https://github.com/lexiforest/curl-impersonate
Python kullanıcıları için binding’ler de var: https://github.com/lexiforest/curl_cffi
İşin ironik yanı, o istek sunucuya sertifikalı bir tarayıcıdan daha az yük bindirecek; 90’larda uyarısı yapılan distopya bu mu acaba. Kendini iyi niyetli açık kaynak/hacker topluluğu katkıcısı olarak konumlandırırken bu durumu yaratan o tek şirketin adını burada kim verebilir merak ediyorum
İleride Ladybird’ün güç kazanmasını umuyorum. Şu anda networking için resmi cURL’ü kullanıyor; bu yaklaşımın zorlukları olabilir
Örneğin bildiğim kadarıyla cURL’ün hâlâ bazı kısıtları var ve h2 üzerinde WebSocket’i işleyemiyor. Öte yandan büyüyen bir tarayıcı motoru ortaya çıkarsa normal trafik de temel cURL ile aynı parmak izine sahip olur ve bu parmak izi alma yolu ortadan kalkabilir
Gerçek tarayıcı iş akışları temelinde cURL’de hangi özelliklerin eksik olduğunu görmek için de iyi bir test alanı
Son birkaç ayda parmak izi alma ve uygulama tanımlı davranışları “istismar etme” düzeyi ciddi biçimde arttı; muhtemelen başka tarayıcı motorlarını öldürme girişimi gibi görünüyor. Mevcut güçlü oyuncular rekabetten hiç hoşlanmıyor
Karşı taraf bunu “yapay zeka botlarının DDoS’u” diye paketlemeye çalışıyor, ama bunun ne kadarının kendi yarattıkları bir iş olduğu şüpheli
Bu curl hoşuma gidiyor, ama bir bileşen “yetişmek” için kandırmaca rolünü üstlendiğinde bakımı zor bir “uyumluluk” yükünün birikmesinden endişe ediyorum
İdeal olarak sadece “Merhaba, ben curl’üm, içeri al beni” diyebilmeliyiz
Elbette sorun kıyafet kuralları konusunda titiz sunucularda; o sorun da kılık değiştirip içeri giren dolandırıcılar yüzünden ortaya çıkıyor, yani tavuk-yumurta gibi döngüsel
[0] https://cybershow.uk/episodes.php?id=39
Ayrıca kanıtlanabilir biçimde güvenli olmayan C++ ile yeniden tasarlanmış olması büyük bir güvenlik riski
Taklit etmeye çalıştığı platforma göre TTL değerini eşleştirmek için
IP_TTLde ayarlanmış mı?Ayarlanmadıysa IP katmanında da bir ölçüde parmak izi alınabilir. IP katmanındaki TTL değeri 64’ün altındaysa, modern Windows’ta çalışmadığı ya da varsayılan TTL’i değiştirilmiş modern Windows olduğu açıktır. Çünkü modern Windows paketlerinin varsayılan TTL’i 128’den başlar, diğer platformların çoğu ise 64’ten başlar
Diğer platformlarda da internet iletişiminde sorun olmadığı için, modern Windows’tan gelen IP paketleri uzak tarafta her zaman 64 veya üzeri, muhtemelen 64’ten biraz yüksek bir TTL ile görünür. Yine de IP katmanı parmak izi alma zor ama imkânsız değil
https://en.wikipedia.org/wiki/TCP/IP_stack_fingerprinting
Bir dakika, TLS el sıkışması farklı görünüyorsa, web tarayıcısı olduğunu iddia eden ama aslında Python/PHP betiği olan trafiği nginx seviyesinde filtreleyemez miyiz?
Örneğin Chrome user-agent kullanan ama gerçek tarayıcı olmayan durumlar. Kötü niyetli bot trafiğinin çoğu buna giriyor olmalı; doğrudan engelleyebilsek iyi olurdu
Nasıl çalıştığı https://github.com/FoxIO-LLC/ja4/blob/main/technical_details... adresinde ayrıntılı anlatılıyor; bir Nginx modülü de sunuluyor: https://github.com/FoxIO-LLC/ja4-nginx-module
Şu anda fiilen saldırı altında değilseniz TLS parmak izi izin listesi kullanmamalısınız
Harika bir araç, ama istemcinin tarayıcı olup olmaması önemli olmamalı. Gerçekte böyle bir araca ihtiyaç duyulması acı verici.
Chrome'a kullanıcı aracısı uzantısı ekleyip IE olarak değiştirerek tekrar denedim; çalıştı ve sitenin tüm işlevleri de sorunsuzdu. Bu yüzden hem buruk hem de sinir bozucuydu. Muhtemelen o devlet kurumu web sitesini 25 yıl önce yapmış ve o zamandan beri güncellememiş gibi.
Bu tür gatekeeping bana da acı verici geliyor. Anladığım kadarıyla, kendi yaptığınız özel tarayıcılar ya da kullanıcı aracıları; onları ikna edebilecek yeterli etki, para, kullanıcı sayısı gibi şeyler oluşana kadar Cloudflare tarzı sitelerde asla çalışmayacak.
Bu araç, red team çalışmalarında küçük bash betikleri ve GNU parallel ile birlikte kullanıldığında oldukça iyi.
Kapsam olarak belirlenmiş adres aralıklarında, çeşitli nedenlerle yalnızca düzgün bir tarayıcıya yanıt veren veya SNI yapılandırması doğruysa yanıt veren HTTPS endpoint'lerini haritalarken faydalı oldu. Başlık taklidi için
-Hgibi normal curl seçenekleri de aynen kullanılabiliyor.O zamanki Show HN gönderisi: https://news.ycombinator.com/item?id=30378562
Böyle şeyler burada her paylaşıldığında hep karışık duygulara kapılıyorum. Bir yandan insanlar arasında hâlâ biraz asi ruh ve bağımsızlığın yaşadığını göstermesi hoşuma gidiyor.
Öte yandan, “özgürlük istikrarsızdır” muamelesi gören diğer projelerde olduğu gibi, istenmeyen ilgiyi üzerine çekerse buna bağımlı olan insanlar için durum daha da kötüleşebilir. Tarayıcı yazmak zor ve mevcut güçlü oyuncular bunu sürekli daha da zorlaştırıyor.
Bunu bir asi ruh meselesi olarak görmüyorum. Yazılımların parmak iziyle tanımlanabilir hâle gelmesi gizlilik korumasını ve yazılım çeşitliliğini aşındırıyor.
Web sitelerinin botları sorun etmiyorsa izin verdiği, istemiyorsa kullanıcı aracısını engellediği basit zamanları biraz özlüyorum.
Sadece 3 yama ve bir shell wrapper'dan ibaretse Daniel'ın kodlamaya girişmesine değer. Şahsen bunun mutlaka mainline curl'e girmesi gerektiğini düşünüyorum.