Regex Injection

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