일부 웹 어플리케이션은 이용자의 편의성을 위해 url rewrite 기능을 사용한다. url rewrite 기능을 사용하면 https://host/search_user_by_name.php?name=alice와 같은 형태의 url을 https://host/search/alice/와 같은 형태로 훨씬 기억하기 쉽고, 간결하게 만드는 것이 가능하다. 하지만 이때 브라우저의 입장에서는 URL의 경로 중 어디부터가 파라미터인지 구별할 수 없다. 만약 이용자가 입력한 파라미터를 브라우저가 경로로 인식하여 해당 경로로부터 자원을 불러오게 되면 의도치 않은 동작이 발생할 수 있다.


Relative Path Overwrite

Relative Path Overwrite

**Relative Path Overwrite (RPO)**는 일반적으로 서버와 브라우저가 상대 경로를 해석하는 과정에서 발생하는 차이점을 이용한 공격이다.

url rewrite 기능을 사용하면 웹 애플리케이션 스크립트명 이하의 경로를 별도로 지정해도 같은 페이지가 조회되는 경우가 존재한다. 예를 들어 /index.php/somepath와 같이 스크립트명 하위로 새로운 경로를 지정해도 서버는 이를 /index.php를 참조하도록 구현되어 있는 경우이다.

그러나 이 때 만약 웹 페이지 내부에서 다른 자원을 참조하는 경우, 새로운 문제가 발생할 수 있다. 예를 들어 다음과 같이 스크립트를 로드하는 태그가 두 개 있다.

<script src="/app/main.js"></script>
<script src="app/main.js"></script>

첫 번째 줄과 두 번째 줄의 차이는 src 속성 맨 앞에 존재하는 /의 차이가 있다. 첫 번째 줄은 앞에 존재하는 /에 의해 스크립트 로드 시 **최상위 경로부터 시작하여 탐색 (절대 경로)**하고 로드한다. 반면에 두 번째 줄의 스크립트는 **현재 경로에서 시작하여 탐색 (상대 경로)**하고 로드한다.

rpo.php에 위 두 스크립트 태그를 작성한 후 http://host/rpo.php와 같이 접근 시 같은 경로에 존재하는 /app/main.js를 로드한다.

5c0915673badab0add213e3a1a3f2019e67a1b9fb799e878360dce0bac5a1cea.png

하지만 http://host/rpo.php/와 같이 요청하게 되면 첫 번째 줄의 스크립트 태그는 절대 경로로 탐색하여 /app/main.js를 로드하지만, 2번째 줄의 스크립트 태그는 현재 경로가 /rpo.php/이므로 해당 경로부터 시작하여 /rpo.php/app/main.js에 존재하는 파일에 대해 요청하게 된다.

4be6c810a30fec2b05e5e0129a5518b540936ef9de8d3d78651aa31a4175b34d.png

즉, index.php의 페이지 내용을 자바스크립트의 내용으로써 사용할 수 있게 된다.

Relative Path Overwrite 공격 예시

RPO는 일반적으로 자바스크립트나 스타일시트 코드를 로드하는 과정에서 경로 해석의 문제로 인해 발생한다. 따라서 임포트하는 페이지의 내용을 조작시킬 수 있다면 공격자가 의도한 자바스크립트, 스타일시트 코드를 로드시킬 수 있다.

자바스크립트와 연계