Güvenlik araştırması sırasında bir uygulamanın proxy ve file parsing API’lerinde SSRF (Server-Side Request Forgery) zafiyeti buldum. Zafiyet DNS rebinding ile bypass edilebiliyordu. Bunu simstudioai/sim projesine bildirdim; ekip hızlıca düzeltti ve zafiyet CVE-2025-69660 olarak kayda geçti. Bu yazıda zafiyetin nasıl işlediğini, DNS rebinding saldırısını ve uygulanan çözümü anlatıyorum.

SSRF nedir?

SSRF, saldırganın sunucuyu kendi iç ağına veya localhost’a istek atmaya zorladığı bir zafiyet. Genelde uygulama kullanıcıdan gelen URL’yi doğrudan fetch ettiğinde ortaya çıkıyor.

SSRF tehlikeli çünkü:

  • Sunucunun iç ağına erişim
  • Localhost servislerine erişim
  • Cloud metadata API’lerine erişim (AWS, GCP, Azure)
  • İç servislerde authentication bypass

DNS rebinding nedir?

DNS rebinding, saldırganın kendi kontrol ettiği bir domain’in DNS kayıtlarını değiştirip aynı domain’in farklı IP’lere çözülmesini sağladığı bir teknik. Özellikle TOCTOU (Time-of-check-to-time-of-use) zafiyetlerinde işe yarıyor.

Nasıl işliyor?

  1. Saldırgan, kontrol ettiği bir domain’i (örneğin evil.com) başlangıçta public bir IP’ye (örneğin 93.184.216.34) yönlendirir
  2. Uygulama URL’yi validate eder ve public IP olduğu için geçerli kabul eder
  3. DNS TTL (Time To Live) süresi dolduğunda, saldırgan domain’i private bir IP’ye (örneğin 192.168.1.1) yönlendirir
  4. Uygulama fetch yaparken domain artık private IP’ye çözülüyor; SSRF gerçekleşiyor

Zafiyeti nasıl buldum?

simstudioai/sim projesinde /api/proxy ve /api/files/parse endpoint’lerinde SSRF vardı. URL validate ediliyordu ama DNS rebinding’e karşı koruma yoktu.

Eski mantık:

  1. URL validate ediliyordu (protocol, format kontrolü)
  2. Hostname’in private IP’ye çözümlenip çözümlenmediği kontrol ediliyordu
  3. Eğer geçerliyse, URL fetch ediliyordu

Sorun: Validation ile fetch arasında zaman var; bu arada DNS değişebiliyor.

DNS rebinding ile bypass

Bypass için yaptığım adımlar:

  1. evil.com domain’ini başlangıçta public bir IP’ye yönlendirdim
  2. Uygulama validation yaparken, domain public IP’ye çözümlendiği için geçerli kabul edildi
  3. DNS TTL süresi dolduğunda, domain’i 192.168.1.1 gibi bir private IP’ye yönlendirdim
  4. Uygulama fetch ederken domain artık private IP’ye çözüldü; SSRF başarılı oldu

Cloud ortamında tehlikeli çünkü AWS metadata API’si (169.254.169.254), iç servisler ve localhost’a erişim mümkün.

Çözüm: DNS pinning

Ekip zafiyeti DNS pinning ile kapattı. Hostname bir kez çözülüyor, dönen IP sabitleniyor; fetch hep bu IP ile yapılıyor.

Yapılanlar:

  1. validateUrlWithDNS() fonksiyonu eklendi
  2. Bu fonksiyon, hostname’i bir kez çözümler ve IP adresini döndürür
  3. IP adresi private/reserved IP kontrolünden geçer
  4. createPinnedUrl() helper fonksiyonu, hostname’i resolved IP ile değiştirir
  5. Fetch pinned IP ile yapılıyor; Host header’da orijinal hostname kullanılıyor

Sonuç: DNS rebinding engelleniyor, TOCTOU kapanıyor, private/reserved IP’ler (IPv4/IPv6 loopback, private aralıklar, link-local, carrier-grade NAT) bloklanıyor.

Bloklanan aralıklar:

  • IPv4 loopback: 127.0.0.0/8
  • IPv4 private ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • Link-local: 169.254.0.0/16
  • Carrier-grade NAT: 100.64.0.0/10
  • IPv6 loopback ve private ranges

Özet

SSRF, özellikle DNS rebinding ile birleşince ciddi risk. Bu zafiyeti kapatmak uygulamanın güvenliğini artırdı.

Çıkarımlar:

  • URL validate ederken DNS rebinding’i hesaba kat
  • TOCTOU’dan kaçınmak için DNS pinning kullan
  • Private ve reserved IP’leri kapsamlı blokla
  • Edge case’leri test et

Benzer zafiyet bulursan sorumlu açıklama (responsible disclosure) ile geliştirici ekibine ilet.

İlgili içerik:

Kaynaklar: