본문 바로가기

드림핵

[드림핵 워게임] [wargame.kr] type confusion

<문제>

 

<풀이>

문제 사이트에 접속하면 처음으로 뜨는 페이지이다.

이것만 보고는 아무것도 알 수 없으므로 view-source를 클릭해서 코드를 확인해본다.

 

<?php
 if (isset($_GET['view-source'])) {
     show_source(__FILE__);
    exit();
 }
 if (isset($_POST['json'])) {
     usleep(500000);
     require("./lib.php"); // include for FLAG.
    $json = json_decode($_POST['json']);
    $key = gen_key();
    if ($json->key == $key) {
        $ret = ["code" => true, "flag" => $FLAG];
    } else {
        $ret = ["code" => false];
    }
    die(json_encode($ret));
 }

 function gen_key(){
     $key = uniqid("welcome to wargame.kr!_", true);
    $key = sha1($key);
     return $key;
 }
?>

POST 요청으로 받은 'json' 입력값에 들어있는 key의 value를 gen_key() 함수로 생성한 $key 값과 비교해서 같으면 flag를 출력한다.

이때 gen_key()로 생성한 $key값은 uniqid() 함수와 sha1() 함수를 거쳐 만들어지는데

마이크로초 단위의 현재시간으로 생성(uniqid())되고 암호화(sha1())되므로 그 값을 알아낼 수 없다.

 

그런데 json 입력값에 들어있는 key의 value와 $key 값을 비교하는 연산자가 == 인 점에 주목할 필요가 있다.

==은 느슨한 비교로, 위의 표를 보면 한 쪽 인자가 비어있지 않은 문자열이고 한 쪽 인자가 true이면 비교 결과가 항상 true이다.

우리가 보고 있는 코드에서는 $key가 문자열이므로 json에 전달하는 값을 true로 하면 flag를 만날 수 있다.

 

POST요청을 보내는 부분의 코드를 찾아보자.

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
        <script src="./util.js"></script>
    </head>
    <body>
        <form onsubmit="return submit_check(this);">
            <input type="text" name="key" />
            <input type="submit" value="check" />
        </form>
        <a href="./?view-source">view-source</a>
    </body>
</html>

폼 태그의 onsubmit속성을 보면 submit되었을 때 submit_check() 함수를 호출한다.

 

개발자 도구(F12)를 열어 Source탭에서 util.js파일을 확인했다.

 

function submit_check(f){
	if (lock) {
		alert("waiting..");
		return false;
	}
	lock = true;
	var key = f.key.value;
	if (key == "") {
		alert("please fill the input box.");
		lock = false;
		return false;
	}

	submit(key);

	return false;
}

 

submit_check() 함수는 위와 같이 생겼다.

폼에서 입력받은 key요소의 값 즉 사용자가 폼에 입력한 값을 key 변수에 받아서 submit() 함수를 호출한다.

 

function submit(key){
	$.ajax({
		type : "POST",
		async : false,
		url : "./index.php",
		data : {json:JSON.stringify({key: key})},
		dataType : 'json'
	}).done(function(result){
		if (result['code'] == true) {
			document.write("Congratulations! flag is " + result['flag']);
		} else {
			alert("nope...");
		}
		lock = false;
	});
}

submit() 함수는 위와 같이 생겼다.

사용자의 입력값을 json 형태로 구성하여 POST 요청을 보낼 때 파라미터로 전달한다.

 

submit() 함수에서 전달되는 json 객체의 key의 value를 true로 수정하여

개발자 도구의 Console에 입력했다.

이제 폼에 어떤 값을 입력해서 제출해도 입력값이 true로 전달될 것이다.

 

폼에 아무 값이나 입력했다.

 

제출하면 FLAG가 출력된다.