2008-10-28 9 views
12

Zakładając skrypt Perla, który pozwala użytkownikom na określenie kilku wyrażeń filtru tekstowego w pliku konfiguracyjnym, czy istnieje bezpieczny sposób na umożliwienie im wprowadzania wyrażeń regularnych, bez możliwości niezamierzonych efektów ubocznych lub wykonania kodu? Bez faktycznego analizowania wyrażeń regularnych i sprawdzania ich pod kątem konstruktów problematycznych, to znaczy. Nie będzie żadnego zastąpienia, tylko dopasowanie.Czy można bezpiecznie czytać wyrażenia regularne z pliku?

Na marginesie, czy istnieje sposób sprawdzenia, czy określone wyrażenie regularne jest poprawne przed faktycznym użyciem go? Chcę wprowadzić ostrzeżenia, jeśli wprowadzono coś takiego jak /foo (bar/.

Dzięki, Z.


EDIT:
Dzięki za bardzo ciekawe odpowiedzi. Mam ponieważ okazało się, że następujące niebezpieczne konstrukcje będą oceniane tylko w regexes jeśli używana jest use re 'eval' Pragma:

(?{code}) 
(??{code}) 
${code} 
@{code} 

Domyślnie jest no re 'eval'; więc chyba że czegoś mi brakuje, powinno być bezpiecznie czytać wyrażenia regularne z pliku, a jedynym sprawdzianem jest eval/catch wysłany przez Axemana. Przynajmniej nie udało mi się ukryć niczego złego w moich testach.

Jeszcze raz dziękuję. Z.

+0

Po prostu przeczytałem, że uważam, że dobrym stylem jest nie edytowanie własnego pytania w celu udzielenia odpowiedzi, ale zamiast tego opublikuj nową odpowiedź. Przepraszam za faux-pas, wciąż jestem tutaj bardzo nowy. Ale się uczę :-) – Zilk

Odpowiedz

5

Prawdopodobnie będziesz musiał zrobić pewien poziom sanityzacji. Na przykład strona perlre człowiek opisano następującą konstrukcję:

(?{ code }) 

wykonywalny kod, który umożliwia wewnątrz dopasowania wzorca.

+1

Jesteś blisko. Ta konstrukcja nie jest dozwolona podczas wykonywania interpolacji zmiennej w wyrażeniu regularnym, chyba że użyjesz 're 'eval';', więc będzie to bezpieczne. –

11

Ten

eval { 
    qr/$re/; 
}; 
if ([email protected] ) { 
    # do something 
} 

kompiluje wyrażenia i pozwala odzyskać od błędu.

można oglądać w poszukiwaniu szkodliwego wypowiedzi, ponieważ jesteś tylko zamiar zrobić dopasowanie, szukając tych wzorów, które mogłyby umożliwić wykonanie wybranego kodu do uruchomienia:

(?: \(\?{1,2} \{ # '(' followed by '?' or '??', and then '{' 
| \@ \{ \s* \[ # a dereference of a literal array, which may be arbitrary code. 
) 

Upewnij się skompilować to z Flaga x.

+0

To nie chroni przed atakami Denial of Service. W zależności od kontekstu może to nie być problem. Jeśli użytkownik uruchamiający program mógłby równie dobrze zrobić "perl -e" podczas (1) {} "", to nie ma znaczenia. Jeśli to serwer, cóż ... – tsee

+1

Wrzuciłbym regex do alarmu(), żeby zabić wszystko, co zajmuje więcej niż sekundę lub dwie. – Schwern

13

W zależności od tego, z czym się pasujesz i od wersji Perla, mogą występować pewne wyrazy regularne, które działają jako skuteczny atak polegający na odmowie usługi, za pomocą nadmiernego wyprzedzania, lookbehindów i innych stwierdzeń.

Najlepiej, jeśli pozwalasz tylko na niewielką, dobrze znaną podgrupę wzorów regex i rozwijaj ją ostrożnie, gdy Ty i Twoi użytkownicy nauczysz się korzystać z systemu. W ten sam sposób, w jaki wiele systemów komentowania blogów dopuszcza tylko mały podzbiór znaczników HTML.

W końcu Parse :: RecDescent może się przydać, jeśli trzeba wykonać złożoną analizę wyrażeń regularnych.

5

Sugerowałbym, aby nie ufać żadnym wyrażeń regularnych od użytkowników. Jeśli jesteś naprawdę zdeterminowany, aby to zrobić, uruchom program perl w trybie taint (-T). W takim przypadku potrzebujesz jakiejś formy sprawdzania poprawności.Zamiast używać Parse :: RecDescent do napisania własnego parsera wyrażeń regularnych, jak sugeruje inna odpowiedź, należy użyć istniejącego, prawdopodobnie szybszego, parsera regexp, który został napisany przez eksperta i działa jak urok.

Wreszcie, od perl 5.10.0 można podłączyć różne silniki wyrażeń regularnych do perla (leksykalnie!). Można sprawdzić, czy dostępny jest mniej wydajny silnik wyrażeń regularnych, którego składnia jest łatwiejsza do sprawdzenia. Jeśli chcesz podążać tą trasą, przeczytaj: the API description, Avar's re::engine::Plugin lub na ogół sprawdź jedną z Avar's plugin engines.

+0

PS: YAPE :: Regex został w większości zastąpiony przez Regexp :: Parser. Żadne z nich nie obsługuje jeszcze rozszerzeń perl 5.10 do silnika regexp. Jeff Pinyan, autor obu modułów, powiedział, że planuje rozszerzyć moduły w najbliższej przyszłości. Zobacz także: PPIx :: Regexp. – tsee

0

Czy moduł Safe byłby przydatny w odniesieniu do kompilowania/wykonywania niezaufanych wyrażeń regularnych?

Powiązane problemy