overthewire.org 문제 풀이 / Natas Level 10 → Level 11
이번 문제는 쿠키가 XOR 암호화로 보호되고 있다고 합니다.
그리고 배경화면 색상을 입력하는 부분이 있습니다.
먼저 소스코드를 보겠습니다.
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "<censored>" };</script></head>
<?
$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>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
data의 default값은 "showpassword"는 no이고, bgcolor 값은 #ffffff입니다.
우리는 data 값을 howpassword"는 yes, bgcolor 값은 #ffffff로 만들어야 합니다.
loadData 함수를 보면 COOKIE의 data 값을 아래와 같은 순으로 디코딩하여 $tempdata를 만들어 냅니다.
=> base64_decode() -> xor_encrypt() -> json_decode()
그렇기 때문에 data 값을 howpassword"는 yes, bgcolor 값은 #ffffff 을 아래 순으로 인코딩하여 쿠키값으로 설정하면 이 문제를 풀 수 잇습니다.
=> json_encode() -> xor_encrypt() -> base64_encode()
그런데 xor_encrypt()를 하기 위해서는 XOR에 사용되는 key 알아야 합니다.
우선 saveData 함수를 보면 setcookie 함수로 "data"값이 설정됩니다.
json_encode() -> xor_encrypt() -> base64_encode() 순으로 인코딩이 됩니다.
EditThisCookie로 보면 쿠키의 data 값이 표시되는 것을 볼 수 있습니다.