2017. 9. 28. 21:37ㆍWebHacking/[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
'WebHacking > [OverTheWire]Natas' 카테고리의 다른 글
[ Natas 20 -> Natas 21 Session Hijacking ] (0) | 2017.10.07 |
---|---|
[ Natas 17 -> Natas18 PHP Injection ] (0) | 2017.09.28 |
[ Natas 16 -> Natas17 `Command`,"$(Command)" ] (0) | 2017.09.28 |
[ Natas 15 -> Natas 16 PHP Injection ( 비밀번호 유추 ) ] (0) | 2017.09.28 |
[ Natas 14 -> Natas 15 PHP Injection ( 쿼리 조건문 변조 ) ] (0) | 2017.09.28 |