heyday2024 님의 블로그
CORS에 대해서 본문
CORS란 무엇인가?
- CORS(Cross-Origin Resource Sharing)는 웹 브라우저에서 보안상의 이유로 도메인이 다른 서버에 요청을 보낼 때 적용되는 정책입니다. 즉, CORS는 클라이언트 웹 애플리케이션이 다른 도메인에 있는 리소스와 전하게 상호작용할 수 있도록 합니다.(특히, 서드 파티 API나 리소스를 참조하는 경우 유용합니다!!)
- 동일 출처(Same-Origin) 정책으로 인해, 기본적으로 웹 페이지가 자신과 동일한 출처(origin)에 있는 리소스만 요청할 수 있으며, 다른 출처의 리소스를 요청하려면 그 서버가 CORS 헤더를 통해 이를 허용해야 합니다.
왜 CORS가 만들어졌을까??
- 과거에 크로스 사이트 요청 위조(CSRF) 문제 발생.
- 악의적인 웹사이트가 사용자를 속여서 사용자의 권한으로 다른 사이트에 요청을 보내게 하는 공격.
- CSRF 공격은 사용자가 특정 사이트에 로그인되어 있는 상태에서 주로 발생하며, 공격자가 사용자의 세션을 도용하여 의도치 않은 요청을 전송하게 함으로써 사용자의 권한을 악용합니다.
- CSRF문제를 해결하기 위해 모든 브라우저에서 동일 오리진 정책(Same-Origin Policy) 구현.
- 클라이언트가 동일한 출처(origin)에서 제공되는 리소스에만 접근할 수 있도록 제한하는 정책
- 예를 들어, 클라이언트 URL이 https://example.com:443인 경우, 동일 출처로 인정되기 위해 요청 대상 URL 역시 https://example.com:443이어야 합니다.
- 동일 오리진 정책(Same-Origin Policy)은 매우 안전한 보안 장치이지만, 실제 사용에서는 제한적일 수 있습니다. 특히 오늘날의 웹 애플리케이션은 다른 도메인의 리소스와 상호작용하는 경우가 많기 때문에, 이 정책이 적용되면 필요한 데이터를 불러오거나 외부 서비스와 통합하는 데 어려움이 발생할 수 있습니다.
- 크로스 오리진 리소스 공유(CORS) 등장.
- 동일 오리진 정책을 확장한 메커니즘. CORS를 통해 서버는 특정 출처(origin)에 한해 자원 접근을 허용할 수 있습니다.
- CORS는 클라이언트-서버 간의 신뢰를 기반으로 필요한 자원 공유를 가능하게 하여, 복잡한 애플리케이션에서 다양한 출처와 안전하게 통합할 수 있는 환경을 제공합니다.
- 공개 API 사용: 날씨 정보, 뉴스, 환율 정보 등의 공개 API에서 데이터를 가져와 애플리케이션에 표시하는 경우, 서버는 CORS 헤더를 통해 클라이언트의 출처를 허용하여 데이터를 안전하게 공유할 수 있습니다.
- 권한 있는 서드 파티 액세스: B2B 서비스에서 파트너 애플리케이션이 특정 리소스에 접근할 수 있도록 허용하는 경우에도 CORS를 활용할 수 있습니다. 서버가 특정 파트너 출처만 허용하는 설정을 통해 제한적인 데이터 접근을 가능하게 할 수 있습니다.
CORS 작동 방식
- 요청 시 오리진 헤더 추가:
- 브라우저는 현재 오리진의 정보(프로토콜, 호스트, 포트)를 Origin 헤더에 추가하여 서버로 요청을 보냅니다. 예를 들어, https://news.example.com에서 https://partner-api.com으로 요청을 보내면 요청 헤더에 Origin: <https://news.example.com이> 포함됩니다.
- 서버에서 오리진 검토 및 응답:
- 서버는 요청에서 Origin 헤더를 확인하고, 요청한 출처가 허용된 경우 Access-Control-Allow-Origin 헤더를 포함하여 응답합니다. 예를 들어, Access-Control-Allow-Origin: <https://news.example.com이> 응답 헤더에 포함됩니다.
- 브라우저에서 응답 헤더 검토:
- 브라우저는 서버 응답의 Access-Control-Allow-Origin 헤더를 확인하여 요청한 출처가 허용된 경우에만 데이터를 클라이언트 애플리케이션과 공유합니다. 허용되지 않는 경우에는 요청이 차단되고 오류가 반환됩니다.
- 인증된 요청:
- 인증이 필요한 요청의 경우 서버는 Access-Control-Allow-Credentials: true 헤더를 포함해야 합니다. 이를 통해 브라우저는 쿠키나 인증 정보를 포함한 요청을 허용하게 됩니다. (서버에서 크로스 오리진 액세스를 허용하지 않는 경우에는 오류 메시지로 응답합니다.)
CORS 사전 요청(Preflight Request)
- 주로 클라이언트가 서버로 민감한 작업을 요청할 때 발생하며, 사전 요청을 통해 서버가 요청을 받아들일 수 있는지를 확인하여 보안을 강화합니다.
복잡한 크로스 오리진 요청 조건
- GET, POST, HEAD 외의 HTTP 메서드 사용 (예: PUT, DELETE 등)
- Accept-Language, Accept, Content-Language 외의 커스텀 헤더 포함
- multipart/form-data, application/x-www-form-urlencoded, text/plain 외의 Content-Type 헤더 사용
사전 요청의 작동 방식
- 사전 요청 전송:
- 클라이언트는 OPTIONS 메서드를 사용하여 서버에 사전 요청을 보냅니다. 이 요청에는 출처, 요청할 메서드 및 요청할 헤더 정보가 포함됩니다.
- 예시:
- OPTIONS /data HTTP/1.1 Origin: <https://example.com> Access-Control-Request-Method: DELETE
- 서버 응답:
- 서버는 요청을 허용하는 경우, 응답에 Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers 등의 CORS 관련 헤더를 포함하여 허용할 출처, 메서드, 헤더 등을 명시합니다.
- 응답 예시:
- HTTP/1.1 200 OK Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Origin: <https://news.example.com> Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS
- 결과 확인 후 실제 요청 전송:
- 브라우저는 서버의 응답을 확인하고, 요청이 허용된 경우 실제 요청(DELETE 등)을 전송합니다. 허용되지 않는 경우에는 요청이 차단됩니다.
- 사전 요청 결과 캐싱:
- 서버는 Access-Control-Max-Age 헤더를 통해 브라우저가 사전 요청 결과를 일정 시간 동안 캐시할 수 있도록 설정할 수 있습니다. 캐시가 활성화되면, 지정된 시간이 지나기 전까지 동일한 요청을 위한 추가 사전 요청이 필요하지 않습니다.
CORS와 JSONP의 차이점
- 둘 다 서로 다른 도메인 간의 데이터를 주고 받기 위해 사용되지만, 구현 방식과 보안 수준이 다릅니다.
CORS (Cross-Origin Resource Sharing)
- 원리: CORS는 서버가 명시적으로 특정 출처(origin)의 요청을 허용하도록 설정하는 방식입니다. 서버는 요청에 대한 접근을 허용할 출처를 응답 헤더에 포함해 브라우저가 이를 확인하고 요청을 허용하도록 합니다.
- 작동 방식: CORS는 브라우저가 HTTP 요청의 헤더와 메서드를 검토하고, 필요한 경우 사전 요청(OPTIONS 메서드)을 통해 서버가 요청을 허용하는지 확인하는 절차를 거칩니다.
- 보안: CORS는 출처별 접근을 세밀하게 설정할 수 있어 더 안전하며, 크로스 오리진 요청 시 자격 증명(쿠키 등)도 포함할 수 있습니다.
- 지원: CORS는 웹의 글로벌 표준으로, 현대적인 모든 브라우저가 지원합니다.
JSONP (JSON with Padding)
- 원리: JSONP는 <script> 태그를 이용해 JavaScript로 외부 데이터를 가져오는 방식입니다. 동일 오리진 정책이 HTML <script> 태그에는 적용되지 않기 때문에, JavaScript 코드를 호출하여 데이터를 가져올 수 있습니다.
- 작동 방식: 서버는 JSON 대신 JavaScript 함수를 반환하며, 클라이언트는 함수 호출로 감싸진 데이터를 받아서 처리합니다. 예를 들어 callback({data: "example"}) 형태로 JSON 데이터를 전송합니다.
- 보안: JSONP는 데이터 요청 시 출처 검증 없이 무조건 데이터를 받아들이므로 보안이 낮으며, 특히 외부 서버를 신뢰할 수 없을 때는 악성 코드가 포함될 위험이 있습니다.
- 제한 사항: JSONP는 GET 요청만을 지원하며, POST, PUT, DELETE 등 다른 HTTP 메서드 요청은 사용할 수 없습니다.
=⇒ 정리하자면, JSONP는 보안 검증이 없어서 외부 서버의 신뢰성에 의존해야하고, 이는 CORS에 비해 보안상 덜 안전합니다. 현대적인 브라우저들에 몇 가지 보안 기능이 추가되면서 JSONP이 포함된 오래된 코드는 더이상 작동되지 않습니다. 크로스 오리진 액세스 제어를 위한 최신 글로벌 웹 표준은 CORS입니다.
CORS를 안전하게 구성하려면??
- 특정 출처에 대한 접근만 허용하도록 명시적으로 허용할 도메인 목록을 정의하는 것이 좋습니다. 허용 목록을 쉼표로 구분된 개별 도메인으로 구성하여, 신뢰할 수 있는 출처에만 접근 권한을 부여해야합니다.
- *** 사용을 지양**합니다. API를 공개하려는 것이 아닌 경우 *는 모든 출처에서 접근을 허용하므로 보안 취약점이 될 수 있습니다.
- 정규식 사용에 주의해야합니다. 예를 들어 permitted-website.com 접미사를 허용하는 정규식이 있다면, 의도하지 않게 maliciouspermitted-website.com과 같은 악성 도메인이 포함될 수 있습니다.
2. null 오리진 사용 방지
- null 오리진은 파일 요청이나 로컬 환경에서 요청 시 발생할 수 있으며, 일부 브라우저는 이러한 요청의 Origin 헤더에 null 값을 설정합니다.
- CORS 허용 목록에 null을 포함하지 않는 것이 안전합니다. null 오리진을 허용하면 허가되지 않은 요청이 서버에 접근할 수 있는 보안 위험이 발생할 수 있습니다.
3. 자격 증명 포함 요청 관리
- 자격 증명(쿠키, HTTP 인증 등)을 포함하는 요청에는 Access-Control-Allow-Credentials를 true로 설정해야 하며,*를 Access-Control-Allow-Origin에 사용하지 않습니다.
- 자격 증명을 포함한 요청은 반드시 특정한 출처에만 허용되도록 설정하여 데이터 노출을 방지합니다.
4. 최소한의 허용 메서드와 헤더 설정
- Access-Control-Allow-Methods와 Access-Control-Allow-Headers 헤더를 통해 실제로 필요한 HTTP 메서드와 헤더만 허용하도록 제한합니다. 불필요한 메서드나 헤더를 허용하면 공격 범위가 넓어질 수 있습니다.
5. 사전 요청 결과 캐시
- Access-Control-Max-Age를 적절히 설정하여 사전 요청의 응답 결과를 캐싱함으로써 서버의 부하를 줄일 수 있습니다. 기본적으로 5~10분 정도로 설정하는 것이 일반적이며, 너무 길게 설정하면 보안 리스크가 커질 수 있습니다.
6. CORS 정책에 대한 지속적인 모니터링과 테스트
- 서버 구성 변경, 새로운 도메인 추가 등의 경우에는 CORS 정책이 올바르게 적용되는지 주기적으로 모니터링합니다. 자동화된 보안 테스트나 검증 도구를 활용해 CORS 설정이 의도한 대로 작동하는지 확인하는 것도 좋습니다.
CORS를 지원하는 몇 가지 AWS 서비스
- Amazon S3는 객체 스토리지 서비스로, CORS 설정을 통해 특정 출처에서 S3 버킷에 접근할 수 있도록 허용할 수 있습니다.
- S3 콘솔에서 CORS 구성(CORS Configuration) 문서를 작성하여 CORS를 설정할 수 있습니다. 여기에는 허용할 오리진(origin), 지원할 작업(HTTP 메서드), 요청에 허용할 헤더 등을 정의할 수 있습니다.
- CORS 규칙 최대 100개까지 추가 가능하며, 이를 통해 각 오리진별로 세부적인 접근 제어가 가능합니다.
- 예제:
- <https://example.com> GET POST *
- 이 설정은 https://example.com 출처에서 GET 및 POST 메서드로 S3 버킷에 접근할 수 있게 합니다.
2. Amazon API Gateway
- Amazon API Gateway는 RESTful 및 WebSocket API를 생성, 게시, 관리하는 서비스로, CORS 설정을 통해 크로스 오리진 요청을 허용할 수 있습니다.
- API Gateway 콘솔에서 한 번의 클릭으로 CORS를 설정할 수 있으며, 특정 오리진을 허용하고 필요한 HTTP 메서드를 정의할 수 있습니다.
- CORS 설정을 활성화하면 API Gateway는 필요한 CORS 헤더(예: Access-Control-Allow-Origin)를 응답에 자동으로 추가합니다.
3. AWS Lambda와 AWS CloudFront와 함께 사용
- AWS Lambda 함수의 경우, Access-Control-Allow-Origin 등의 CORS 헤더를 함수 응답에 포함하여 크로스 오리진 요청을 허용할 수 있습니다.
- AWS CloudFront를 사용해 프론트엔드 콘텐츠를 배포할 때도 CORS 헤더를 추가하여 CORS 정책을 설정할 수 있습니다. 이를 통해 캐싱과 보안을 동시에 관리할 수 있습니다.
CORS에러를 맞이했을 때 당황했던 기억이 있는데 이 기회에 CORS 등장배경과 그 작동 방식을 자세히 알게된 것 같아 좋았다.
(+추가적으로 오늘 밍글데이여서 팀별로 게임을 진행했는데 세영매니저님 덕에 정말 즐거운 시간을 보냈다. 무려 우리 9조가 1등했어요!!ㅎ.ㅎ)
'프론트엔드 부트캠프' 카테고리의 다른 글
팀과제 + DB에 대해서 (1) | 2024.11.18 |
---|---|
클린 코드 (Clean Code) (1) | 2024.11.15 |
[개인과제] 포켓몬 도감 만들 때 참고한 부분(1) (0) | 2024.11.13 |
RESTful API (3) | 2024.11.13 |
JavaScript의 History API (0) | 2024.11.11 |