Çoğu satıcı webhook'u masum bir bildirim sanır. "Tedarikçi işlem tamamlandı diyor, ben de siparişi teslim ediyorum" diye düşünür. Oysa webhook, internetin herhangi bir yerinden senin sunucuna açılmış bir kapıdır ve o kapıdan geçen isteğin gerçekten tedarikçinden geldiğine dair tek kanıtın, senin yazdığın doğrulama kodudur. Doğrulama yoksa kanıt da yoktur. Kanıt yoksa o uç nokta, adresini bilen herkesin sipariş teslim ettirebileceği bir düğmeye dönüşür.
Bu açık gürültülü değil, sessizdir. Sunucun çökmez, hata logu birikmez, panelde kırmızı bir uyarı yanmaz. Sadece bir gün ciro ile tedarikçi maliyetini karşılaştırdığında rakamların tutmadığını görürsün; teslim edilmiş ama hiç satın alınmamış onlarca kod bulursun. Aşağıda bir e-pin satış scripti tarafında webhook doğrulamanın tam katmanlarını anlatıyorum: imza, zaman penceresi, tekrar koruması, idempotency ve en sonunda "webhook'a hiç inanmayan" mimari. Sırayla oku, çünkü her katman bir öncekinin bıraktığı boşluğu kapatıyor.
Webhook'u "Tedarikçi Gönderdi" Diye Kabul Etmek Neden Kapıyı Açık Bırakmaktır?
Webhook adresin gizli değildir. Tarayıcı geçmişinde, sunucu loglarında, hata bildirimlerinde, bazen de tedarikçinin panelinde görünür. Kötü niyetli bir kişi o adrese doğru biçimli bir JSON gövdesi gönderdiğinde ne olur? Doğrulama yapmayan bir dijital ürün satış scripti gövdedeki sipariş numarasını okur, siparişi başarılı işaretler ve kodu ekrana basar. Saldırgan hiç ödeme yapmamıştır. Daha kötüsü, bu işlem senin stoktan düşer; yani sattığını sandığın ama hiç parası gelmeyen bir maliyet doğar. Bazı sistemlerde gövdedeki tutar alanı da güvenilmez biçimde okunur ve bakiye yükleme bildirimi taklit edilerek cüzdana para basılır. Buradaki temel hata, HTTP isteğinin kaynağına dair hiçbir kriptografik kanıt aramamaktır. Ağ üzerinden gelen hiçbir veri, doğrulanmadığı sürece veri değil iddiadır. Bu cümleyi bir yere yaz, çünkü webhook güvenliğinin tamamı bunun üzerine kurulu.
İmza Doğrulama: HMAC Neden Tek Başına Yetmez?
İlk katman imzadır. Tedarikçi sana bir gizli anahtar verir; isteği gönderirken gövdenin HMAC-SHA256 özetini hesaplayıp bir başlıkta iletir. Sen de aynı anahtarla aynı hesabı yapar ve iki değeri karşılaştırırsın. Burada üç klasik hata var. Birincisi, karşılaştırmayı normal eşitlikle yapmak: zamanlama saldırısına açık olur, sabit zamanlı karşılaştırma fonksiyonu kullanılmalı. İkincisi, imzayı çözümlenmiş gövde üzerinden hesaplamak. JSON'u diziye çevirip sonra yeniden metne dönüştürürsen boşluk, sıra ve karakter kaçışları değişir, imza asla tutmaz; bu yüzden ham gövde mutlaka işlenmeden önce saklanmalıdır. Üçüncüsü ve en tehlikelisi, imza tutmadığında işlemi yine de devam ettirmek. Bazı panellerde "imza uyuşmazsa logla ama geç" gibi bir esneklik bırakılmış; bu, kilidi takıp anahtarı kapı önüne bırakmaktır. İmza doğru kurulduğunda isteğin kaynağını kanıtlarsın, ama ne zaman gönderildiğini kanıtlamazsın. Sıradaki katman tam bunun için var.
| Katman | Hangi saldırıyı engeller | Yoksa ne olur | Doğru uygulama |
|---|---|---|---|
| HMAC imza | Sahte bildirim üretme | Bedava kod teslimi | Ham gövde + sabit zamanlı karşılaştırma |
| Zaman damgası penceresi | Eski isteğin yeniden kullanımı | Geçmiş bildirimler tekrar işler | ±5 dakika, sunucu saati NTP ile senkron |
| Olay kimliği kaydı | Tekrar (replay) saldırısı | Aynı sipariş 40 kez teslim | Benzersiz indeks, kalıcı tablo |
| Idempotency anahtarı | Çift işleme ve yarış durumu | Aynı koda iki müşteri | Kilitli işlem + tek satır güncelleme |
| IP beyaz listesi | Rastgele tarama ve yük | Uç nokta gürültüye açık | Tedarikçi IP aralığı, imzanın yerine değil yanına |
| Zorunlu TLS | Ortadaki adam ve anahtar sızması | İmza anahtarı ağda görülebilir | Sadece HTTPS, yönlendirme değil ret |
Tekrar Saldırısı: Aynı Bildirim 40 Kez Gelirse Ne Olur?
Geçerli imzalı bir isteği yakalayıp aynısını tekrar tekrar göndermek, imza doğrulamasını bozmaz; çünkü imza gerçekten geçerlidir. İşte replay saldırısı budur. Savunma iki parçalı: zaman damgası ve olay kimliği. Tedarikçi isteğe bir zaman damgası koyuyorsa onu da imzanın içine dahil et ve beş dakikadan eski istekleri reddet. Bu, saldırgana çok kısa bir pencere bırakır. Pencereyi tamamen kapatmak içinse her olayın benzersiz kimliğini veritabanında sakla ve aynı kimliğin ikinci gelişinde işlemi yapmadan 200 döndür. Dikkat: burada 200 dönmek önemli, hata dönersen tedarikçi denemeye devam eder ve logların şişer. Bu tabloyu geçici önbellekte tutma alışkanlığı yaygın ama hatalıdır; sunucu yeniden başladığında koruma buharlaşır. Kalıcı tabloda benzersiz indeksle tut, temizliğini de otuz günlük bir işle yap. Böylece e-pin yazılımı tarafında aynı bildirim yüz kez gelse bile sonuç tek bir teslimat olur.
Doğrulanmamış webhook'ların yol açtığı olay dağılımı
- Çift ve çoklu teslimat 50%
- Sahte bildirimle bedava kod 25%
- Bakiye ve cüzdan manipülasyonu 15%
- Sipariş durumu bozulması 10%
Idempotency Anahtarı Olmayan Scriptte Çift Teslimat Kaçınılmazdır
Replay koruması kötü niyeti engeller, idempotency ise iyi niyetli kazaları engeller. Tedarikçiler yanıt alamadıklarında bildirimi tekrar gönderir; bu normal ve doğru davranıştır. Senin tarafın da bunu sorunsuz karşılamak zorunda. Kritik nokta, iki bildirim milisaniyeler arayla geldiğinde ortaya çıkan yarış durumudur. Kod şöyle yazıldıysa tehlike var: siparişi oku, durumu kontrol et, teslim et, durumu güncelle. İki paralel süreç aynı anda okursa ikisi de "henüz teslim edilmemiş" görür ve iki kod gider. Doğru yöntem, kontrolü ve güncellemeyi tek bir atomik adıma indirmek: yalnızca durumu "bekliyor" olan satırı "işleniyor" yapan koşullu bir güncelleme çalıştır, güncellenen satır sayısı sıfırsa çık. Bu tek satırlık disiplin, epin yazılım tarafındaki çift teslimatların neredeyse tamamını bitirir. Kuponlu bakiye yüklemelerinde ise aynı mantığı cüzdan hareketi tablosundaki benzersiz referansla kurmalısın; cüzdanı doğrudan artırmak yerine hareket kaydı yaz, bakiyeyi hareketlerden türet.
İmza geçerli olsa bile gövdedeki tutarı kendi sipariş kaydındaki tutarla karşılaştır. Pinova'da bildirim yalnızca tetikleyicidir; karar her zaman kendi veritabanındaki sipariş satırı ve tedarikçiye yapılan doğrulama sorgusuyla verilir. Tutar uyuşmazsa sipariş otomatik olarak manuel incelemeye düşer.
IP Listesi, TLS ve Ham Gövde: Üç Küçük Detay, Üç Büyük Fark
Bu üçü genelde "detay" diye atlanır ama her biri gerçek olayların kökünde duruyor. IP beyaz listesi imzanın yerine geçmez; tedarikçi IP'lerini bilmek gürültüyü keser, tarayıcı botlarını uzak tutar, ama IP taklit edilebileceği için tek savunma olamaz. TLS tarafında sık yapılan hata, HTTP isteğini HTTPS'e yönlendirmekle yetinmek: yönlendirme öncesinde başlıklar ve gövde şifrelenmemiş ağda bir kez yolculuk etmiş olur. Doğrusu, şifresiz gelen webhook isteğini yönlendirmek değil reddetmektir. Ham gövde meselesi ise framework kaynaklı: bazı katmanlar gövdeyi otomatik ayrıştırır ve orijinal baytlara erişimi kapatır; bu durumda imza doğrulaması imkansız hale gelir ve geliştirici çareyi doğrulamayı kapatmakta bulur. Bu yüzden webhook uç noktası her zaman en dış katmanda, ham gövdeye erişebilen özel bir girişte durmalı. Üçünü birlikte kurarsan dijital ürün satış yazılımı tarafında webhook yüzeyin kapanmış olur.
Webhook'a Asla Güvenmeyen Mimari: Doğrula, Sonra Sor
Gerçekten olgun sistemlerin sırrı şu: webhook'u bilgi kaynağı değil, uyandırma sinyali olarak kullanmak. Bildirim geldi, imzayı doğruladın, olay kimliğini kaydettin. Şimdi gövdedeki "başarılı" ifadesine bakarak teslim etmek yerine tedarikçiye kendi referansınla bir durum sorgusu gönder ve cevabı ondan al. Bu tek hamle, imza anahtarının sızdığı senaryoda bile seni korur; çünkü saldırgan sahte bildirim üretebilse de tedarikçinin sorgu cevabını değiştiremez. Ayrıca webhook hiç gelmediğinde de aynı sorgu mekanizması periyodik bir işle çalışır, yani kayıp bildirim diye bir sorunun kalmaz. Maliyeti nedir? Sipariş başına bir ek istek. Kazancı nedir? Teslimat kararının tek ve güvenilir bir otoriteye bağlanması. Ciddi bir e-pin satış yazılımı bu maliyeti tereddütsüz öder, çünkü alternatif, kasanın dışarıdan gelen bir JSON'a emanet edilmesidir.
| Denetim maddesi | Nasıl test edilir | Beklenen sonuç |
|---|---|---|
| İmzasız istek reddediliyor mu? | Başlık olmadan gövde gönder | 401, teslimat yok |
| Bozuk imza reddediliyor mu? | İmzanın son karakterini değiştir | 401, log kaydı var |
| Eski zaman damgası reddediliyor mu? | 10 dakika öncesine ait imzalı istek | Reddedilir |
| Aynı olay iki kez işliyor mu? | Geçerli isteği 5 kez tekrarla | Tek teslimat, 5 kez 200 |
| Eş zamanlı istek çift teslim ediyor mu? | Aynı anda 10 paralel istek | Tek teslimat |
| Tutar uyuşmazlığı yakalanıyor mu? | Gövdedeki tutarı değiştir | Manuel incelemeye düşer |
| HTTP isteği reddediliyor mu? | Şifresiz uç noktaya gönder | Yönlendirme değil ret |
| Webhook hiç gelmezse ne oluyor? | Bildirimi engelle, bekle | Periyodik sorgu tamamlar |
Webhook yüzeyin denetlenmiş bir altyapıyla çalış
Pinova'da her tedarikçi bildirimi imza, zaman penceresi, olay kimliği ve karşı sorgu katmanlarından geçer. Çift teslimat ve sahte bildirim mimari olarak imkansızdır. Lisans ve özellik detaylarına bak.
Tedarikçim imza göndermiyor, ne yapmalıyım?
Bu durumda webhook'u yalnızca uyandırma sinyali olarak kullan: gövdeye hiç güvenme, gelen bildirimle birlikte tedarikçiye kendi referansınla durum sorgusu at ve kararı o cevaba göre ver. Ek olarak IP kısıtlaması ve tahmin edilemez uzun bir uç nokta adresi kullan.
Olay kimliklerini ne kadar süre saklamalıyım?
Pratikte 30 gün yeterlidir, çünkü tedarikçilerin tekrar deneme pencereleri genelde saatlerle ölçülür. Tabloyu benzersiz indeksle kur, eski kayıtları periyodik bir işle temizle. Geçici önbellekte tutma; sunucu yeniden başladığında koruman kaybolur.
İmza doğrulaması başarısız olursa hangi HTTP kodunu dönmeliyim?
401 veya 403 dön ve gövdeye hiçbir açıklama yazma. Hangi kontrolün başarısız olduğunu dışarıya bildirmek saldırgana yol gösterir. Detayı sadece kendi log kaydına yaz; gerçek tedarikçi zaten doğru imzayla geldiğinde sorun yaşamaz.
Çift teslimatı sadece durum kontrolüyle engelleyebilir miyim?
Hayır. "Oku, kontrol et, teslim et" sırası eş zamanlı isteklerde yarış durumu yaratır. Kontrolü ve durum değişimini tek bir koşullu güncellemeye indirmen, yani atomik bir geçiş kurman gerekir. Ancak o zaman paralel bildirimler tek teslimatla sonuçlanır.
Webhook güvenliği tek bir satır kod değil, üst üste binen dört beş küçük disiplindir; ve bu disiplinlerin hiçbiri sonradan yapıştırılabilecek türden değildir. Uç noktanın nasıl davrandığını, bozuk imzada ne döndüğünü ve aynı bildirimi on kez gönderdiğinde sipariş ekranında ne olduğunu kendi gözünle görmek istersen canlı demo üzerinde dene; entegrasyon katmanının tamamı için özellikler bölümünü, lisanslama için ödeme sayfasını inceleyebilirsin.

