Aikido

ReDoS saldırılarını önlemek için neden yavaş düzenli ifadelerden kaçınmalısınız?

Okunabilirlik

Kural
Muhafız karşı yavaş düzenli ifadeler.
Düzenli ifadeler iç içe iç içe miktar belirleyicileri veya 
belirsiz desenler olabilir neden olabilir felaket 
geri izleme ve performans sorunlarına yol açabilir.
Desteklenen diller: 45+

Giriş

Düzenli ifadeler, uygun bir girdi ile uygulamanızı saniyelerce veya dakikalarca dondurabilir. Felaket düzeyinde geri izleme, düzenli ifade motorlarının bir deseni eşleştirmeye çalışırken katlanarak artan yolları taraması durumunda ortaya çıkar. Şu gibi bir düzenli ifade: (a+)+b Geçerli bir girdiyi eşleştirmek mikrosaniyeler sürer, ancak sonuna b harfi eklenmemiş a harflerinden oluşan bir dizgiyi reddetmek saatler sürebilir. Saldırganlar, bu durumu Düzenli İfade Hizmet Reddi (ReDoS) saldırıları yoluyla istismar eder; istek zaman aşımına uğrayana veya işlem çökene kadar düzenli ifade motorunuzun CPU’yu %100 oranında tüketmesine neden olacak şekilde özel olarak hazırlanmış girdiler gönderirler.

Neden önemli?

Güvenlik etkileri (ReDoS saldırıları): Bir saldırgan, özel olarak hazırlanmış girdi içeren tek bir istekle uygulamanızı felç edebilir. E-posta doğrulama ve URL ayrıştırma kalıpları sıkça hedef alınan alanlardır. Bant genişliği gerektiren geleneksel DoS saldırılarının aksine, ReDoS saldırıları yalnızca çok küçük yükler gerektirir.

Performans düşüşü: Normal kullanıcı girdileri, felaket niteliğinde bir geri izlemeyi tetikleyerek yanıt sürelerinin milisaniyelerden saniyelere çıkmasına neden olabilir. Bu durum, yalnızca belirli girdi kalıplarında ortaya çıktığı için hata ayıklaması zor olan, öngörülemez bir gecikmeye yol açar.

Üretim ortamındaki sorunlar: Güvenlik açığı bulunan bir düzenli ifade (regex), Node.js’deki olay döngüsünü engeller veya iş parçacığı havuzu kaynaklarını tüketir. İstekler birikmeye başladıkça bellek kullanımı artar ve sistem yanıt vermez hale gelir. Mikro hizmetlerde, güvenlik açığı bulunan tek bir düzenli ifade, hataları bağımlı hizmetlere zincirleme olarak yayar.

Tespit zorluğu: Kısa girdilerle yapılan testlerde sorunsuz çalışan kalıplar, daha uzun girdilerde katlanarak yavaşlar. Bu güvenlik açığı genellikle üretim ortamına geçene kadar fark edilmez ve aktif bir olay sırasında acil durum dağıtımı gerektirir.

Kod örnekleri

❌ Uygun değil:

function validateEmail(email) {
    const regex = /^([a-zA-Z0-9_\-\.]+)+@([a-zA-Z0-9_\-\.]+)+\.([a-zA-Z]{2,5})$/;
    return regex.test(email);
}

function extractURLs(text) {
    const regex = /(https?:\/\/)?([\w\-])+\.(\w+)+([\w\-\.,@?^=%&:/~\+#]*)+/g;
    return text.match(regex);
}

Neden güvenli değil: İç içe geçmiş niceleyiciler ([a-zA-Z0-9_\\-\\.]+)+ üstel geri izleme oluşturun. Şu tür bir e-posta için: aaaaaaaaaaaaaaaaaaaaaaaaa!, düzenli ifade motoru hata vermeden önce sayısız kombinasyonu dener. URL düzenli ifadesinde, sorunu daha da karmaşık hale getiren birden fazla iç içe geçmiş nicelik belirleyicisi bulunur; bu da, beklenen yapıya sahip olmayan uzun geçerli karakter dizileri gibi girdilerle bu ifadenin son derece kolay bir şekilde istismar edilmesine yol açar.

✅ Uygunluk:

function validateEmail(email) {
    const regex = /^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}$/;
    return regex.test(email);
}

function extractURLs(text) {
    const regex = /https?:\/\/[\w\-]+\.[\w\-]+(?:[\w\-\.,@?^=%&:/~\+#]*)?/g;
    return text.match(regex);
}

Neden güvenlidir: İç içe geçmiş niceleyicilerin kaldırılması, felaket niteliğindeki geri izlemeyi ortadan kaldırır. [a-zA-Z0-9_\-\.]+ gibi tek niceleyiciler doğrusal sürede çalışır. URL kalıbı, iç içe geçmiş tekrarlar yerine isteğe bağlı sonek (?:...)? içeren yakalamayan gruplar kullanır; bu da giriş uzunluğu veya içeriğinden bağımsız olarak öngörülebilir bir performans sağlar.

Sonuç

Düzenli ifadelerin performansı, sadece bir optimizasyon meselesi değil, aynı zamanda bir güvenlik sorunudur. Tüm düzenli ifade kalıplarını, iç içe geçmiş nicelik belirleyiciler, tekrar gruplarında çakışan karakter sınıfları ve belirsiz alternatifler açısından gözden geçirin. Düzenli ifade kalıplarını, patolojik girdilerle (geçerli karakterlerden oluşan uzun dizelerin ardından gelen geçersiz son ekler) test ederek, devreye almadan önce felaket niteliğinde geri izleme durumlarını tespit edin. Mümkün olduğunda, karmaşık düzenli ifadeleri, öngörülebilir performans özelliklerine sahip dize ayrıştırma işlevleriyle değiştirin.

Sık Sorulan Sorular

Sorularınız mı var?

Hangi kalıplar felaket niteliğinde geri izlemeye yol açar?

Sık karşılaşılan sorunlara, (a+)+, (a*)* veya (a+)*b gibi iç içe geçmiş nicelik belirteçleri dahildir. (a|a)* veya (a|ab)* gibi örtüşen kalıplarla alternatif kullanımlar da bunlara dahildir. (a?)+ gibi isteğe bağlı bileşenlerin bulunduğu tekrarlar. Düzenli ifade motorunun aynı alt dizgiyi birden fazla şekilde eşleştirebileceği herhangi bir desen, üstel arama alanı yaratır. Kendileri de nicelik belirticisi olan grupların içindeki nicelik belirticilerine (+, *, {n,m}) dikkat edin.

Regex'imin ReDoS saldırısına karşı savunmasız olup olmadığını nasıl test edebilirim?

Yürütme adımlarını gösteren ve felaket niteliğindeki geri izleme konusunda uyarı veren regex101.com gibi çevrimiçi araçları kullanın. Geçerli karakterlerden oluşan uzun dizelerin ardından geri izlemeyi zorlayan karakterlerin geldiği test girdileri oluşturun. /^(a+)+b$/ desenini "aaaaaaaaaaaaaaa!" (30'dan fazla "a", "b" yok) ile test edin. Yürütme süresi milisaniyeden fazla sürerse, düzenli ifade güvenlik açığına sahiptir. Kapsamlı bir savunma stratejisi olarak, üretim ortamındaki düzenli ifade işlemlerinde zaman aşımı sınırları uygulayın.

Katastrofik geri izleme ile doğrusal geri izleme arasındaki fark nedir?

Doğrusal geri izleme, düzenli ifade alternatifleri sırayla denediğinde ancak önceki seçimleri yeniden değerlendirmediğinde ortaya çıkar. İş yükü, girdi boyutuyla doğrusal olarak artar. Felaket düzeyinde geri izleme ise, iç içe geçmiş nicelik belirteçlerinin motoru katlanarak artan sayıda kombinasyonu denemeye zorlaması durumunda meydana gelir. n uzunluğundaki bir girdi için yürütme süresi O(2^n) veya daha kötü olabilir. Makul girdi boyutları için aradaki fark milisaniye ile dakika arasındadır.

İleriye ve geriye bakışları güvenli bir şekilde kullanabilir miyim?

Lookaheads (?=...) and lookbehinds (?<=...) themselves don't cause catastrophic backtracking, but they can hide vulnerable patterns. A lookahead containing (a+)+ is still vulnerable. Use lookarounds for their intended purpose (assertions without consuming characters), not as a workaround for complex matching. Keep the patterns inside lookarounds simple and test them thoroughly.

Felaket niteliğindeki geri izlemeyi önleyen düzenli ifade motorları var mı?

RE2 (Google tarafından kullanılır), geri izlemeyi tamamen engelleyerek doğrusal zamanlı yürütmeyi garanti eder. Tüm özellikleri (geri referanslar, lookarounds) desteklemez, ancak ReDoS’u tamamen önler. Kritik güvenlik kontrolleri için RE2 bağlayıcılarını veya benzer motorları kullanmayı düşünün. JavaScript için yerleşik bir alternatif bulunmadığından, desen tasarımı ve zaman aşımları başlıca savunma yöntemlerinizdir.

Tüm düzenli ifade işlemlerine zaman aşımı süresi eklemeli miyim?

Güvenilmeyen girdiler için (kullanıcı tarafından sağlanan veriler, harici API yanıtları), evet. Beklenen karmaşıklığa bağlı olarak 100-500 ms gibi makul zaman aşımı süreleri belirleyin. Node.js’te regex.test() işlevi için doğrudan zaman aşımı ayarlayamazsınız, ancak önce girdi uzunluğunu doğrulayabilir veya zaman aşımı ayarlanmış bir işçi iş parçacığında düzenli ifadeyi çalıştırabilirsiniz. Düzenli ifade eşleştirmesini denemeden önce, makul uzunluk sınırlarını aşan girdileri reddedin.

Mevcut ve güvenlik açığı bulunan bir düzenli ifade desenini nasıl düzeltebilirim?

Öncelikle, düzenli ifadeye gerçekten ihtiyacınız olup olmadığını belirleyin. Birçok doğrulama görevi, includes(), startsWith() veya split() gibi dize yöntemleriyle daha basit bir şekilde gerçekleştirilebilir. Düzenli ifade gerekliyse, deseni düzleştirerek iç içe geçmiş nicelik belirteçlerini ortadan kaldırın. (a+)+ ifadesini a+ ile değiştirin. Düzenli ifade motorunuz destekliyorsa, atomik gruplar veya sahiplik nicelik belirteçleri kullanın. Karmaşık desenler için, girişi daha basit düzenli ifade veya dize işlemleriyle birden fazla aşamada ayrıştırmayı düşünün.

Şimdi güvenliğinizi sağlayın

Kodunuzu, bulutunuzu ve çalışma zamanınızı tek bir merkezi sistemde güvenceye alın.
Güvenlik açıklarını otomatik olarak hızla bulun ve düzeltin.

Kredi kartı gerekmez | Tarama sonuçları 32 saniyede.