Modül dersleri (4/4)
ReDoS güvenli kalıpların yazılması
ReDoS (Normal ifade Hizmet Reddi), bir saldırı sınıfıdır. Dikkatlice hazırlanmış bir girdi, bir regex'in eşleşme zamanının patlamasına neden olur. JS motoru geri izleme kullanır: eğer bir kalıp "belirsiz" ise, şanssız giriş, üstel sayıda deneme gerçekleştirebilir.
Klasik felaket modeli
Pattern: ^(a+)+$
Input: "aaaaaaaaaaaaaaaaaaaaab"Eşleştirmek için motor, "a"nın her olası bölümünü dener.
iki + niceleyici. 20 "a"da bu 2^20 = ~1 milyon denemedir.
30 "a" ile bir milyar.
Diğer tehlikeli örnekler:
(a*)*b-- "yuvalanmış yıldızlar".(a|a)*-- örtüşen alternatifler.(\w+)+@-- dış niceleyiciye sahip açgözlü gruplar.
Tehlike nasıl fark edilir
Bu yapıları arayın:
- Bir niceleyici içindeki niceleyici:
(...+)+,(...*)*,(...{n,})+. - Bir niceleyici altında örtüşen alternatifler:
(a|ab)*,(\w|\d)+. - Karmaşık alternatiflerle ileri/geriye bakış tekrarlandı.
Savunma amaçlı yeniden yazma
Dangerous: ^(\w+\s+)+$
Safe: ^(?:\w+\s+)*\w+$Güvenli sürüm, temel durumu tekrarlanan durumdan ayırarak belirsizlik. Diğer teknikler:
- İyelik niceleyiciler (
a++) -- JS'de desteklenmez ancak diğer motorlarda mevcuttur. - Atomik kalıplar (
(?>...)) -- JS'de değil. - Eşleştirmeden önce girişin uzunluğunu sınırlayın.
- Eşleştirmede zaman aşımı (bu kursun düzenleyicisi 500 ms zaman aşımı olan bir çalışan kullanır).
ReDoS güvenli modeller için öneriler
- Alternatif olarak seçeneklerin birbirini dışladığından emin olun (örn.
(a|a+)kullanmayın). - Çakışan ifadelere iç içe niceleyiciler uygulamaktan kaçının (ör.
(\\s*)*). - Her zaman genel joker karakter noktası (
.*) yerine belirli olumsuzlanmış karakter sınıflarını ([^\\n]*) tercih edin.
Deneyin
Tekrarlanan harf kalıplarını ReDoS açısından güvenli bir şekilde tanımlayın. (a+)+ gibi iç içe geçmiş gruplar DEĞİL, tek bir karakter sınıfı kullanın.
İpucu göster
Tehlikeli (a+)+'yı basit bir a+ ile değiştirin. Sonuç aynı ama güvenli.
3 denemeden sonra çözüm mevcut
Alıştırmayı gözden geçirin
Boşluklarla ayrılmış bir kelime dizisini ReDoS açısından güvenli bir şekilde tanıyın. `(kelime+boşluk+)+` yerine `(?:kelime+boşluk+)*kelime` yapısını kullanın.
İpucu göster
Yakalama grubunu (\\w+\\s+)+ ayrık sürümle (?:\\w+\\s+)*\\w+ ile değiştirin.
3 denemeden sonra çözüm mevcut
Ek zorluk
Make the vulnerable pattern `(\w+\s*)+:` which causes ReDoS safe, by removing the overlapping whitespace recursion.
İpucu göster
Alanı grup tekrarıyla çakışmayacak şekilde taşıyın: (?:\\w+\\s+)*\\w+:
3 denemeden sonra çözüm mevcut