Regular expression Denial of Service - ReDoS

Denial of Service da espressione regolare - ReDoS

Supporta HackTricks

Denial of Service da espressione regolare (ReDoS)

Un Denial of Service da espressione regolare (ReDoS) si verifica quando qualcuno sfrutta le debolezze nel modo in cui funzionano le espressioni regolari (un modo per cercare e abbinare modelli nel testo). A volte, quando vengono utilizzate le espressioni regolari, possono diventare molto lente, specialmente se il pezzo di testo con cui stanno lavorando diventa più grande. Questa lentezza può diventare così grave che cresce molto rapidamente anche con piccoli aumenti nella dimensione del testo. Gli attaccanti possono utilizzare questo problema per far smettere di funzionare correttamente un programma che utilizza espressioni regolari per un lungo periodo di tempo.

L'algoritmo Naïve problematico delle regex

Controlla i dettagli in https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS

Regex malvagie

Un modello di espressione regolare malvagio è quello che può bloccarsi su input creati causando un DoS. I modelli di regex malvagi contengono tipicamente raggruppamenti con ripetizione e ripetizione o alternanza con sovrapposizioni all'interno del gruppo ripetuto. Alcuni esempi di modelli malvagi includono:

  • (a+)+

  • ([a-zA-Z]+)*

  • (a|aa)+

  • (a|a?)+

  • (.*a){x} per x > 10

Tutti questi sono vulnerabili all'input aaaaaaaaaaaaaaaaaaaaaaaa!.

Payload ReDoS

Esfiltrazione di stringhe tramite ReDoS

In un CTF (o bug bounty) potresti controllare la regex con cui viene abbinata un'informazione sensibile (il flag). Quindi, potrebbe essere utile far congelare la pagina (timeout o tempo di elaborazione più lungo) se la regex ha corrisposto e non se non lo ha fatto. In questo modo sarai in grado di esfiltrare la stringa carattere per carattere:

  • In questo post puoi trovare questa regola ReDoS: ^(?=<flag>)((.*)*)*salt$

  • Esempio: ^(?=HTB{sOmE_fl§N§)((.*)*)*salt$

  • In questo writeup puoi trovare questo: <flag>(((((((.*)*)*)*)*)*)*)!

  • In questo writeup ha usato: ^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$

Controllo dell'input e regex ReDoS

I seguenti sono esempi di ReDoS in cui controlli sia l'input che la regex:

function check_time_regexp(regexp, text){
var t0 = new Date().getTime();;
new RegExp(regexp).test(text);
var t1 = new Date().getTime();;
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
}

// This payloads work because the input has several "a"s
[
//  "((a+)+)+$",  //Eternal,
//  "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$",   //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
].forEach(regexp => check_time_regexp(regexp, "aaaaaaaaaaaaaaaaaaaaaaaaaa!"))

/*
Regexp (a|a?)+$ took 5076 milliseconds.
Regexp (\w*)+$ took 3198 milliseconds.
Regexp (a*)+$ took 3281 milliseconds.
Regexp (.*a){100}$ took 1436 milliseconds.
Regexp ([a-zA-Z]+)*$ took 773 milliseconds.
Regexp (a+)*$ took 723 milliseconds.
*/

Strumenti

Riferimenti

Supporta HackTricks

Last updated