설명
CORS는 브라우저가 다른 출처의 응답을 읽을 수 있는 조건을 정합니다. 검증하지 않은 Origin 값을 Access-Control-Allow-Origin에 그대로 반영하면 신뢰하지 않는 사이트가 응답을 읽을 수 있습니다. 인증된 응답 노출에는 브라우저의 자격 증명 전송, 쿠키 정책과 서버의 credential 허용 설정 등도 영향을 줍니다. CORS 허용만으로 세션 쿠키 값이 상대 사이트에 전달되는 것은 아닙니다.
잠재적 영향
- 신뢰하지 않는 사이트가 민감한 API 응답을 읽을 수 있습니다.
- 인증 정보를 포함한 요청이 허용되는 조건에서는 피해자의 권한으로 반환되는 데이터가 노출될 수 있습니다.
- CORS는 인증·인가나 CSRF 방어를 대신하지 않으므로 해당 보호도 별도로 필요합니다.
해결 방법
- 허용할 출처의 스킴, 호스트와 포트를 명시적인 허용 목록으로 관리하세요.
HttpServletResponse.setHeader("Access-Control-Allow-Origin", userInput)처럼 검증하지 않은 입력을 그대로 반영하지 마세요. 공개 응답의 의도적인*허용과 민감한 응답을 구분하세요.- 요청 출처에 따라 응답 헤더가 달라지고 응답을 캐시한다면
Vary: Origin도 설정하세요. credential은 필요한 출처에만 허용하고 인증·권한 검사와 CSRF 방어를 유지하세요.
예시
허용 출처는 실제 서비스에 맞게 바꾸세요. 아래는 응답 헤더 설정의 일부이며, preflight와 credential 정책은 애플리케이션에서 별도로 구성합니다.
변경 전
java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class InsecureCORS {
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
String origin = request.getHeader("Origin"); // 사용자 입력 기반 설정
response.setHeader("Access-Control-Allow-Origin", origin); // 위험한 코드
}
}
변경 후
java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
public class SecureCORS {
private static final Set<String> ALLOWED_ORIGINS = Set.of(
"https://example.com",
"https://sub1.example.com",
"https://sub2.example.com"
);
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
String origin = request.getHeader("Origin");
if (origin != null && ALLOWED_ORIGINS.contains(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
} else {
response.setHeader("Access-Control-Allow-Origin", "https://example.com"); // 기본 허용 도메인
}
}
}
설명:
- 변경 전:
- 사용자 입력값을 직접
Access-Control-Allow-Origin에 설정하여 공격자가 악의적인 도메인을 설정할 수 있음.
- 사용자 입력값을 직접
- 변경 후:
- 요청
Origin이 허용 목록에 있으면 그대로 반환합니다. 그 밖에는 고정 출처를 반환하므로 일치하지 않는 요청 출처는 응답을 읽을 수 없습니다.
- 요청