Post

Natas Level 20 풀이


로그인


Username: natas20
URL: http://natas20.natas.labs.overthewire.org


admin으로 로그인해야 한다.
소스코드를 보면,

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
 
function debug($msg) { /* {{{ */
    if(array_key_exists("debug", $_GET)) {
        print "DEBUG: $msg<br>";
    }
}
/* }}} */
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.";
    }
}
/* }}} */
 
/* we don't need this */
function myopen($path, $name) {
    //debug("MYOPEN $path $name");
    return true;
}
 
/* we don't need this */
function myclose() {
    //debug("MYCLOSE");
    return true;
}
 
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);
    return true;
}
 
/* we don't need this */
function mydestroy($sid) {
    //debug("MYDESTROY $sid");
    return true;
}
/* we don't need this */
function mygarbage($t) {
    //debug("MYGARBAGE $t");
    return true;
}
 
session_set_save_handler(
    "myopen",
    "myclose",
    "myread",
    "mywrite",
    "mydestroy",
    "mygarbage");
session_start();
 
if(array_key_exists("name", $_REQUEST)) {
    $_SESSION["name"] = $_REQUEST["name"];
    debug("Name set to " . $_REQUEST["name"]);
}
 
print_credentials();
 
$name = "";
if(array_key_exists("name", $_SESSION)) {
    $name = $_SESSION["name"];
}
 
?>
 
<form action="index.php" method="POST">
Your name: <input name="name" value="<?=$name?>"><br>
<input type="submit" value="Change name" />
</form>




풀이



print_credentials()는 $_SESSION에서 admin 키가 존재하고 그 값이 1일 때 패스워드를 출력한다.
따라서 세션의 키-값 쌍으로 admin,1이 되도록 하면 될 것이다.


전체적으로 세션데이터를 수동으로 관리하는 코드인데
session_set_save_handler()로 세션 기능을 사용자 정의 함수들( myopen(), myclose(), myread(), mywrite(), mydestroy(), mygarbage() )로 설정하고 있다.


이 중 myread()와 mywrite()를 보면
myread()에서는 세션 파일에 추가된 키-값 쌍이 검증없이 그대로 $_SESSION에 로드되고,
mywrite()에서는 $_SESSION 데이터가 제대로된 검증없이 세션파일에 저장되고 있다.


burpsuite를 켜서, admin으로 이름 변경해보면 아무일도 일어나지 않는다.
Desktop View


name을 바꾸는 요청을 인터셉트해서, 세션 파일에 admin 1 키-값이 추가되도록 name 파라미터에 admin 1을 url인코딩한 값으로 바꿔 보내자.

Desktop View

한 번 더 인터셉트해서 name 파라미터 값을 똑같이 %0Aadmin 1 로 변경해 보내면 된다.


첫번째로 포워드했을 때 세션 파일에 admin 1 키-값 쌍 추가해서 저장되고,
두번째로 포워드하면 세션 파일에 저장된 admin 1 키-값 쌍을 세션데이터로 로드해서 패스워드가 출력된다.

Desktop View

자세하게 쓴 write-up은 https://00yj.tistory.com/257~

This post is licensed under CC BY 4.0 by the author.