ReDoS - ReDoS

The regulární výraz odepření služby (ReDoS)[1]je útok algoritmické složitosti který produkuje a odmítnutí služby poskytnutím a regulární výraz vyhodnocení trvá velmi dlouho. Útok využívá skutečnosti, že většina implementace regulárních výrazů mít exponenciální čas nejhorší případ složitost: čas může vzrůst exponenciálně ve vztahu k velikosti vstupu. Útočník tak může způsobit, že program stráví neomezené množství času zpracováním takového regulárního výrazu, buď zpomalí, nebo přestane reagovat.[2][3]

Popis

Regulární výraz ("regex") shodu lze provést vytvořením a konečný stavový automat. Regex lze snadno převést na nedeterministické automaty (NFA), ve kterých pro každý stav a vstupní symbol může existovat několik možných dalších stavů. Po sestavení automatu existuje několik možností:

  • motor jej může převést na a deterministický konečný stavový automat (DFA) a spustit vstup přes výsledek;
  • motor může vyzkoušet jeden po druhém všechny možné cesty, dokud není nalezena shoda nebo jsou všechny cesty vyzkoušeny a selžou („backtracking“).[4][5]
  • motor může uvažovat paralelně všechny možné cesty nedeterministickým automatem;
  • motor může převést nedeterministický automat na DFA líně (tj., za běhu, během zápasu).

Z výše uvedených algoritmů jsou první dva problematické. První je problematický, protože deterministický automat by mohl mít až uvádí kde je počet stavů v nedeterministickém automatu; konverze z NFA na DFA tedy může trvat exponenciální čas. Druhá je problematická, protože nedeterministický automat může mít exponenciální počet cest délky , takže procházíme zadáním délky bude také trvat exponenciální čas.[6]Poslední dva algoritmy však nevykazují patologické chování.

Všimněte si, že u nepatologických regulárních výrazů jsou problematické algoritmy obvykle rychlé a v praxi lze očekávat, že „kompilovat "regex v čase O (m) a porovnat jej v čase O (n); místo toho simulace NFA a líný výpočet DFA mají Ó (m2n) nejhorší složitost.[7] Odmítnutí služby regulárního výrazu nastane, když jsou tato očekávání aplikována na regulární výrazy poskytované uživatelem a škodlivé regulární výrazy poskytované uživatelem spustí nejhorší složitost porovnávače regulárních výrazů.

Zatímco algoritmy regulárního výrazu lze psát efektivním způsobem, většina existujících strojů regulárních výrazů rozšiřuje regexové jazyky o další konstrukty, které nelze vždy efektivně vyřešit. Takový rozšířené vzory v podstatě ve většině nutí implementaci regexu programovací jazyky použít backtracking.

Příklady

Exponenciální zpětné sledování

Nejzávažnější typ problému nastává při zpětném sledování shod regulárních výrazů, kde některé vzory mají běh, který je exponenciální v délce vstupního řetězce.[8] Pro struny znaků, runtime je . To se stane, když má regulární výraz tři vlastnosti:

  • regulární výraz aplikuje opakování (+, *) k subexpresi;
  • podvýraz může odpovídat stejnému vstupu několika způsoby, nebo podvýraz může odpovídat vstupnímu řetězci, který je předponou delší možné shody;
  • a po opakovaném subexpresi existuje výraz, který odpovídá něčemu, co subexpresi neodpovídá.

Druhá podmínka je nejlépe vysvětlena dvěma příklady:

  • v (a | a) + $, na podvýraz se použije opakování a | a, které se mohou shodovat A dvěma způsoby na každé straně střídání.
  • v (a +) * $, opakování se použije subexpresi a +, které se mohou shodovat A nebo aa, atd.

V obou těchto příkladech jsme použili $ aby odpovídal konci řetězce, splňující třetí podmínku, ale je také možné použít jiný znak. Například (a | aa) * c má stejnou problematickou strukturu.

Všechny tři z výše uvedených regulárních výrazů budou při použití na řetězce formuláře vykazovat exponenciální běhové prostředí . Například pokud se je pokusíte srovnat aaaaaaaaaaaaaaaaaaaaaaaaa! na backtrackingovém enginu výrazů bude dokončení trvat podstatně dlouho a doba běhu se přibližně zdvojnásobí pro každou extra A před !.

Je také možné mít zpětné sledování, což je polynomiální čas , místo exponenciálního. To může také způsobit problémy pro dostatečně dlouhé vstupy, i když tomuto problému byla věnována menší pozornost, protože škodlivý vstup musí být mnohem delší, aby měl významný účinek. Příkladem takového vzoru je „a * b? a * x", když je vstup libovolně dlouhou sekvencí"A„s.

Zranitelné regulární výrazy v online úložištích

V online úložištích regulárních výrazů byly nalezeny takzvané „zlé“ nebo škodlivé regexy. Všimněte si, že stačí najít zlo subvýraz za účelem útoku na celý regulární výraz:

  1. RegExLib, id = 1757 (ověření e-mailu) - viz Červené část, kterou je Evil Regex
    ^ ([a-zA-Z0-9])(([[-.] | [_] +)? ([a-zA-Z0-9] +)) *(@) {1} [a-z0-9] + [.] {1} (([az] {2,3}) | ([az] {2,3} [.] {1} [az] {2,3})) $
  2. OWASP Validace úložiště regexu, Java Classname - viz Červené část, kterou je Evil Regex
    ^(([a-z]) +.) +[A-Z] ([a-z]) + $

Tyto dva příklady jsou také citlivé na vstup aaaaaaaaaaaaaaaaaaaaaaaaa!.

Útoky

Pokud je samotný regex ovlivněn vstupem uživatele, útočník může vložit škodlivý regex a učinit systém zranitelným. Proto se ve většině případů lze odmítnutí regulárního výrazu vyhnout odstraněním možnosti, aby uživatel mohl na serveru provádět libovolné vzory. V tomto případě jsou hlavními zranitelnými aplikacemi webové aplikace a databáze. Alternativně může škodlivá stránka zavěsit webový prohlížeč uživatele nebo způsobit, že použije libovolné množství paměti.

Některé z příkladů ve výše uvedených odstavcích jsou však podstatně méně „umělé“ než ostatní; tak ukazují, jak lze použít zranitelné regexy v důsledku programovacích chyb. V tomto případě skenery e-mailů a systémy detekce narušení může být také zranitelný. Naštěstí lze ve většině případů problematické regulární výrazy přepsat jako „nezlověstné“ vzory. Například, (. * a) + lze přepsat na ([^ a] * a) +.

V případě webové aplikace může programátor použít stejný regulární výraz k ověření vstupu na straně klienta i na straně systému. Útočník by mohl zkontrolovat kód klienta, hledat zlé regulární výrazy a poslat vytvořený vstup přímo na webový server, aby jej mohl zavěsit.

Viz také

Reference

  1. ^ OWASP (2010-02-10). „Regex Denial of Service“. Citováno 2010-04-16.
  2. ^ Software RiverStar (2010-01-18). „Bulletin zabezpečení: Upozornění při používání regulárních výrazů“. Citováno 2010-04-16.
  3. ^ Ristic, Ivan (2010-03-15). Příručka ModSecurity. Londýn, Velká Británie: Feisty Duck Ltd. str. 173. ISBN  978-1-907117-02-2.
  4. ^ Crosby a Wallach, Usenix Security (2003). „Odmítnutí služby s regulárním výrazem“. Citováno 2010-01-13.
  5. ^ Bryan Sullivan, MSDN Magazine (2010-05-03). „Útoky a obrana s odmítnutím pravidelných výrazů“. Citováno 2010-05-06.
  6. ^ Kirrage, J .; Rathnayake, A .; Thielecke, H. (2013). "Statická analýza pro útoky typu odmítnutí služby s regulárním výrazem". Zabezpečení sítě a systému. Madrid, Španělsko: Springer. str. 135–148. arXiv:1301.0849. doi:10.1007/978-3-642-38631-2_11.
  7. ^ Líný výpočet DFA může obvykle dosáhnout rychlosti deterministických automatů při zachování chování v nejhorším případě podobném simulaci NFA. Je však podstatně složitější implementovat a může využívat více paměti.
  8. ^ Jim Manico a Adar Weidman (07.12.2009). „OWASP Podcast 56 (ReDoS)“. Citováno 2010-04-02.

externí odkazy