π Introduction
Regex Injectionμ 곡격μκ° Regexκ° compile λκΈ° μ regex ν¨ν΄μ μν₯μ μ€ μ μλ Injection 곡격μ μλ―Έν©λλ€. Injection 곡격μΌλ‘ ν° μν₯λ ₯μ΄ λ°μνλ건 μλμ§λ§, μ΄λ₯Ό ν΅ν΄ ReDOSλ₯Ό μ½κ² λ°μμν¬ μ μμ΅λλ€.
π‘ Offensive techniques
Detect
With Sourcecode
μμ€μ½λκ° μλ€λ©΄ μ¬μ©μ μ λ ₯κ°μ΄ μ κ·ννμ λ¬Έλ²μ μν₯μ μ£Όλμ§ μ²΄ν¬νλ©΄ λ©λλ€. λνμ μΌλ‘ μ κ·ννμ λ¬Έλ²μ μΈλΆ νλΌλ―Έν°λ‘ μμ±νλ κ²½μ° μ΄μ ν΄λΉλ©λλ€.
Code
data := c.Param("user_data")
body := c.Param("user_body")
r, _ := regexp.Compile(data)
r.FindString(body)
Request
GET /target?user_data=/[a-z]/g&user_body=abcd
Without Sourcecode
μμ€μ½λκ° μλ€λ©΄ ReDOS ꡬ문과 λ¬Έμλ₯Ό ν¬ν¨μμΌ μ μ μ¨μ λμΈ ν Response, Response Time λ±μ μ΄μ©ν΄ μΆμΈ‘νλ κ²μ΄ μ΅μ μ λλ€.
Exploitation
ReDOS
Regexp ν¨ν΄μ μμ ν μ μλ κ²½μ° μλ ν¨ν΄κ³Ό κ°μ΄ ν° μ€λ²ν€λλ₯Ό λ°μμν€λ ReDOS ν¨ν΄μΌλ‘ μΌλ‘ λ³κ²½ν©λλ€.
(a+)+
([a-zA-Z]+)*
(a|aa)+
(a|a?)+
(.*a){x} for x \> 10
ReDOSμ λν μμΈν λ΄μ©μ Cullinan > ReDOSλ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ!
Other
μμ§μ ReDOS μ΄μΈμ νΉλ³ν Exploting λ°©λ²μ΄ μλ건 μλλλ€. λ€λ§ μ΄λ»κ² νμ©λ μ§λ μμ§ λͺ¨λ₯΄λ μΌμ΄κΈ° λλ¬Έμ μνμ΄μ½λ© κ΄μ μμλΌλ κ³ μΉλκ² μ’μκ±°λ μκ°μ΄ λλ€μ. μλ daily-swigμλ λΉμ·ν λ΄μ©μ κΈμ΄ μμΌλ μ°Έκ³ ν΄μ£ΌμΈμ!
- https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets
π‘ Defensive techniques
μ κ·ννμμ κ°κΈμ μ¬μ©μ μ λ ₯κ°μΌλ‘ μμ±λμ§ μλλ‘ μ£Όμν΄μΌν©λλ€. λ§μ½ μ¬μ©μ μ λ ₯κ°μΌλ‘ λΆν° μ κ·ννμ μμ±μ΄ νμνλ€λ©΄ νμ©ν μ μλ ν¨ν΄μ λ²μ λ± ReDOSλ₯Ό μνν μ μλ κ²μ¦ λ‘μ§μ΄ νμν©λλ€.
Worst-case
data := c.Param("user_data")
body := c.Param("user_body")
r, _ := regexp.Compile(data)
r.FindString(body)
Better-case
allowList := []string{
"[a-z]",
"[1-9]",
"abcd",
}
data := c.Param("user_data")
body := c.Param("user_body")
if checkAllowList(data, allowList) {
r, _ := regexp.Compile(data)
r.FindString(body)
}
π References
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets