대소문자 구분 정규식 미들웨어 경로 사용

Improper Handling of Case Sensitivity

설명

Express에서 middleware 경로를 RegExp로 정의하면 기본이 대소문자 구분(case-sensitive)입니다. 인증/인가 같은 보안 middleware를 정규식 경로로 적용하면서 'i' 플래그를 빼면, 동일한 endpoint를 대문자/소문자만 바꿔 호출해 middleware를 우회할 수 있습니다. 예를 들어 /admin 으로 보호했지만 /Admin, /AdMiN 등은 매칭되지 않아 보호가 빠집니다.

잠재적 영향

  • 인증/인가 우회: 관리 페이지나 보호된 API에 경로의 대소문자만 바꿔 접근할 수 있습니다.

  • 로깅/감사 누락: 로깅/모니터링 middleware가 일부 케이스에서 실행되지 않아 추적이 어려워집니다.

  • 보안 정책 불일치: Rate limit, CSRF 보호, 보안 헤더(CSP/HSTS 등) 적용 middleware를 건너뛰어 취약한 응답이 노출될 수 있습니다.

  • 접근 제어 오해: 운영자가 동일한 경로라고 생각하지만, 실제로는 서로 다른 경로로 취급되어 규칙이 분리·무력화됩니다.

해결 방법

  • RegExp 경로에는 항상 대소문자 비민감 플래그 'i'를 사용하세요. 예: /^/admin(?:/|$)/i 또는 new RegExp('^/admin(?:/|$)','i').

  • 가능하면 문자열 경로를 사용하여 Express의 기본 대소문자 비민감 매칭과 일관되게 유지하세요. 예: app.use('/admin', authMiddleware).

  • 프레임워크 설정을 점검하세요: app.set('case sensitive routing', false)가 기본이며, 팀 내에서 정규식/문자열 경로 혼용 시 동작 차이를 문서화하고 점검합니다.

  • 보안 middleware는 가능한 전역 적용 후 세부 경로를 제한적으로 열어주는 방식(allowlist)으로 구성하세요.

  • 경로 케이스 변형에 대한 테스트(예: /admin, /Admin, /AdMiN)를 추가하여 우회가 없는지 검증하세요.

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

취약한 코드

안전한 코드

설명:

  • 취약한 코드: RegExp 경로에 'i' 플래그가 없어 대소문자를 구분합니다. 따라서 '/admin/...' 는 보호되지만, '/Admin/...' 같은 케이스는 매칭되지 않아 인증/인가 middleware가 실행되지 않습니다. Express의 문자열 경로와 달리 RegExp는 기본이 case-sensitive라는 차이로 인해 우회가 발생합니다.

  • 안전한 코드: 문자열 경로를 사용해 Express의 기본 대소문자 비민감 매칭을 활용하거나, 정규식 사용 시 'i' 플래그를 추가해 대소문자에 상관없이 동일하게 매칭되도록 했습니다. 이렇게 하면 경로의 케이스 변형으로 보안 middleware를 우회할 수 없습니다.

참조

Last updated