OverTheWire: Natas level11
OverTheWire 문제풀이 - Natas
* Bandit는 웹 보안 관련 문제입니다.
* 개인적인 문제풀이로 해답을 보시기 전에 직접 풀어보시기를 권해드립니다.
* 반드시 연습용으로 제공된 환경에서만 작업하시기 바랍니다. 악용으로 일어난 사태는 절대로 책임지지 않습니다.
Natas level11
Natas11에 접속하면 다음과 같은 화면을 볼 수 있다.
쿠키값은 XOR 연산으로 보호받고 있다는데 아직은 무슨 소린지 알 수가 없다. 소스를 살펴볼 필요가 있다.
[View sourcecode]
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <? $defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff"); function xor_encrypt($in) { $key = '<censored>'; $text = $in; $outText = ''; // Iterate through each character for($i=0;$i<strlen($text);$i++) { $outText .= $text[$i] ^ $key[$i % strlen($key)]; } return $outText; } function loadData($def) { global $_COOKIE; $mydata = $def; if(array_key_exists("data", $_COOKIE)) { $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true); if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) { $mydata['showpassword'] = $tempdata['showpassword']; $mydata['bgcolor'] = $tempdata['bgcolor']; } } } return $mydata; } function saveData($d) { setcookie("data", base64_encode(xor_encrypt(json_encode($d)))); } $data = loadData($defaultdata); if(array_key_exists("bgcolor",$_REQUEST)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) { $data['bgcolor'] = $_REQUEST['bgcolor']; } } saveData($data); ?> <h1>natas11</h1> <div id="content"> <body style="background: <?=$data['bgcolor']?>;"> Cookies are protected with XOR encryption<br/><br/> <? if($data["showpassword"] == "yes") { print "The password for natas12 is <censored><br>"; } ?> <form> Background color: <input name=bgcolor value="<?=$data['bgcolor']?>"> <input type=submit value="Set color"> </form> | cs |
소스가 좀 복잡한데 결과적으로 우리는 위 코드의 57번 줄 showpassword 값이 "yes"가 되면 natas12 패스워드를 획득할 수 있는 것을 알 수 있다.
이 사실을 인지하고 코드를 풀어나가야 하는데 줄은 길지만 잘 보면 크게 3개의 함수가 존재하는 것을 알 수 있다.
5번 줄의 xor_encrypt($in), 18번 줄의 loadData($def), 마지막으로 33번 줄의 saveData($d) 이렇게 3개의 함수가 존재한다.
loadData 함수가 $defaultadata를 매개변수로 이용하여 현재 쿠키값을 base64_decode > xor_encrypt > json_decode 순으로 복호화하여 나온 값을 $data에 저장해주고, SaveData 함수가 $data값을 다시 json_encode > xor_encrypt > base64_encode 순으로 암호화하여 쿠키 값을 설정해준다. 이 과정에서 $defaultadata 값이 항상 array( "showpassword"=>"no", "bgcolor"=>"#ffffff")로 정해져있기 때문에 우리가 어떤 값을 입력하든 결과적으로는 $data["showpassword"] == "no" 라는 공식이 나와서 암호를 볼 수가 없다. 이 showpassword 값을 "yes"로 바꿔주어야 하는데 해답의 실마리는 xor_encrypt 함수에서 찾을 수 있다.
xor_encrypt 함수에서 특정 key 값을 이용해 xor 연산으로 $outText 값을 형성하는데 xor 특징상 A xor B = C 라면, A xor C = B 라는 공식이 성립되기 때문에 디코드된 쿠키 값과 언코드된 $defaultdata 값을 이용해 key 값을 구할 수 있다.
[key 구하기]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php function xor_encrypt() { $defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff"); $text = base64_decode("ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw"); $outText = json_encode($defaultdata); $key = ''; for($i=0;$i<strlen($text);$i++) { $key .= $outText[$i] ^ $text[$i % strlen($text)]; } return $key; } echo "key : " . xor_encrypt() . "\n"; ?> | cs |
이 php 코드를 돌려보면 다음과 같이 나온다.
key : qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php function xor_encrypt($in) { $defaultdata = array( "showpassword"=>"yes", "bgcolor"=>"#ffffff"); $key = 'qw8J'; $text = json_encode($defaultdata); $outText = ''; for($i=0;$i<strlen($text);$i++) { $outText .= $text[$i] ^ $key[$i % strlen($key)]; } return $outText; } echo "cookie : " . base64_encode(xor_encrypt()) . "\n"; ?> | cs |
next level password : EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3
'War Game > natas' 카테고리의 다른 글
OverTheWire: Natas level13 (0) | 2017.07.20 |
---|---|
OverTheWire: Natas level12 (0) | 2017.07.14 |
OverTheWire: Natas level10 (0) | 2017.07.12 |
OverTheWire: Natas level9 (0) | 2017.04.27 |
OverTheWire: Natas level8 (0) | 2017.04.26 |