문제풀이
빈칸과 코드가 주어진다.
<?php
$db = dbconnect();
if($_POST['id']){
$_POST['id'] = str_replace("\\","",$_POST['id']);
$_POST['id'] = str_replace("'","''",$_POST['id']);
$_POST['id'] = substr($_POST['id'],0,15);
$result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
if($result[0] == 1){
solve(39);
}
}
?>
○ 코드 분석
1) id에서 \\를 공백으로 ' 를 '' 로 replace
3) id에서 15자리만 split
4) SQL 쿼리를 실행해고 결과를 가져와 $result에 저장
5) result[0]이 1이면 문제 해결
목표는 result[0] == 1 조건을 충족하는 것이다.
SQL 쿼리를 보면, select 문 결과는 항상 1이다. 즉, where문 조건만 DB에 저장된 데이터와 일치하면된다.
where 문에서 and 기준 뒷부분을 보면 id='~~ 로 되어있는데 앞에만 ' 가 있을 뿐이고 뒤에는 ' 가 없다. 따라서 id로 ' 를 넣어서 쿼리문이 정상적으로 끝맺음이 되도록 완성해야한다. (안 넣으면 쿼리 에러 발생)
그러나 ' 를 '' 로 치환하기 때문에 일반적인 방법으로 ' 를 입력하는 것은 힘들다.
하지만 15자리만큼 split하고 있으니, id의 15번째 인덱스에 ' 를 넣는다면 '' 로 치환되도 하나의 ' 만 남기 때문에 우회 가능하다.
11111111111111'
(예시)
위와 같은 형태를 생각했고 id를 입력했다. 하지만 문제가 발생했다.
id 길이가 14보다 작아야 한다는 조건이 있다.
필자가 생각한대로면 총 15자리라서 id 길이가 14보다 작아야 한다는 조건이 성립하지 않는다.
이것을 우회하기 위해 여러가지 방법을 생각해봤고 SQL과 관련해서 새로운 사실을 알았다.
SQL에서는 입력값 사이에 빈칸이 존재하면 쿼리 실행단계에서 전부 무시하고 실행하는 특징이 있다.
1[빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸][빈칸]'
(예시)
즉, 위와 같이 입력해도 쿼리 실행 과정에서는 [빈칸]이 모두 제거되서 id는 1' 이 된다.
payload를 제출해보자.