Mam świadomość odmowy wyrażenia regularnego usługi (ReDoS). Czy jest jakiś rozsądny sposób, aby pozwolić użytkownikom na tworzenie niestandardowych wyrażeń regularnych, gwarantując jednocześnie, że nie przesyłają oni wykładniczo wolnego wzoru?
Mam świadomość odmowy wyrażenia regularnego usługi (ReDoS). Czy jest jakiś rozsądny sposób, aby pozwolić użytkownikom na tworzenie niestandardowych wyrażeń regularnych, gwarantując jednocześnie, że nie przesyłają oni wykładniczo wolnego wzoru?
Odpowiedzi:
Problemem z wyrażeniami regularnymi nie jest sam regex, ale silnik regex, który ma wszystkie „wygodne” funkcje, takie jak cofanie. Dlatego unika się używania silnika regex bez tych funkcji.
Wyrażenia regularne koncepcję informatyki można zawsze dopasować w czasie liniowym po skompilowaniu ich do skończonej maszyny stanów. Tak więc silnik Regex oparty na maszynie stanów nie może być używany do ReDoS. Jednak niezbędne maszyny stanów mogą stać się dość duże w przykładach patologicznych. Ale ograniczenie dostępnej pamięci jest zwykle łatwiejsze niż ograniczenie dostępnego czasu obliczeń.
Silnik RE2 został opracowany specjalnie z myślą o niezaufanych wyrażeniach regularnych i został zaprojektowany do wykonywania w czasie liniowym.
Inną alternatywą jest samodzielne składanie wyrażeń regularnych na podstawie uproszczonej notacji. Na przykład możesz zezwolić użytkownikom na stosowanie wzorców globalnych (takich jak *.txt
). Następnie można to przeanalizować w sposób, który zapobiega cofaniu się, np. Poprzez wyłączenie zagnieżdżania i stosowanie tylko chciwych kwantyfikatorów. W wielu przypadkach użycia uproszczona notacja wzoru jest całkowicie wystarczająca.
Analiza wyrażenia regularnego w celu sprawdzenia, czy będzie on powolny, czy też nie, bez przeprowadzania samego spowolnienia , sprowadza się do rozwiązania problemu zatrzymania. Innymi słowy, nie jest możliwe znalezienie poprawnego i kompletnego rozwiązania.
Można, oczywiście, znaleźć rozwiązanie, które jest poprawne i w kompletne. Na przykład możesz pracować z restrykcyjną białą listą funkcji, które są bezpieczne w użyciu (np. Klasy postaci tak, powtórzenie nie ...). Pozwoliłoby to przekazać wiele bezkrytycznych wyrażeń regularnych, odrzucić wszystkie krytyczne i (niesłusznie) odrzucić te, które są w porządku, ale są zbyt skomplikowane, aby automatycznie były bezpieczne.
Jako autor parsera dla projektu Lazarus powiedziałbym, że nie ma sposobu, aby zrozumieć dane wyrażenie regularne, jakie zasoby zużyje na dany tekst.
Mam na myśli to, że nie wydałem tych samych zasobów (przynajmniej w sensie big-O).
Więc najlepsze podejście - uruchom ponownie parser w osobnym wątku i zabij go po upływie limitu czasu.
Oprócz innych odpowiedzi rozwiązaniem może być również rzutowanie własnej biblioteki wyrażeń regularnych, która umożliwia instrumentowanie wydajności podczas wykonywania, a tym samym zapewnia środki do zabicia wykonania w połowie, jeśli zostaną spełnione pewne kryteria.
Podobnie możesz uruchomić wyrażenia regularne w innym wątku i zabić wątki, jeśli będą one trwały zbyt długo.