기술보안/WEB
SOP(Same Origin Policy)
kimcogi
2022. 5. 10. 13:05
이용자가 웹 서비스에 접속할 때, 브라우저는 해당 웹 서비스에서 사용하는 인증 정보인 Cookie(쿠키)를 HTTP 요청에 포함시켜 전달하는 특징이 있다
이 특징은 사이트에 직접 접속하는 것만 한정되는 것이 아닌 브라우저가 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 Cookie(쿠키)를 함께 전송하는 특징을 가지고 있다
이 특징 때문에 악의적인 페이지가 클라이언트의 권한을 이용해 대상 사이트에 HTTP 요청을 보내고, HTTP 응답 정보를 획득 할 수 있는데 이 경우에는 정보 유출과 같은 보안 위협이 생길 수 있는 요소가 발생한다
따라서, 클라이언트 입장에서는 가져온 데이터를 악의적인 페이지에서 읽을 수 없도록 해야하는데 이때, 브라우저의 보안 매커니즘 중 하나인 SOP(동일 출저 정책, Same Origin Policy)가 사용된다
SOP의 Origin은 프로토콜(Protocol), 포트(Port), 호스트(Host)로 구성되어 있으며, 이 구성 요소가 모두 일치해야 동일한 Origin이라고 판단할 수 있다
URL | 결과 | 이유 |
https://same-origin.com/index.jsp | Same Origin | Path 값이 다름 |
http://same-origin.com/index.jsp | Cross Origin | Protocol(Scheme)이 다름 |
https://cross.same-origin.com/index.jsp | Cross Origin | Host가 다름 |
https://same-origin.com:8080/ | Cross Origin | Port가 다름 |
아래는 Javascript를 이용하여 SOP 테스트 코드를 만들어 보았다
<Same Origin>
// Same Origin
sameNewWindow = window.open('https://kimcogi.tistory.com/SOP');
console.log(sameNewWindow.location.href);
결과 : https://kimcogi.tistory.com/SOP
<Cross Origin>
// Cross Origin
crosNewWindow = window.open('https://security.com');
console.log(crossNewWindow.location.href);
결과 : Origin 오류 발생
<Cross Origin 데이터 읽기/쓰기>
// 외부 출저에서 불러온 데이터 읽기 및 쓰기
// Cross Origin 데이터 읽기/쓰기
crossNewWindow = window.open('https://security.com/');
crossNewWindow.location.href = "https://kimcogi.tistory.com/SOP";
만약 SOP의 모듈을 구성해본다면 아래처럼 예시 코드(HTML)를 들수 있다
<!-- iframe 객체 생성 -->
<iframe src="" id="myframe">
</iframe>
<!-- Javascript -->
<script> /* 2번째 줄의 iframe 객체를 my-Frame변수로 가져오기 */
let my-Frame = document.getElementById('myframe')
/* iframe 객체에 주소가 로드 될 시 아래 코드 실행 */
my-Frame.onload = () => {
try {
/* 로드 완료 시, secret-element 객체 내용 콘솔 출력 */
let secretValue = my-Frame.contentWindow.document.getElementById('secret-element').innerText;
console.log({ secretValue });
} catch(error) {
/* 오류 발생 시 콘솔에 오류 로그 출력 */
console.log({ error });
}
}
/* iframe 객체 내 Same origin, Cross, origin 주소 로드 */
const loadSameOrigin = () => { my-Frame.src = 'https://same-origin.com/index.jsp'; }
const loadCrossOrigin = () => { my-Frame.src = 'https://cross-origin.com/index.jsp'; }
</script>
<!-- 버튼 2개 생성 (Same origin, Cross origin) -->
<button onclick=loadSameOrigin()>Same Origin</button><br>
<button onclick=loadCrossOrigin()>Cross Origin</button>
<!-- index.jsp의 코드는 아래와 같음, secret-element라는 ID를 가진 div 객체 내 비밀 값(treasure) 삽입 -->
<div id="secret-element">treasure</div>
반응형