본문 바로가기

챌린지/los.rubiya.kr

Lord of SQLInjection - troll

8번째 문제인 troll이다.

<?php  
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/\'/i', $_GET[id])) exit("No Hack ~_~");
  if(preg_match("/admin/", $_GET[id])) exit("HeHe");
  $query = "select id from prob_troll where id='{$_GET[id]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['id'] == 'admin') solve("troll");
  highlight_file(__FILE__);
?>

이번 문제에서는 "admin"이란 문자열을 필터링하고 있다. 이 문제를 해결하려면 admin 계정의 id가 조회되어야 하는데 문자열이 필터링되고 있으니 어떻게 할 수 있을까? 우선 문자열을 16진수로 변환하여 우회하는 방법을 시도해 보았다.

echo "Hello '{\x31\x32\x33}'\n"; // Hello '{123}'
echo "Hello '{\x61\x64\x6d\x69\x6e}'\n"; // Hello '{admin}'

'\x' 접두사와 16진수로 변환된 문자의 아스키 값을 입력함으로써 php가 이를 다시 아스키 문자로 해석하도록 지시할 수 있다. "admin" 문자열은 각각 \x61, \x64, \x6d, \x69, \x6e로 변환되기 때문에 이를 id 파라미터에 전달했는데 출력은 다음과 같았다.

아무래도 코드에서 $_GET[id]처럼 전달해주기 때문에 따옴표에 갇혀서 문자열이 파싱되지 않고 그대로 입력되는 것 같다. PHP 문자열 표현 시 single quote/double quote 차이 – friday's blog (fun25.co.kr)

 

PHP 문자열 표현 시 single quote/double quote 차이

PHP에서 문자열 표현 시에 single quote(‘) 혹은 double quote(“) 를 사용합니다. 이 둘은 일반적인 경우에서 동일한 결과를 출력하게 됩니다.

friday.fun25.co.kr

그렇다면 php 구문에서 admin 문자열로 변환되지 않고 mysql 쿼리를 실행할 때 문자열로 변환시킬 수 있는 방법은 없을까? mysql에서 문자열 생성 관련 함수를 찾아봤더니 concat() 함수를 발견할 수 있었다.

문자열을 이어붙여주는 함수기 때문에 이를 활용해서 "admin"을 "admi"과 "n"을 이어붙여서 구현할 수 있지 않을까? 시도해봤지만 역시 그대로 문자열로 치환될 뿐이었다.

결국 쿼리 내의 {$_GET[id]} 부분을 감싸고 있는 따옴표 때문에 내부 문자열이 파싱되지 않고 그대로 쿼리로 전달되는 것 같은데 그렇다면 위에서 시도했던 16진수나 concat() 함수도 그대로 전달되어 id가 "\x61\x64\x6d\x69\x6e"이거나 "concat('admi', 'n')"인 데이터를 찾으려 했으니 쿼리가 실패하는 것은 당연할것이다. 그렇다면 어떻게 단순 문자열만 입력해서 이 "admin" 필터링을 우회할 수 있을까? 이는 옛날에 풀었던 bughela - login filtering을 되짚어보면 간단한 문제였다.

 

bughela - login filtering

wargame.kr의 네 번째 문제인 login filtering이다. 차단된 계정에 로그인하는 것이 목적이다. Start 버튼을 눌러 문제를 확인해보면 다음과 같은 간단한 로그인 폼이 나타난다. 따로 자바스크립트로 필

haruhiism.tistory.com

위 문제를 풀 수 있었던 주요 단서는 mysql에서 대소문자를 구문하지 않는다는 것이었다.

위의 쿼리처럼 'ADMIN'과 'admin' 문자열이 같은 지 판단하여 'same'을 출력하도록 했을 때 그대로 출력되는 것을 볼 수 있는것처럼 문제에서 실행하는 쿼리도 id 파라미터에 'admin'을 비교하든 'ADMIN'을 비교하든 admin 계정의 아이디를 참조하기 때문에 대소문자를 신경 쓸 필요가 없었다.

 

그렇지만 "admin" 문자열이 필터링됐는데 "ADMIN"도 필터링되지 않을까? 다행히 php의 preg_match() 함수는 정규표현식에 따라 문자열을 검색하기 때문에 대소문자를 구문하는 정규표현식 특성상 "ADMIN"은 "admin"으로 인식되지 않아 필터링을 통과할 수 있었다.

그래서 id 파라미터에 "ADMIN"이나 "ADMIn"처럼 소문자 "admin"이 아닌 문자열을 입력해주면 어렵지 않게 클리어할 수 있다.

 

 

이는 지난 문제처럼 mysql에서 대소문자를 구문하지 않는다는 특성을 활용한 문제같다.

'챌린지 > los.rubiya.kr' 카테고리의 다른 글

Lord of SQLInjection - skeleton  (0) 2020.12.30
Lord of SQLInjection - vampire  (0) 2020.12.30
Lord of SQLInjection - orge  (0) 2020.12.27
Lord of SQLInjection - darkelf  (0) 2020.12.27
Lord of SQLInjection - wolfman  (0) 2020.12.22