1. RPO?
Ralative Path Overwrite, 말 그대로 상대경로를 덮어쓰는 기법이다.
웹 페이지가 CSS나 JS 같은 리소스를 상대경로로 불러올 때, 사용자가 접근한 URL 형태에 따라 브라우저가 그 상대경로를 원래 의도와 다르게 해석하게 만드는 방식이다.
예를 들어 페이지에서 아래처럼 리소스를 불러온다고 하자.
<script src="config.js"></script> <link rel="stylesheet" href="style.css">
개발자는 현재 문서 기준으로 config.js, style.css가 로드될 것 이라고 생각한다.
하지만 사용자가 페이지를 여는 URL이 예상과 다르면, 브라우저는 이 상대경로를 다른 위치로 계산할 수 있다.
즉, RPO는 서버가 아니라 브라우저의 상대경로 해석 방식을 이용하는 기법이라고 보면 된다.
2. 왜 발생하는가?
- 문서가 리소스를 상대경로로 불러옴
- 서버가 비정상적인 경로도 같은 문서로 처리함
- 브라우저는 현재 URL을 기준으로 상대경로를 다시 계산함
예를 들어 /test.php로 접근한다고 했을 때, <script src="config.js"></script> 는 보통 /config.js 또는 /test.php 기준의 같은 디렉터리 위치로 해석된다.
그런데 /test.php/~~~ 처럼 접근 할 수 있으면?
서버가 이 주소들도 여전히 test.php가 처리하도록 받아준다면, 브라우저는 현재 문서를 디렉터리처럼 보고 상대경로 config.js를 /test.php/config.js 처럼 계산할 수 있다.
이건 개발자가 원래 의도한 위치가 아니다. 결국 config.js가 정상 로드되지 않거나, 심한 경우 다른 응답을 받게 된다.
3. Example
<html>
<head>
<script src="config.js"></script>
</head>
<body>
Hello
</body>
</html>
이런 페이지가 있다고 하면, 개발자는 /page.php로 접근할 것만 생각했다.
그런데 서버가 /page.php/~~~ 요청도 전부 page.php로 처리한다면, 브라우저는 현재 문서를 디렉터리처럼 보고 config.js를 /page.php/config.js 로 요청할 수 있다.
원래 의도는 /config.js 또는 /page_dir/config.js 였는데, 완전 다른 URL이 되어버린다.
이렇게 되면 필요한 JS가 로드되지 않고, CSS가 이상한 문서를 불러와 stylesheet처럼 해석될 수 있고, 이후 DOM 구조나 전역 변수에 의존하던 로직이 깨진다.
결론은 RPO 단독으로 끝나기보다 보통 다른 취약점이랑 연계해서 같이 나온다.
4. Extension
4-1. 보호용 JS 로드를 깨뜨릴 수 있음
어떤 페이지가 config.js, sanitize.js, security.js 같은 파일에 의존해서 방어 로직을 수행한다면, RPO로 해당 파일 로드를 망가뜨려 보호 로직 자체를 무력화할 수 있다.
4-2. DOM Clobberring과 결합
원래라면 JS가 window.CONFIG 같은 객체를 세팅해 주는데, 그 JS가 로드되지 않으면 공격자가 삽입한 DOM 요소가 그 자리를 대신 차지할 수 있다.
4-3. CSS 해석 문제로 이어질 수 있음
옛날 RPO 사례에서는 HTML 문서를 CSS처럼 해석하게 만들어서 정보 유출이나 스타일 기반 공격으로 이어지는 경우도 있었는데, 요즘은 브라우저/헤더 정책 때문에 자주 보이진 않는다.
5. Mitigation
5-1. 상대경로 대신 절대경로 사용
<script src="/js/config.js"></script>
<link rel="stylesheet" href="/css/style.css">
이런식으로 하면 현재 URL이 어떻게 바뀌든 경로 해석이 흔들리지 않는다.
5-2. 비정상 경로 차단
/page.php/~~~ 같은 요청이 정상 경로가 아니면 404 반환
5-3. 클라이언트 측 전역 객체에 과도하게 의존하지 않기
JS에서 window.CONFIG 같은 전역 객체를 너무 믿고 쓰는 구조는 DOM Clobbering과 결합될 수 있다.
더 명시적이고 안전한 초기화 방식이 좋다.
'Web' 카테고리의 다른 글
| DOM Clobbering (0) | 2026.03.13 |
|---|---|
| [Dreamhack] Strong BypassIF / Write up (0) | 2026.03.13 |
| [Dreamhack] Guest book v0.2 / Write up (0) | 2026.03.13 |
| [Dreamhack] Guest book / Write up (0) | 2026.03.11 |
| [Dreamhack] node_api / Write up (0) | 2026.03.11 |