불완전한 호스트네임 정규식 (. 이스케이프 누락)

Improper Input Validation (Incomplete hostname RegExp)

설명

정규표현식에서 점(.)은 "임의의 한 글자"를 의미하는 메타문자입니다. 호스트네임(도메인)을 검증할 때 점을 이스케이프(.)하지 않으면, 의도한 도메인보다 훨씬 넓은 문자열이 매칭되어 검증을 우회할 수 있습니다. 예를 들어 example.com을 허용하려고 /^example.com$/을 사용하면 exampleXcom, example-com 등도 매칭될 수 있습니다. 공격자는 이를 악용해 오픈 리다이렉트나 SSRF 필터를 우회하여 악성 사이트로 리다이렉트하거나 내부망으로 요청을 보내도록 만들 수 있습니다.

잠재적 영향

  • 오픈 리다이렉트: 검증을 우회해 임의의 외부 사이트로 사용자를 리다이렉트할 수 있음

  • SSRF 우회: 내부망 또는 민감한 엔드포인트로 서버가 요청을 보내도록 유도 가능

  • 접근 통제 우회: 특정 도메인으로만 허용된 연계를 임의의 호스트로 확장해 정책을 무력화

  • 피싱/브랜드 훼손: 신뢰 도메인으로 가장한 유사 호스트로 연결하여 사용자 기만

해결 방법

  • 정규식에서 도메인 라벨 구분 점(.)은 반드시 이스케이프(.) 처리하세요. 예: ^((www|beta).)?example.com$

  • 시작(^)과 끝($) 앵커를 사용하여 전체 문자열을 정확히 일치시키세요.

  • 가능하면 정규식 대신 허용 목록(allow-list)으로 정확한 문자열 비교를 사용하세요. 예: host === 'example.com' 또는 host가 Set(['a.example.com', ...])에 포함되는지 확인

  • URL 파싱 시 표준 API를 사용하고 hostname(포트 제외)을 기준으로 검증하세요.

  • 서브도메인 허용이 필요하다면 경계 검사를 명확히 하세요. 예: host === 'example.com' 또는 host.endsWith('.example.com')

  • 정규식에서 모호한 패턴(.* , .?, 중첩 그룹)을 피하고 라벨 길이/문자 규칙을 명시적으로 제한하세요.

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

취약한 코드

안전한 코드

설명:

  • 취약한 코드: 정규식에서 점(.)을 이스케이프하지 않아 "."가 임의의 한 글자로 동작합니다. 따라서 '^((static|media).)?example.com$'는 실제 점 구분자가 없어도 매칭될 수 있고, 공격자가 유사 호스트네임을 만들어 검증을 우회하여 오픈 리다이렉트나 SSRF를 유발할 수 있습니다.

  • 안전한 코드: 허용 목록을 사용해 hostname을 정확히 비교하므로 유사 문자열이나 점 대체 문자로는 우회할 수 없습니다. 또한 URL을 안전한 API로 파싱하고 소문자로 정규화해 비교 일관성을 보장합니다. 정규식을 쓸 경우에도 점을 '.'로 이스케이프하고 앵커를 사용하여 정확히 의도한 도메인만 허용합니다.

참조

Last updated