https://webhacking.kr/challenge/web-38/
61번 문제이다.
이런 소스코드가 주어졌다. 하나씩 해석해보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
$db = dbconnect();
if(!$_GET['id']) $_GET['id']="guest"; //id의 값이 없으면 guest로 설정
echo "<html><head><title>Challenge 61</title></head><body>";
echo "<a href=./?view_source=1>view-source</a><hr>";
$_GET['id'] = addslashes($_GET['id']); //addslashes 함수를 사용하여 id값 재설정
if(preg_match("/\(|\)|select|from|,|by|\./i",$_GET['id'])) exit("Access Denied");
//괄호, select, from, 콤마, by, 마침표 필터링
if(strlen($_GET['id'])>15) exit("Access Denied"); //글자수 제한
$result = mysqli_fetch_array(mysqli_query($db,"select {$_GET['id']} from chall61 order by id desc limit 1"));
echo "<b>{$result['id']}</b><br>"; //쿼리문 실행하여 'id'로 값을 찾음
if($result['id'] == "admin") solve(61); //찾은 값이 admin일 경우 문제 해결
echo "</body></html>";
?>
주석으로 설명해놨다. 다시한번 흐름을 해석해보면
id를 get 메소드로 받는다.
받은 값을 addslashes()함수로 재설정한다.
괄호, select, from, 콤마, by, 마침표가 id값에 들어가 있을 시 접근을 제한한다.
글자수도 15자를 초과할 시 접근을 제한한다.
select {$_GET['id']} from chall61 order by id desc limit 1 을 실행한다.
이 값이 admin이면 문제 해결
그 외 필자가 접근한 잘못된 방법들을 소개하겠다.
1. id = *
테이블에 값이 admin과 guest가 들어가 있을 때, admin의 인덱스가 처음일 것을 기대하고 시도한 방법이다. 하지만 쿼리문 뒤에 order by id desc limit 1이 들어있어 실패했다.
2. id = * from chall61;-- -
정렬 값을 무시해주기 위해 위와 같은 방법을 생각해봤지만 from 이 필터링 되어 실패했다.
union select를 사용하는 방법도 생각해봤지만 마찬가지로 select가 필터링되어 있어 실패했다.
3. id = 'admin'
addslashes()함수에 의해 \'admin\'이 되어 실패했다.
addslashes 함수는 성공적인 접근방법을 소개함과 동시에 설명하겠다.
성공적인 접근 법
우리가 select문에 admin문자열을 넣고 싶다면 'admin' 넣어야 한다. 하지만 addslashes()함수는 작은 따옴표나 큰 따옴표 앞에 백슬래시를 붙여 문자로 인식하게 한다.
간단히 소개하자면 싱글쿼터, 더블쿼터, 널 문자 등등을 이스케이프한다.
예를 들어, I am a 'man' 이라는 문자를 코드에 삽입한다고 생각해보면 싱글쿼터를 문자로 인식하지 않을 수 있을 것이다. 그러면 오류가 발생하기 때문에 addslashes를 사용하여 싱글 쿼터를 문자로 인식하게 해주는 함수이다.
http://docs.php.net/manual/en/function.addslashes.php
위 자료를 참고하자.
따라서 우리는 admin을 16진수로 바꿔서 입력해야 한다.
admin을 16진수로 바꾸면 0x61646d696e이다.
하지만 이대로 입력하면 문제가 풀리지 않는다.
이유는 if($result['id'] == "admin") solve(61); 에 있다. 자세히 보면 result변수에서 id로 값을 검색하고 있다.
result 변수는 $result = mysqli_fetch_array(mysqli_query($db,"select {$_GET['id']} from chall61 order by id desc limit 1"));
라고 한다. 여기서 mysqli_fetch_array함수에 주목해보자.
이 함수는 결과 집합에서 한 행의 데이터를 가져와 배열로 반환한다.
위 코드에서는 $result['id'] 와 같이 연관 배열 형태로 값을 찾고 있다. 우리는 select 0x61646d696e as id 와 같이 admin의 키를 id로 설정해주어야 한다.
https://www.php.net/manual/en/mysqli-result.fetch-array.php
위 자료를 참고하자.
그럼 우리는 id = 0x61646d696e as id를 입력해도 문제가 풀리지 않는다. 왜냐하면 15글자를 초과하기 때문이다.
위 형식에서 as를 빼도 설정에 문제가 없으므로 우리는 최종적으로 id = 0x61646d696e id를 입력해야 한다.
짜자잔
'웹 해킹 > webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] old - 38 풀이 (0) | 2023.08.23 |
---|---|
[Webhacking.kr] old - 24 풀이 (0) | 2023.08.03 |
[Webhacking.kr] old - 39 풀이 (0) | 2023.07.14 |
[webhacking.kr] Challenge 16 풀이 (0) | 2023.07.14 |
[webhacking.kr] old - 26 풀이 (0) | 2023.06.27 |