본문 바로가기
webhacking.kr

[webhacking.kr] old - 61 풀이

by jwcs 2023. 7. 20.
728x90

https://webhacking.kr/challenge/web-38/

 

Challenge 61

 

webhacking.kr

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

 

PHP: addslashes - Manual

spamdunk at home dot com, your way is dangerous on PostgreSQL (and presumably MySQL). You're quite correct that ANSI SQL specifies using ' to escape, but those databases also support \ for escaping (in violation of the standard, I think). Which means that

docs.php.net

위 자료를 참고하자.

 

따라서 우리는 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

 

PHP: mysqli_result::fetch_array - Manual

query($query);/* numeric array */$row = $result->fetch_array(MYSQLI_NUM);printf("%s (%s)\n", $row[0], $row[1]);/* associative array */$row = $result->fetch_array(MYSQLI_ASSOC);printf("%s (%s)\n", $row["Name"], $row["CountryCode"]);/* associative and numeri

www.php.net

위 자료를 참고하자.

 

그럼 우리는 id = 0x61646d696e as id를 입력해도 문제가 풀리지 않는다. 왜냐하면 15글자를 초과하기 때문이다.

위 형식에서 as를 빼도 설정에 문제가 없으므로 우리는 최종적으로 id = 0x61646d696e id를 입력해야 한다.

 

짜자잔

728x90
반응형

'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