[ Natas 18 -> Natas19 Session Hijacking ]

2017. 9. 28. 21:37WebHacking/[OverTheWire]Natas


1> 페이지 초기화면 ( admin으로 로그인해보자 )


2> 실행 결과


$_SESSION[admin] == 0 이므로 admin계정으로 시스템에서 인식되어 지지 않는다


3> PHP 소스코드를 보고 시스템 실행 순서를 이해하자

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
<? 
 
$maxid = 640// 640 should be enough for everyone 
 
function isValidAdminLogin() { /* {{{ */     # 사용자가 접속하는 계정명이 admin인지 확인하는 함수지만
    if($_REQUEST["username"== "admin") {     # return 1 을 주석처리하여 이용할 수 없다
    /* This method of authentication appears to be unsafe and has been disabled for now. */ 
        //return 1; 
    } 
 
    return 0
/* }}} */ 
function isValidID($id) { /* {{{ */ 
    return is_numeric($id); 
/* }}} */ 
function createID($user) { /* {{{ */ 
    global $maxid
    return rand(1$maxid); 
/* }}} */ 
function debug($msg) { /* {{{ */ 
    if(array_key_exists("debug"$_GET)) { 
        print "DEBUG: $msg<br>"
    } 
/* }}} */ 
function my_session_start() { /* {{{ */ 
    if(array_key_exists("PHPSESSID"$_COOKIE) and isValidID($_COOKIE["PHPSESSID"])) { 
# => 쿠키에 PHPSESSID 값이 존재하고 숫자인 경우

    if(!session_start()) { # 세션 생성 실패
        debug("Session start failed"); 
        return false

    } else { 
        debug("Session start ok"); # 사용자가 로그인에 성공하고 세션 생성
        if(!array_key_exists("admin"$_SESSION)) { 
        debug("Session was old: admin flag set"); 
        
$_SESSION["admin"= 0// backwards compatible, secure
# 세션 변수의 admin키 값을 0으로 초기화한다

        } 
        return true
    } 
    } 
 
    return false
/* }}} */ 
function print_credentials() { /* {{{ */ 
    if($_SESSION and array_key_exists("admin"$_SESSION) and $_SESSION["admin"== 1) {     # 세션변수의 admin키 값이 존재하고, 그 값이 1이다
    print "You are an admin. The credentials for the next level are:<br>";                     # => admin으로 인정되며 Natas19 비밀번호가 출력된다
    print "<pre>Username: natas19\n"
    print "Password: <censored></pre>"
    } else { 
    print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19."
    } 
/* }}} */ 
 
$showform = true
if(my_session_start()) { 
    print_credentials(); 
    $showform = false
else { 
    if(array_key_exists("username"$_REQUEST&& array_key_exists("password"$_REQUEST)) {     # 사용자명, 비밀번호를 입력
    session_id(createID($_REQUEST["username"])); 
    session_start();                                 # 세션 생성
    $_SESSION["admin"= isValidAdminLogin();        # 0으로 초기화된다
    debug("New session started"); 
    $showform = false
    print_credentials(); 
    } 
}  
 
if($showform) { 
?> 
 
<p
Please login with your admin account to retrieve credentials for natas19. 
</p
 
<form action="index.php" method="POST"
Username: <input name="username"><br
Password: <input name="password"><br
<input type="submit" value="Login" /
</form
<? } ?> 
cs



4> 문제 파악

관리자 계정으로 인식되어 지기 위해서는

66 $_SESSION["admin"= isValidAdminLogin(); 에서 return 1 을 시켜서 

48 $_SESSION["admin"== 1 을 만족시켜야 하지만 함수를 변질 시킬 수 는 없다


페이지 소스코드의 첫번째 줄을 보면 $maxid = 640; // 640 should be enough for everyone 가 있다

해당 페이지의 아이디가 640개 있다고 한다. 즉, 세션 아이디가 640개 존재하고, 그 중에는 관리자 세션 아이디가 존재할 것이다

그럼 최대 640개의 패킷들을 각각 세션아이디 값을 바꿔가며 서버에 전송하면, 관리자 세션 아이디 일 때 화면에 비밀번호가 출력 될 것이다

관리자의 세션아이디로 변조된 패킷이 서버에 전송되면, $_SESSION[admin]==1 이 만족되어 화면에 결과물이 출력된다


[ SESSID 값 확인 ]



5> 파이썬 자동화 프로그래밍

[ 파이썬 소스코드 ]


[ 와이어 샤크 캡쳐화면 1 ]


[ 와이어 샤크 캡쳐화면 2 ]


PHPSESSID 를 1~ 640 까지 바꿔가며 패킷을 계속 전송한다


[ 실행결과 ]


SESSID = X 가 서버의 관리자(admin)계정의 세션아이디 일 때 화면에 출력되는 문자들이다

natas19의 비밀번호가 출력된다



natas19 : 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs