Kötü Regexes Neden Bir Sorun?
Çünkü bilgisayarlar, kastettiğiniz şey olmasa veya tamamen mantıksız olsa bile, onlara ne söylediğinizi tam olarak yaparlar. Bir Regex motorundan, belirli bir girdi için, belirli bir model için bir eşleşme olduğunu veya olmadığını kanıtlamasını isterseniz, motor, kaç farklı kombinasyonun test edilmesi gerektiğine bakılmaksızın bunu yapmaya çalışacaktır.
İşte OP'nin gönderisindeki ilk örnekten ilham alan basit bir model:
^((ab)*)+$
Giriş göz önüne alındığında:
ababababababababababab
Normal ifade motoru benzer (abababababababababababab)bir şeyi dener ve ilk denemede bir eşleşme bulunur.
Ama sonra maymun anahtarını içeri atıyoruz:
ababababababababababab a
İlk önce motor deneyecek (abababababababababababab)ama bu ekstra yüzünden başarısız oluyor a. Bu, felaketle sonuçlanan brack izlemeye neden olur, çünkü bizim modelimiz, (ab)*iyi niyet göstergesi olarak, yakalamalarından birini serbest bırakacak ("geri dönecektir") ve dış modelin tekrar denemesine izin verecektir. Normal ifade motorumuz için bu şuna benzer:
(abababababababababababab)- Hayır
(ababababababababababab)(ab)- Hayır
(abababababababababab)(abab)- Hayır
(abababababababababab)(ab)(ab)- Hayır
(ababababababababab)(ababab)- Hayır
(ababababababababab)(abab)(ab)- Hayır
(ababababababababab)(ab)(abab)- Hayır
(ababababababababab)(ab)(ab)(ab)- Hayır
(abababababababab)(abababab)- Hayır
(abababababababab)(ababab)(ab)- Hayır
(abababababababab)(abab)(abab)- Hayır
(abababababababab)(abab)(ab)(ab)- Hayır
(abababababababab)(ab)(ababab)- Hayır
(abababababababab)(ab)(abab)(ab)- Hayır
(abababababababab)(ab)(ab)(abab)- Hayır
(abababababababab)(ab)(ab)(ab)(ab)- Hayır
(ababababababab)(ababababab)- Hayır
(ababababababab)(abababab)(ab)- Hayır
(ababababababab)(ababab)(abab)- Hayır
(ababababababab)(ababab)(ab)(ab)- Hayır
(ababababababab)(abab)(abab)(ab)- Hayır
(ababababababab)(abab)(ab)(abab)- Hayır
(ababababababab)(abab)(ab)(ab)(ab)- Hayır
(ababababababab)(ab)(abababab)- Hayır
(ababababababab)(ab)(ababab)(ab)- Hayır
(ababababababab)(ab)(abab)(abab)- Hayır
(ababababababab)(ab)(abab)(ab)(ab)- Hayır
(ababababababab)(ab)(ab)(ababab)- Hayır
(ababababababab)(ab)(ab)(abab)(ab)- Hayır
(ababababababab)(ab)(ab)(ab)(abab)- Hayır
(ababababababab)(ab)(ab)(ab)(ab)(ab)- Hayır
...
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abababab) - Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ababab)(ab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(abab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(ab)(ab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ababab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(ab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)- Hayır
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)- Hayır
Olası kombinasyonların sayısı, girdinin uzunluğuna göre üssel olarak ölçeklenir ve siz farkına varmadan, normal ifade motoru bu şeyi çözmeye çalışan tüm sistem kaynaklarınızı tüketiyor, tüm olası terim kombinasyonlarını tüketene kadar, sonunda pes ediyor ve "Eşleşme yok" şeklinde raporlar. Bu arada sunucunuz yanan bir erimiş metal yığınına dönüştü.
Kötü Regexes Nasıl Tespit Edilir
Aslında çok zor. Ne olduklarını ve genellikle onlardan nasıl kaçınılacağını bilmeme rağmen kendim bir çift yazdım. Regex'in şaşırtıcı derecede uzun sürdüğünü görün . Bir atomik grupta yapabileceğiniz her şeyi sarmak , geri izleme sorununu önlemeye yardımcı olabilir. Temel olarak, normal ifade motoruna belirli bir ifadeyi tekrar ziyaret etmemesini söyler - "ilk denemede eşleştiğini kilitle". Bununla birlikte, atomik ifadelerin ifade içinde geri dönüşü engellemediğini , bu ^(?>((ab)*)+)$nedenle yine de tehlikeli olduğunu, ancak ^(?>(ab)*)+$güvenli olduğunu unutmayın (eşleşecek (abababababababababababab)ve ardından eşleşen karakterlerinden herhangi birini bırakmayı reddedecek, böylece felaket geri dönüşü önleyecektir).
Ne yazık ki, bir kez yazıldıktan sonra, normal ifadelerde hemen veya hızlı bir şekilde sorun bulmak aslında çok zordur. Sonunda, kötü bir normal ifadeyi tanımak, diğer herhangi bir kötü kodu tanımak gibidir - çok fazla zaman ve deneyim ve / veya tek bir felaket olayı gerektirir.
İlginç bir şekilde, bu cevap ilk kez yazıldığından beri, Austin'deki Texas Üniversitesi'ndeki bir ekip, bu "kötü" kalıpları bulmak için açık bir amaçla Normal İfadelerin statik analizini gerçekleştirebilen bir aracın geliştirilmesini açıklayan bir makale yayınladı. Araç, Java programlarını analiz etmek için geliştirildi, ancak önümüzdeki yıllarda, özellikle ReDoS saldırılarının oranı artmaya devam ettikçe , JavaScript ve diğer dillerdeki sorunlu kalıpları analiz etme ve tespit etme etrafında geliştirilen daha fazla araç göreceğimizden şüpheleniyorum .
Normal İfadeler
Valentin Wüstholz, Oswaldo Olivo, Marijn JH Heule ve Isil Dillig
The University of Texas at Austin kullanan Programlarda DoS Güvenlik Açıklarının Statik Tespiti