0%

CORS란, CORS 해결방법, access-control-allow-origin, CORS/sop 이유

img

CORS란?

CORS란 Cross Origin Resource Sharing 의 약자로, 한국어로 교차 출처 리소스 공유라는 뜻입니다.

기본적으로 웹 브라우저는 동일 출처 정책(Same-Origin Policy)을 따르며, 이는 같은 출처에서만 리소스를 공유하도록 제한하는 보안 정책입니다.
그러나 CORS는 추가적인 HTTP 헤더를 사용하여 한 출처에서 실행 중인 웹 어플리케이션이 다른 출처의 선택한 리소스에 접근할 수 있도록 허용합니다.
Cross-Origin Resource Sharing (CORS)는 웹 페이지가 다른 도메인에서 리소스를 요청할 때, 보안상의 이유로 발생하는 제한을 완화하기 위한 정책입니다.
예를 들어, http://domain1.com에서 실행 중인 웹 페이지가 XMLHttpRequest 또는 Fetch API를 사용하여 http://domain2.com의 리소스를 요청할 수 있습니다.
이는 API 서버와 같은 다른 도메인으로 AJAX 요청을 보내는 등의 상황에서 유용합니다.

front-end 쪽의 화면과 api 서버가 같으면 same origin,
다르다면 cross origin으로, 아래 그림과 같이 표현할 수 있으며,
기본적으로 cross origin으로 통신불가하나 api 서버 변경으로 이를 가능하게 만들 수 있다로 정리할 수 있습니다.
img

CORS 해결방법

웹 개발을 하다보면 개발자도구에서 아래와 같이
access to xmlhttprequest at has been blocked by CORS policy no ‘access-control-allow-origin’ header is present
라는 메시지를 보실 수 있는데요,
CORS

이를 해결하려면 서버를 개발할때, 다른 도메인에서도 호출가능하도록 허용해주도록 개발해야 합니다.
정확히는, 서버쪽에서 http response header에 Access-Control-Allow-Origin 값을 변경해주어야 합니다.
어디든 상관없이 적용해주려면 http response를 하기위해 “access-control-allow-origin: *”로 명시해주어야 하며,
특정 도메인에서만 적용하려면 “access-control-allow-origin: http://domain-a.com“ 과 같이 명시해주면 됩니다.

주요 웹 프레임워크 별 CORS 해결하기 위한 예제코드는 아래와 같습니다.
아래 모든 예제는 모든 origin에 대해 resource를 허용하겠다는 것으로 가정합니다.

CORS 해결방법 : nodejs

1
2
3
4
5
6
7
8
9
10
11
const http = require('http');

const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*'); //CORS를 해결하기 위한 코드
res.write('Hello World!');
res.end();
});

server.listen(3000, () => {
console.log('Server listening on port 3000');
});

CORS 해결방법 : flask

1
2
3
4
5
6
7
8
9
from flask import Flask
from flask_CORS import CORS

app = Flask(__name__)
CORS(app, resources={r'*': {'origins': '*'}})

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)

CORS 해결방법 : fastapi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from fastapi import FastAPI
from fastapi.middleware.CORS import CORSMiddleware

app = FastAPI()

origins = [
"*",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

CORS 해결방법 : spring boot

WebConfig.class 파일을 만들고, addCorsMappings메소드를 아래와 같이 구현합니다.

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
.allowedOrigins("*")
.allowedMethods("*")
.allowCredentials(false)
.maxAge(3000);
}
}

SOP (Same Origin Policy) 가 브라우저 기본적인 정책인 이유

SOP를 왜 해야하는지, CORS 에러는 왜 개발자들을 괴롭히는지 알아보겠습니다.
만일 SOP가 아닐경우, CSRF와 같이 보안 사고가 발생할 수 있기 때문입니다.
어떤 악의적인 공격이 발생될 수 있는지 알아봅시다.

  1. 먼저, 아래와 같은 상황을 가정합니다.
  • bank.com : 정상적인 서비스 (송금가능한 사이트)
  • evil.com : 악의적인 사이트
    evil.com 은 아래와 같이 구성되어있다고 합시다.
    1
    2
    3
    4
    5
    <form method="post" action="http://bank.com/trasfer">
    <input type="hidden" name="to" value="evil">
    <input type="hidden" name="ammount" value="100">
    <input type="submit" value="주식종목 추천드립니다">
    </form>
  1. 아래와 같은 순서로,
    bank.com 에 로그인을 한 상태에서 evil.com에서 악의적으로 bank.com 으로 request를 날릴 수 있습니다.
    (사용자가 인지하지 못한 채로, 돈이 송금될 수 있는 사례입니다)
    CORS
@startuml

hide footbox
user -> bank.com : 로그인
bank.com -> user : 로그인정보가 담긴 session cookie 리턴
user -> evil.com : session cookie가 존재하는 상태로 사이트 접근
user -> evil.com : 사용자가 button 클릭
user -> bank.com : 로그인된 상태에서(session cookie 포함된 상태에서) evil로 $100 송금

footer devscb.com
@enduml

</div>

## 총평
개발할때 CORS가 뭔지 잘 모르고 이 문제를 해결하기 위해서 단순히 아래와 같이 header에 모든 도메인 허용하신 분들이 많을 것 같습니다.
Access-Control-Allow-Origin : *
그러나 이렇게 설정하면 얼마든지 보안사고가 일어날 수 있으니, 유의하셔야 겠습니다. 
무작정 웹에 나와있는 코드만 보고 에러메시지만 없애려고만 하지 마시고, 
이 개념을 잘 이해하셔서 보안사고가 일어나지 않도록 유의하시길 바랍니다.