설명
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 필요 여부와 각 출처의 소유권도 확인해야 합니다.