문제 풀이

<?php
  include "./config.php";
  login_chk();
  $db = mongodb_connect();
  $query = array(
    "id" => $_GET['id'],
    "pw" => $_GET['pw']
  );
  echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
  $result = mongodb_fetch_array($db->prob_cerberus->find($query));
  if($result['id']) echo "<h2>Hello {$result['id']}</h2>";
  if($result['id'] === "admin") solve("cerberus");
  highlight_file(__FILE__);
?>

공격 백터

  • id
  • pw

코드 설명

$db = mongodb_connect();

DB가 mongodb이므로 NoSQLi 문제로 보인다.

 

$query = array(
    "id" => $_GET['id'],
    "pw" => $_GET['pw']
);
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_cerberus->find($query));

공격 백터 id와 pw는 "id" => "공격 백터 id", "pw" => "공격 백터 pw"에 들어가서 Json 형식으로 인코딩된다.
인코딩된 값은 {"id":"공격 백터 id", "pw":"공격 백터 pw"}이며, MongoDB에 전달이 된다.

 

if($result['id']) echo "<h2>Hello {$result['id']}</h2>";
if($result['id'] === "admin") solve("cerberus");

해당 쿼리의 id 반환값이 있다면 Hello id 반환값이 화면에 출력된다.
또한 그 id 반환값이 admin이라면 문제가 클리어 된다.


문제 풀이

아래의 사이트를 참고하여 NoSQLi에 대해 이해를 하였다.

참고 사이트
NoSQL Injection :: skyhell
PayloadsAllTheThings/NoSQL Injection at master · swisskyrepo/PayloadsAllTheThings · GitHub

 

나는 일단 쿼리문에 대해 생각하였다.
현재 문제의 쿼리문을 MySQL 쿼리문으로 이해하자면, SELECT * FROM prob_cerberus WHERE id='공격 백터 id' and pw='공격 백터 pw'로 된다.


MySQL의 경우 주석 처리를 이용하여 id='공격 백터 id' and pw='' or 1=1--'로 할 수 있지만, MongoDB의 쿼리문은 MySQL와 다르기 때문에 MongoDB의 쿼리문에 적합한 방법을 찾아야 한다.

 

MongoDB의 쿼리문 중 $ne(not equal, !=)를 이용하면, id='admin' and pw!='1'으로 만들 수 있다.
그럼 admin의 pw는 1이 아니니깐 True가 되어 True and True로 admin의 정보를 반환하게 된다.

 

?id=admin&pw[$ne]=1

아주 간단하게 문제 풀이를 하였다.
아마 이번 문제는 NoSQL에 대해서 알아보라는 문제로 추측된다.

복사했습니다!