과도하게 허용된 CORS 설정 (Permissive CORS)

신뢰하지 않는 출처에 브라우저 응답 읽기를 허용하는 CORS 설정을 제한하세요.

설명

CORS는 브라우저가 다른 출처의 응답을 읽을 수 있는 조건을 정합니다. 검증하지 않은 Origin 값을 Access-Control-Allow-Origin에 그대로 반영하면 신뢰하지 않는 사이트가 응답을 읽을 수 있습니다. 인증된 응답 노출에는 브라우저의 자격 증명 전송, 쿠키 정책과 서버의 credential 허용 설정 등도 영향을 줍니다. CORS 허용만으로 세션 쿠키 값이 상대 사이트에 전달되는 것은 아닙니다.

잠재적 영향

  • 신뢰하지 않는 사이트가 민감한 API 응답을 읽을 수 있습니다.
  • 인증 정보를 포함한 요청이 허용되는 조건에서는 피해자의 권한으로 반환되는 데이터가 노출될 수 있습니다.
  • CORS는 인증·인가나 CSRF 방어를 대신하지 않으므로 해당 보호도 별도로 필요합니다.

해결 방법

  1. 허용할 출처의 스킴, 호스트와 포트를 명시적인 허용 목록으로 관리하세요.
  2. HttpServletResponse.setHeader("Access-Control-Allow-Origin", userInput)처럼 검증하지 않은 입력을 그대로 반영하지 마세요. 공개 응답의 의도적인 * 허용과 민감한 응답을 구분하세요.
  3. 요청 출처에 따라 응답 헤더가 달라지고 응답을 캐시한다면 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이 허용 목록에 있으면 그대로 반환합니다. 그 밖에는 고정 출처를 반환하므로 일치하지 않는 요청 출처는 응답을 읽을 수 없습니다.

참조