EYDefterEmre Yakut
← tüm yazılar
Sistem · derin

Kendi captcha’mı yazdım — beş katman, dördünü kimse görmüyor

Hazır bot korumasını kullanmak istemedim: kullanıcıyı üçüncü tarafa açıyor, bazı ülkelerde çalışmıyor ve görsel bulmaca insanı da yoruyor.

imzalı jetonHMAC · süreli · tek kullanımbal küpügizli alan doldurulduysa botiş kanıtıküçük hash bulmacası · CPU maliyetioran sınırıIP + jeton başına penceregörsel bulmacakendi harflerimiz, kendi çizimimiztek bir duvar değil — her katman ucuz, hepsi birlikte pahalıhiçbir katman kullanıcıyı görmüyor; beşincisi ancak dördü şüphelenirse çıkıyor

ArenaSim’in kayıt formuna bot yağmaya başladığında herkesin yaptığını yapmam bekleniyordu: hazır bir bot koruma servisi ekle, geç.

Üç sebepten yapmadım:

  • Kullanıcıyı üçüncü tarafa açıyor. Formumu dolduran herkesin tarayıcısı başka bir şirkete bağlanıyor ve ona veri veriyor.
  • Her yerde çalışmıyor. Bazı ülkelerde ilgili alan adları erişilemez; kullanıcı formu dolduramıyor ve nedenini anlamıyor.
  • Görsel bulmaca insanı da yoruyor. Bisikletli kareleri seçtirmek botu üç saniye, insanı on beş saniye oyalıyor. Oran giderek insanın aleyhine.

Kendim yazdım. Beş katman — ve normal bir kullanıcı ilk dördünün varlığını bilmiyor.

1. İmzalı jeton

Form sayfası sunulurken içine bir jeton gömülüyor: oturum + zaman damgası + imza.

jeton = base64( oturum_id | zaman | rastgele )
imza  = HMAC-SHA256( jeton, sunucu_sırrı )

Gönderimde üç koşul aranıyor: imza geçerli mi, jeton çok mu eski, daha önce kullanılmış mı.

Bu katman formu hiç açmadan doğrudan gönderim yapan botların tamamını eliyor. Basit bir betikle istek atanlar buradan geçemiyor — ve bunlar trafiğin büyük çoğunluğu.

2. Bal küpü

Formda görünmeyen bir alan var. İnsan göremiyor; formu ayrıştırıp bütün alanları dolduran bot dolduruyor.

<div aria-hidden="true" class="hp">
  <label>Şirket adı</label>
  <input name="company_name" tabindex="-1" autocomplete="off">
</div>
iki detay önemli

tabindex="-1" — klavyeyle gezen kullanıcı yanlışlıkla oraya düşmesin. autocomplete="off" — tarayıcının otomatik doldurması gerçek bir kullanıcıyı bot ilan etmesin.

Bal küpünün işe yaraması için hiçbir koşulda insan tarafından doldurulamaması gerekiyor.

3. İş kanıtı

Üçüncü katman maliyet yüklüyor. Sunucu bir zorluk gönderiyor; istemci belirli sayıda sıfırla başlayan bir hash bulana kadar deniyor.

bulunması istenen
SHA256( zorluk ‖ nonce ) → ilk 18 bit sıfır

Ortalama 2¹⁸ ≈ 262.000 deneme. Modern bir tarayıcıda yaklaşık 0,2 saniye — kullanıcı form doldururken arka planda bitiyor.

istektoplam maliyet
Normal kullanıcı10,2 sn
Bot10.000/saat33 dk saf CPU

Botu durdurmuyor — pahalı hale getiriyor. Çoğu spam işleminde marj o kadar ince ki, bu maliyet hedefi değiştirmeye yetiyor.

4. Oran sınırı

Klasik ama gerekli: IP ve jeton başına kayan pencere. İncelik, sınırı aşan isteği reddetmek yerine yavaşlatmak. Reddetme botu yeni IP aramaya gönderiyor; yavaşlatma onu meşgul tutuyor ve hiçbir şey öğretmiyor.

5. Ve ancak o zaman: görsel bulmaca

İlk dört katman şüphelenirse beşinci devreye giriyor. Kendi ürettiğim bir bulmaca: kendi harflerim, kendi çizimim, sunucuda üretiliyor, cevabı sunucuda tutuluyor.

Karmaşık değil — olmasına gerek de yok. Buraya gelen trafik zaten filtrelenmiş küçük bir kalıntı. Beşinci katmanın işi %99’u durdurmak değil, dördü geçmiş olan birkaç isteği yavaşlatmak.

Asıl fikir

Hazır bot korumasının mantığı “tek bir yüksek duvar”. Benimki farklı: beş alçak duvar.

Her katmanı tek başına aşmak kolay. Beşini birden aşmak için botun sırasıyla: sayfayı gerçekten açması, DOM’u doğru yorumlaması, JavaScript çalıştırması, hesaplama maliyetini ödemesi ve hız sınırına uyması gerekiyor.

Bu noktada bot bir tarayıcıya dönüşmüş oluyor — ve bir tarayıcı çalıştırmak, basit bir betik çalıştırmaktan yüzlerce kat pahalı.

Amaç imkânsız kılmak değil. Amaç, ekonomiyi bozmak.

Ne öğrendim

Güvenlikte “çözüldü / çözülmedi” diye bir durum yok; maliyet eğrisi var. Saldırganın maliyetini kullanıcının maliyetinden hızlı artıran her şey işe yarıyor.

Ve en iyi koruma, korunanın fark etmediği korumadır. Bu sistemde normal bir kullanıcının gördüğü tek şey, formun gönderilmesi.

Sistem