과도하게 허용적인 CORS 정규식(와일드카드 및 이스케이프되지 않은 점)

Permissive CORS Regex (Wildcard with Unescaped Dot)

설명

CORS(Cross-Origin Resource Sharing)에서 허용 도메인을 지정할 때, 정규식 내에 이스케이프되지 않은 '.'(점)을 사용하면 매우 넓은 범위의 도메인을 허용할 수 있습니다. 이로 인해 의도하지 않은 출처의 JavaScript가 응답을 읽도록 허용될 수 있습니다. 민감한 응답의 노출 여부는 응답 내용과 자격 증명 전송 및 서버의 CORS 설정에 따라 달라집니다. CORS는 요청 전송 자체를 모두 막는 접근 제어 수단은 아닙니다.

잠재적 영향

  • 잘못된 정규식으로 인해 의도하지 않은 출처의 스크립트가 응답을 읽을 수 있습니다.
  • 개인 정보 및 민감 데이터 노출(정보 유출): 공격자가 악성 도메인을 통해 중요한 데이터에 접근할 수 있습니다.
  • 인증된 응답에 민감한 정보가 포함되고 자격 증명이 허용되는 경우, 악성 사이트에서 해당 정보를 읽을 수 있습니다.

해결 방법

  • 도메인 지정 정규식에서는 '.'(점)을 반드시 '\.'(역슬래시와 함께)로 이스케이프 처리하세요.
  • 특정 신뢰 도메인만 명확하게 허용하도록 CORS 정책을 설정하세요.
  • 와일드카드(*)나 과도하게 허용적인 패턴 사용을 피하세요.
  • CORS 설정을 변경할 때는 철저히 테스트하여 실제 허용되는 도메인이 의도한 범위 내에 있는지 확인하세요.

예시

변경 전

tsx
const corsDomains = [
  /(.+\.)*example.com$/,
  /^(http|https):\/\/.+\.evil\.com$/,
  /^(http|https):\/\/(.+)\.my\.site.com$/,
];

// CORS 설정 예시
app.use(cors({
  origin: corsDomains,
}));

변경 후

tsx
const corsAllowedDomains = [
  /^https?:\/\/www\.example\.com$/,   // 명확하게 'www.example.com'만 허용
  /^https?:\/\/service\.my\.site\.com$/,  // 서비스용 서브도메인만 허용
];

app.use(cors({
  origin: corsAllowedDomains,
}));

설명:

  • 변경 전: 첫 패턴은 이스케이프되지 않은 점과 시작 경계 누락 때문에 유사한 호스트를 허용할 수 있습니다. 다른 패턴의 넓은 서브도메인 범위도 별도로 검토해야 합니다.
  • 변경 후: 시작·끝 경계와 이스케이프된 점으로 두 호스트의 HTTP 또는 HTTPS 출처만 허용합니다. 운영 환경에서는 HTTPS 필요 여부와 각 출처의 소유권도 확인해야 합니다.

참조