sql의 implicit type conversion을 이용한 문제이다.
자세한 내용은 아래 두 링크를 참고하길 바란다.
문제 살펴보기

문제의 전체 코드는 위와 같다.
필요한 부분만 추출하여 보도록 하자.
if(preg_match('/prob|_|\.|\(\)|#|-/i', $_GET[pw])) exit("No Hack ~_~");
if(strlen($_GET[pw])>6) exit("No Hack ~_~");
pw 파라미터를 통해 값을 전달할 수 있다.
그런데 'prob', '_', '.', '\', '#', '-' 를 모두 사용할 수 없다.
지금까지 사용했던 %23(#)을 사용할 수 없게 되었다.
또한 pw 파라미터로 전달한 값의 길이가 6바이트를 넘으면 안된다.
$query = "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'";
...
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("nightmare");
where 문을 참으로 만들면 풀리는 문제라고 한다.
문제 풀이 과정
# 대신 사용할 수 있는 주석은 다양하게 있다.
한 줄만 주석처리하는 주석 중 # 다음으로 길이가 짧은 ;%00을 사용하면 될 것 같다.
바이트 길이 제한 때문에 문제 풀기가 상당히 까다로웠다.
구글링을 해본 결과 implicit data conversion을 이용하여 문제를 풀 수 있다고 한다.
우선 pw=('')을 사용하여 single quote(')와 괄호를 닫아준다. → 2byte 사용
pw=('')는 false 가 되는데, pw=('')=0과 같이 값을 넣어주면 논리자료형과 정수를 비교하게 된다.
이 때, 논리자료형의 우선순위가 더 낮아 정수(0)으로 바뀌게 된다. 0=0은 참이기 때문에,
where 문이 참이 된다. 그 후, ;%00을 통해 뒷 부분을 주석처리하면 된다.
만약 설명에서 틀린 부분이 있다면 지적 부탁드립니다.

페이로드 : ?pw=')=0;%00
상당히 이름값을 하는 문제였다.
다음 문제를 풀도록 합시다.
'web > Lord of SQLInjection' 카테고리의 다른 글
| Lord of SQLInjection - 20번 : dragon (0) | 2023.12.10 |
|---|---|
| Lord of SQLInjection - 19번 : xavis (1) | 2023.12.10 |
| Lord of SQLInjection - 17번 : zombie assassin (0) | 2023.12.10 |
| Lord of SQLInjection - 16번 : succubus (0) | 2023.12.10 |
| Lord of SQLInjection - 15번 : assassin (0) | 2023.12.10 |