비효율적인 정규표현식으로 인한 ReDoS

Regular Expression Denial of Service (ReDoS)

설명

정규표현식에 중첩된 반복(예: (.+)+, (.*)+, (r+){m,})이나 모호한 분기가 있으면 매칭 과정에서 'catastrophic backtracking'이 발생하여 입력 길이에 대해 지수적 시간 복잡도가 나타날 수 있습니다. 공격자는 매우 긴 문자열이나 특정 패턴(예: 'aaaaaaaaaX')을 요청 파라미터로 보내 서버의 CPU를 과점유하게 만들어 응답이 지연되거나 중단되도록 악용합니다. 이벤트 루프 기반 런타임(Node.js 등)에서는 단일 요청만으로도 전체 서비스에 영향을 줄 수 있습니다.

잠재적 영향

  • 서비스 거부(DoS): 정규식 매칭이 장시간 걸려 요청 처리가 지연·중단됩니다.

  • CPU/메모리 자원 고갈: 백트래킹으로 과도한 연산과 스택 사용이 발생합니다.

  • 응답 지연 및 타임아웃: API 응답 속도가 급격히 느려지고 타임아웃이 증가합니다.

  • 가용성/확장성 저하: 소수의 악성 요청만으로도 전체 인스턴스의 처리 능력이 떨어집니다.

해결 방법

  • 중첩 반복 제거: (.+)+, (.*)+, (a+){2,} 같은 패턴을 비모호한 형태로 재작성합니다. 예) /^(__|.)+$/ → /^(__|[^])+_$/.

  • 고정/제한된 반복 사용: 가급적 고정 길이 또는 상한을 둔 {0,64} 등으로 작성합니다.

  • 입력 길이 제한: 정규식 매칭 전에 입력 최대 길이를 제한(예: 256자)하고 초과 시 즉시 차단합니다.

  • 안전한 엔진 사용: 가능한 경우 RE2 기반 라이브러리(re2 등)처럼 선형 시간 매칭을 보장하는 엔진을 사용합니다.

  • 리뷰/정적분석: 정규식 린터(safe-regex 류), SAST 규칙을 통해 위험 패턴을 사전에 차단합니다.

  • 방어적 타임아웃: 서버 레벨에서 요청/핸들러 타임아웃을 설정해 장시간 점유를 방지합니다.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: ^([a-z]+)+$ 는 그룹 내부에 +, 외부에도 +가 있어 모호한 경로가 다수 생성됩니다. 긴 유사 패턴 입력(예: 'aaaa...X')에 대해 백트래킹이 폭발적으로 증가해 CPU를 장시간 점유하고, Node.js 이벤트 루프가 блок되어 서비스 거부(DoS)가 유발됩니다. 또한 입력 길이 제한이 없어 위험이 더 커집니다.

  • 안전한 코드: 정규식을 비모호하게 재작성(중첩 반복 제거)하고, 명시적 길이 상한을 둬 선형 시간에 가까운 매칭을 보장합니다. 필요 시 RE2 같은 선형 시간 엔진을 사용해 백트래킹 기반 취약점을 구조적으로 제거합니다. 이로써 공격자가 만든 특수 입력으로도 CPU 과점유와 서비스 지연을 유발하기 어렵습니다.

참조

Last updated