Bunu yaşayan biri olarak söyleyeyim, Geçen yaz, Temmuz 2024’te İstanbul’da bir güvenlik toplantısında tam bu konuyu konuşurken biri şöyle demişti: “Regex dediğin şey basit işte.” O cümle masada iki saniye durdu. Sonra hepimiz güldük. Çünkü işin aslı şu: regex bazen kapı kilidi gibi çalışıyor — doğru anahtar gelirse açılıyor, yanlış kombinasyonda ise sistemi yavaş yavaş boğuyor, hem de öyle bir boğuyor ki küçük bir giriş metni koca bir servisi diz çöktürebiliyor. Siz hâlâ monitöre bakıp “ne oldu ya” diye düşünüyorsunuz.
Doğrusu, İşte bugün konuşacağım mesele tam bu. Python dünyasında sık kullanılan paketlerde tehlikeli regex desenleri ne kadar yaygın? Harshith Reddy Nalla’nın yaptığı çalışma bunu kurcalıyor ve açık konuşayım — çıkan tablo pek iç açıcı değil. Bu yazıyı hazırlarken 2023 sonbaharında kendi projemde yaşadığım o sinir bozucu olayı hatırladım; Ankara’daki bir müşteri panelinde tek bir log satırı yüzünden endpoint’in tepki süresi fena halde uzamıştı. Sonradan baktık… suçlu yine regex’ti. Klasik.
Şimdi gelelim işin can alıcı noktasına.
ReDoS Nedir ve Neden Bu Kadar Sessizdir?
ReDoS. Yani Regular Expression Denial of Service. Kulağa akademik geliyor ama pratikte gayet gündelik bir bela, inan bana.
Kullanıcıya açık alanda çalışan bir regex ifadeniz varsa ve bu ifade kötü tasarlanmışsa, saldırgan özel hazırlanmış bir girdiyle CPU’yu zıplatabiliyor — bunu söyleyince insanlar “e tamam fark edilir” diyor ama hayır, çoğu zaman fark edilmiyor. Mesela Cloudflare olayında tek bir kural değişikliği sonrası küresel trafikte %80 düşüş yaşanması boşuna değil; sistemler bazen en küçük görünen detaylarda patlıyor, inanılmaz ama gerçek.
Buradaki kritik nokta şu: problem sadece “regex var” olması değil. Problem, regex’in aynı karakteri farklı yollarla tüketebilmesi. Motor önünde birkaç yol görüyor… hepsini deniyor… sonra yine olmuyor… tekrar deniyor. Küçük metinde sorun çıkarmayan yapı, biraz uzun ve uymayan bir veri geldiğinde katlanarak büyüyor. Üstel. Kontrol edilemez.
Ben buna bazen bavul sıkıştırmaya benzetiyorum, nasıl desem — valizin içine kazakları rastgele doldurursanız kapak kapanır gibi olur ama fermuarı zorladığınızda içeride her şey birbirine giriyor, ne çeksenin çıkmıyor. Regex de tam öyle davranıyor bazı durumlarda; düzenli görünürken içeride tam bir karmaşa yaratabiliyor (kendi tecrübem)
ReDoS’un tehlikesi şurada yatıyor: çoğu zaman saldırı “gürültülü” olmaz. Trafik normal görünür, ama arka planda CPU kıvranır.
Asıl Sorun Nerede Başlıyor?
Bi saniye — Lafı gevelemeden teknik tarafa geçeyim. Bazı regex desenleri iç içe geçen tekrarlar içeriyor. En meşhur örnek: (a+)+. Bu ifade eşleşmeyen uzun bir metne verildiğinde motor önce “belki buradan olur” diyor, sonra başka bölünme ihtimallerini denerken süre uçup gidiyor. Küçük girişte idare eder. Biraz büyüyünce işler karışıyor. Patlıyor.
Küçük bir detay: Bunu ilk kez laboratuvar gibi kurduğum küçük bir Ubuntu VM’de test ettiğimde şaşırdım açıkçası — 10 karakterde göz kırparken biten işlem 20 karakterde neredeyse takılıp kaldı. Şaka değil. n=10 için milisaniyelerden söz ediyoruz, n=20 civarında süre dramatik biçimde şişiyor. Ve işin can sıkıcı tarafı da şu: kodunuz gayet temiz görünüyor olabilir, hatta linter’dan rahatça geçiyor. Runtime’da tokadı yersiniz.
Aşağıdaki örnek mantığı biraz daha somutlaştırıyor:
# Kötü örnek
pattern = r"(a+)+"
# Daha dikkatli yaklaşım
pattern = r"a+"
Tabii gerçek dünyada bu kadar basit çözülmüyor. E-posta doğrulama, URL ayrıştırma, log filtreleme — bunlarda desenler çok daha çetrefilli oluyor. Bir de ekipler çoğu zaman “çalışıyor mu?” sorusuna bakıp geçiyor, performans ve güvenlik kontrolü ikinci plana atılıyor. İşte hayal kırıklığı da tam burada başlıyor.
sre_parse ile Statik Tarama Nasıl Yapılıyor?
Vallahi, Neyse, gelelim güzel tarafa — bu çalışmanın bence en ilginç kısmı burası.
Araştırmacılar saldırgan girdi üretip deneme yapmıyorlar; doğrudan Python’ın regex AST’sine bakıyorlar. Python regex derlenirken içerde sre_parse modülü devreye giriyor ve desenin ağacını çıkarıyor. Motorun kafasının içine bakmak gibi düşünün, tam öyle. Eğer ağaçta MAX_REPEAT düğümünün içinde yine MAX_REPEAT taşıyan bir SUBPATTERN varsa alarm çalabiliyor — bu yaklaşımın hoş yani netliği, girdiye bağımlı değilsiniz ve milyon kere test koşmanıza gerek kalmıyor çünkü risk daha kod okunurken, derleme anına yakın görülüyor (şaşırtıcı ama gerçek) Claude, mitmproxy ve Spor Uygulamasının Gizli API’si yazımızda bu konuya da değinmiştik. Daha fazla bilgi için Aşırı Gürültülü Uyarıları Susturmanın Akıllı Yolu: Pratik Rehber yazımıza bakabilirsiniz. Daha fazla bilgi için Yazılım Mühendislerinde Tükenmişlik: Sessiz İşaretler yazımıza bakabilirsiniz.
Durun, bir saniye.
Kendi deneyimimde statik analiz araçlarının hep en sevdiğim tarafı bu oldu zaten. Geçen mart ayında Kadıköy’de yaptığımız küçük bir code review oturumunda ekipten biri “önce üretimde görelim” demişti; ben tam tersini savundum (şaşırtıcı ama gerçek). Çünkü bazı hatalar üretime çıkınca değil, daha erken yakalanınca değerli oluyor. Maliyeti düşüyor, stresi düşüyor, her şey düşüyor. Yapay Zekâ Yığını: Kendi Akıllı Uygulamanı Kur yazımızda da bu konuya değinmiştik. Manticore Search’ü Grafana ile Tek Komutla İzle yazımızda da bu konuya değinmiştik.
| Kategori | Anlamı | Neden önemli? |
|---|---|---|
| Nested quantification | Tekrarın içinde tekrar var | Patlama etkisi yaratabilir |
| nulls within quantifications | Tekerleme gibi boş eşleşmeler oluşabilir | Motor sonsuz dallanmaya yaklaşabilir |
| overlapping alternatives | Aynı şeyi yapan alternatifler üst üste biner | Eşleşme denemeleri artar |
| beklenmedik kategori | Araştırmanın bulduğu ekstra risk tipi | Daha önce fark edilmeyebilir |
Peki Hangi Paketlerde Risk Var?
Tuhaf ama, Araştırma ekibi Python ekosistemindeki popüler paketleri taramış: requests, flask, django, fastapi, sqlalchemy, pydantic, pytest, numpy… liste uzayıp gidiyor. Dürüst olayım — bazı isimleri görünce insan otomatik olarak “bunlarda sorun çıkmaz herhalde” diye düşünüyor. Büyük isim, büyük güven. Ama büyük paket demek kusursuz paket demek değil. Hiç değil aslında.
Bence asıl ders şu: açık kaynakta kullanılan yardımcı fonksiyonlar bile saldırı yüzeyi oluşturabiliyor. Bir proje kendi içinde mükemmel güvenlik duvarlarına sahip olabilir. Üçüncü parti paketteki ufak bir pattern tüm resmi bozabiliyor — özellikle input validation tarafında bu çok daha kritik. Kurumsal tarafta bunu daha sert hissediyorsunuz. Etki alanı geniş; küçük startup’ta tek servis yavaşlarken enterprise ortamda beş ayrı ürün aynı anda tökezleyebiliyor.
Küçük ekiplerde neden kaçırılıyor?
Hız baskısı. Hepsi bu kadar. “Şu form çalışsın yeter” deniyor ve regex ince ayarı erteleniyor. Sonra trafik biraz artınca gecikmeler başlıyor. Kimse ilk bakışta sebebi bulamıyor — çünkü hata stack trace bırakmıyor, sessiz ilerliyor, sinsi bir şekilde.
Büyük organizasyonlarda neden daha da kritik?
Büyük organizasyonlarda olay sadece performans meselesi değil. SLA var, müşteri güveni var, hatta bazen regülasyon baskısı var. Benim gördüğüm kadarıyla kurumsal yapılarda en pahalı şey CPU maliyeti bile olmuyor — asıl pahalı olan yanlış alarm zinciri ve incident yönetimi sırasında kaybedilen saatler oluyor (inanın bana). E peki, sonuç ne oldu? Gerçekten.
- Kullanıcıdan gelen veri doğrudan regex’e giriyorsa dikkat edin.
- Nesting yani iç içe tekrarlar özellikle risklidir. — ciddi fark yaratıyor
- Eşleşmeyen uzun girdilerle mutlaka test yapın.
- Paket güncellemelerinde security notlarını okumayı alışkanlık haline getirin.
- Mümkünse statik analiz + dinamik test ikilisini birlikte kullanın.
Bana Göre En Pratik Savunma Katmanları
Açık konuşayım: herkesin hemen kompleks araçlara koşmasına gerek yok. İlk savunma katmanı sade tasarım olmalı. Regex’i mümkün olduğunca kısa tutun, alternatifleri azaltın, gereksiz yıldızları üst üste bindirmeyin. Çoğu ekipte sorun teknik değil zaten — disiplin sorunu, biraz bakım kültürü yetiyor aslında.
Şöyle toparlayayım: eğer kullanıcı girdisi üzerinde çalışıyorsanız timeout koymak şarttır. Üstelik sadece uygulama seviyesinde değil, proxy (belki yanılıyorum ama) veya WAF tarafında da sınır koymak gayet mantıklı. Ben geçen yıl Eylül ayında İzmir’de yapılan bir hackathon’da bunu birebir gördüm; timeout olmayan bir demo sunumu yarıda kesilmişti çünkü masum görünen bir pattern yarışmayı kilitlemişti. Salonda sessizlik. Utanç. Sonra uzun bir “hata nerede” tartışması.
Neleri kontrol etmeli?
- Zaman aşımı sınırı belirleyin.
- Düzenli expression’ları kod incelemesinde ayrıca değerlendirin.
- Kritik endpoint’lerde yük testi yapın.
- Saldırı simülasyonu yerine güvenlik odaklı regresyon testleri ekleyin.
- Kullanılan paketlerin sürümlerini takip edin.
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



