기술보안/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>
반응형