본문 바로가기

IT/웹해킹

오늘의 공부

오늘의 공부

-DBSM Fingerprinting-


1.INTRO

 범죄현장에 있어서 증거를 수집하고 분석하는 것은 수사의 핵심이다.  범죄 현장에서 발견할 수 있는 증거 중 하나인 지문은 사람이 가지고 잇는 고유한 정보로 수사를 해결하기 위한 열쇠이다. 지문은 영단어로 핑거프린트 (fingerprint)이며 해당 단어는 모의 해킹에서도 등장한다. 

 

모의 해킹은 * Penetraion Testing Execution Standard(PTES)에 의해 총 일곱 가지 단계로 구성되어 있다. 이는 체계화된 방법으로 모의 해킹을 수행할 수 있도록 돕는다. 처음 과정을 살펴보면 먼저 공격 대상을 지정하고 대상의 정보를 수집한다. 이때, 대상의 정보를 수집하는 과정을 핑거 프린팅이라고 한다. 정보 수집은 모의 해킹에 있어 가장 중요한 단계 중 하나이다. 공격 대상이 사용하는 웹 서버와 개발 언어, 그리고 DBMS 등을 알아내는 과정이 이에 해당한다. 소프트웨어마다 서로 다른 기능과 특징이 있기 때문에 이러한 정보를 수집한다면 공격 지점을 쉽게 도출해 낼 수 있을 뿐만 아닌, 알려진 취약점을 사용할 수 있다.

 

* Penetraion Testing Execution Standard(PTES)에 의해 총 일곱 가지 단계 :

[1. 사전계약 2. 정보수집, 3. 위협 모델링, 4. 취약점 분석, 5. 침투 수행, 6. 포스트 익스플로잇, 7. 보고서 작성]


 

2.DBMS FingerPrinting

DBSM은 용도와 목적에 따라 MYSQL, MSSQL, Oracle, SQLite 등을 선택해 사용할 수 있다. 이들은 모두 비슷한 쿼리의 형태를 띠지만, 각 시스템 별로 제공하는 함수가 다르다. SQL Injection 취약점을 발견하면 제일 먼저 알아내야할 정보는 DBMS의 종류와 버전이다. 이를 알아낸다면 해당 DBMS에서 제공하는 기능을 통해 보다 수월한 공격을 수행할 수 있다. 

 

SQL Injection이 발생한느 형태는 다양하기 때문에 상황에 따라 DBMS  w정보를 알아내는 방법이 달라질 수 있다. 그렇다면 아래에서 각가의 상황별로 DBMS 정보를 수집하는 방법에 대해 간략히 소개한다. 

 

ⅰ) 쿼리 실행 결과 출력 

 

SELECT @@version
SELECT version()

애플리케이션에서 삽입한 쿼리의 실행 결과를 출력한다면 DBSM에서 지원하는 환경 변수의 값을 이용하는 방법이 있다. 위 예시는 각각 DBSM에서 제공하는 환경 변수와 함수를 사용해 버전을 확인하는 쿼리문이다. 

 

ⅱ) 에러 메시지 출력

select 1 union select 1, 2;
# MY SQL => ERROR 1222(21000): The used 
SELECT statements have a different 
number of colums
(select * from not_exists_table)
#SQLite => Error: no such table:
not_exists_table

삽입한 쿼리를 어플에서 실행하면서 에러 메시지를 출력하는 경우 사용하는 DBMS를 알아낼 수 있다. 위 예시는 잘못된 쿼리를 삽입했을 때 에러 메시지가 출력된 모습이다. 에러 메시지를 살펴보면 각각 MYSQL, SQLite의 DBMS정보가 노출된 것을 확인할 수 있다. 

 

ⅲ) 참 또는 거짓 출력

mid(@@version, 1,1)='5';
substr(version(), 1, 1)='p';

어플에서 쿼리 실행 겨로가가 아닌 참과 거짓 여부만을 출력할 경우 Blind SQL Injection 공격으로 사용 중인 DBMS를 알아낼 수 있다. 위 예시는 Blind SQL Injection 기법을 사용한 쿼리문의 일부로, 이와 같이 버전 환경 변수 및 함수를 통해 가져온 버전을 한 바이트씩 비교해서 알아낼 수 있다. 

(시간 진짜 오래 걸릴 듯요,,,)

 

ⅳ)예외 상황

sleep(10)
pg_sleep(10)

어플에서 쿼리와 관련된 어떠한 결과도 출력하지 않는 경우 시간 지연 함수를 사용하는 방법이 있다. 

위 예시는 시간 지연 함수들로 일부 DBMS에서는 해당 함수가 존재하지 않기 때문에 시스템에 맞는 시간 지연 함수를 사용한다. 


3.MYSQL

MYSQL DBMS를 사용하는 환경에서 데이터 베이스 정보를 수집하는 방법에 대해 소개한다. 

ⅰ) 쿼리 실행 결과 출력 

mysql select @@version; #select 
version();

+---------------------------------+
|@@version                        |
+---------------------------------+
|5.7.29-0ubuntu0.16.04.1         |
+---------------------------------+
1 row in set ( 0.00sec)

 

MYSQL에서 version 환경 변수 또는 version 함수를 사용해 MySQL DBMS의 버전과 운영 체제 정보를 알아낸 모습이다. 

 

ⅱ) 에러 메시지 출력

mysql> select 1 union select 1, 2;
ERROR 1222 (21000): The used SELECT 
statements have a different number of
columns

위 예시는 에러 메시지에 포함된 키워드로 DBMS 정보를 알아낸 모습이다. 1222 에러 코드는 MySQL에서 명시한 코드로, 이를 통해 DBMS가 MySQL임을 유추할 수 있다. 

 

ⅲ) 참 또는 거짓 출력

# @@version => '5.7.29-
0ubuntu0.16.04.', mid(@@version, 1, 1)
=> '5'
mysql> select mid(@@version, 1, 1)='5';
+------------------------+
| mid(@@version,1,1)='5' |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)
mysql> select mid(@@version, 1, 1)='6';
+------------------------+
| mid(@@version,1,1)='6' |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.00 sec)

위 예시는 version 환경 변수의 값이, "5.7.29-0 ubuntu0.16.04" 일 때 Blind SQL Injection로 한 글자씩 알아내는 모습이다. 

표를 살펴보면 MySQL에서 제공하는 mid 함수를 통해 version 환경 변수의 첫 번쨰 글자가 '5'인지 확인한다. 이때, 쿼리 결과로 참을 반환하므로, 첫 글자가 '5'임을 알 수 있다. 

 

ⅳ) 예외 상황

mysql> select mid(@@version, 1, 1)='6' 
and sleep(2);
+---------------------------------------+
| mid(@@version, 1, 1)='6' and sleep(2) |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> select mid(@@version, 1, 1)='5' 
and sleep(2);
+---------------------------------------+
| mid(@@version, 1, 1)='5' and sleep(2) |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (2.00 sec)

위는 어플에서 쿼리 실행 결과를 반환하지 않을 때 Sleep함수를 사용하여 시간 지연 발생 여부로 알아내는 모습이다. 표를 살펴보면 version의 첫 글자가 '6'이라면 and 연산자 뒤에 위치하는 식인 sleep(2)를 실행한다. 그러나 버전의 첫 글자가 '6'이 아니기 때문에 시간 지연이 발생하지 않는다. 

반면 두번째 예시는 참이기 때문에 두 식이 모두 실행되어 2초의 지연시간이 발생했다.


4.PostgreSQL

PostgreSQL를 사용하는 환경에서 데이터 베이스 정보를 수집하는 방법에 대해 소개한다. 

ⅰ) 쿼리 실행 결과 출력 

postgres=$ selcet version();
version
-------
 postgreSQL 12. 2(Debian 12.2-
 2.pgdg101) on x86_64 pc linux-gnu,
 compiled by gcc (Debian 8.3.0-6) 8.3.0,
 64-bit
 (1 row)

postgreSQL에서 version 함수를 사용해 DBMS의 상세 정보와 운영 체제 정보를 알아낸 모습

 

ⅱ) 에러 메시지 출력

postgres=$ select 1 union select 1, 2;
ERROR:  each UNION query must have the 
same number of columns
LINE 1: select 1 union select 1, 2;

에러 메시지에 포함된 키워드로 DBMS 정보를 알아낸 모습입니다. 에러 메시지를 검색해 보면 PostgreSQL에서 출력하는 문자열임을 확인할 수 있다.

 

ⅲ) 참 또는 거짓 출력

 /* version() => 'PostgreSQL ...',
substr(version(), 1, 1) => 'P' */
postgres=$ select substr(version(), 1, 
1)='P';
 ?column?
----------
 t
(1 row)
postgres=# select substr(version(), 1,
1)='Q';
 ?column?
----------
 f
(1 row)

version함수로 가져온 버전이 "PostgreSQL"로 시작할 때 Blind SQLI로 한 글자씩 알아내는 모습이다. 표를 보면 PostgreSQL에서 제공하는 substr 함수를 통해 version 함수로 불러온 값의 첫 글자가 'P'임을 확인하고, 이때 쿼리의 결과가 't'즉, 참임을 반환하므로, 첫 글자가 'p'임을 알 수 있다. 

 

ⅳ)예외 상황

postgres=$ select substr(version(), 1,
1)='P' and pg_sleep(10);
 pg_sleep
----------
(1 row)

위 예시는 쿼리 실행 결과를 반환하지 않을 때 pg_sleep함수를 사용해 시간 지연 발생 여부로 알아내는 모습이다. 표를 살펴보면 version 함수를 통해 가져온 값의 첫 글자가 'P'라면 and 연산자 뒤에 위치하는 식인 pg_sleep(10)을 실행한다.


5.MSSQL

ⅰ) 쿼리 실행 결과 출력 

> select @@version;
--------------------------------------
---------------------------------------
---------------------------------------
---------------------------------------
---------------------------------------
---------------------------------------
---------------------------------------
----------------------------
Microsoft SQL Server 2017 (RTM-CU13) 
(KB4466404) - 14.0.3048.4 (X64)
	Nov 30 2018 12:57:58
	Copyright (C) 2017 Microsoft 
Corporation
	Developer Edition (64-bit) on Linux (Ubuntu 16.04.5 LTS)
(1 rows affected)

MSSQL에서 version 환경 번수를 통해 DBMS의 버전과 운영 체제 정보를 알아낸 모습. 



ⅱ) 에러 메시지 출력

> select 1 union select 1, 2;
Msg 205, Level 16, State 1, Server 
e2cb36ec2593, Line 1
All queries combined using a UNION, 
INTERSECT or EXCEPT operator must have
an equal number of expressions in their 
target lists.asdf

위의 예시는 에러 메시지에 포함된 키워드로 DBMS 정보를 알아낸 모습이다. 

에러 메시지를 검색하면 MSSQL에서 출력하는 문자열임을 확인할 수 있다. 


ⅲ) 참 또는 거짓 출력

-- @@version => 'Microsoft SQL 
Server...', substring(@@version, 1, 1)
=> 'M'
> select 1 from test where 
substring(@@version, 1, 1)='M';
-----------
          1
(1 rows affected)
1> select 1 from test where 
substring(@@version, 1, 1)='N';
2> go
-----------
(0 rows affected)

위의 예시는 version 환경 변수의 값이 "Microsoft SQL Server"로 시작할 때 Blind SQLI로 한 글자씩 알아내는 모습이다. 표를 살펴보면, MSSQL에서 제공하는 substring 함수를 통해 version 환경 변수의 첫 번째 글자가 "M"인지 확인한다.

이때, 쿼리의 결과로 참을 반환하므로,  첫 글자가 "M"임을 알 수 있다.


ⅳ) 예외 상황

select 1 where substring(@@version, 1, 
1)='M' and waitfor delay '0:0:5';

위 예시는 어플에서 쿼리 실행 결과를 반환하지 않을 때 waitfor delay를 사용하여 시간 지연 발생 여부로 알아내는 모습이다. 위를 살펴보면 version의 첫 글자가 "M"이라면 and 연산자 뒤에 위치하는 식인 waitfor delay '0:0:5'를 실행한다. 


SQLite

ⅰ) 쿼리 실행 결과 출력 

sqlite> select sqlite_version();
3.11.0

위는 SQLite에서 sqlite_version() 함수를 통해 DBMS 버전을 알아낸 모습이다

 (이게 가장 간단해 보인다)

ⅱ) 에러 메시지 출력

sqlite> select 1 union select 1, 2;
Error: SELECTs to the left and right of
UNION do not have the same number of
result columns

위 예시는 에러메시지에 포함된 키워드로 DBMS 정보를 알아낸 모습이다. 에러 메시지를 검색해 보면 SQLite에서 출력하는 문자열임을 확인할 수 있다.

 

ⅲ) 참 또는 거짓 출력

-- sqlite_version() => '3.11.0', 
substr(sqlite_version(), 1, 1) => '3'
sqlite> select substr(sqlite_version(),
1, 1)='3';
1
sqlite> select substr(sqlite_version(),
1, 1)='4';
0

위 예시는 sqlite_version함수로 가져온 버전이 "3.11.0" 일 때, Blind SQLI로 한 글자씩 알아내는 모습이다. 표를 살펴보면 SQLite에서 제공하는 substr 함수를 통해 버전의 첫 글자가 '3'인지 확인한다. 이때, 쿼리의 결과로 참을 반환하므로, 첫 글자가 '3'임을 알 수 있다. 


ⅳ) 예외 상황

select case when 
substr(sqlite_version(), 1,1)=>'3' then
LIKE('ABCDEFG',UPPER(HEX(RANDOMLOB(3000
00000/2)))) else 1=1 end;

위 예시는 어플에서 쿼리 실행 결과를 반환하지 않을 때 LIKE('ABCEDFG', UPPER(HEX(RANDOMLOB(300000000/2))))를 통해 시간 지연 발생 여부로 알아내는 모습이다. 

SQLite의 조건식을 통해 버전의 첫 글자가 '3'이라면, 시간 지연을 발생시키는 코드를 실행시키고 아니라면 1=1 식을 실행한다.


OUTRO

이번 강의는 SQL Injection을 통해 DBMS 또는 운영 체제의 정보를 알아낸 방법에 소개하였다. 

이는 다른 공격을 시도하는 데에 있어서도 중요하게 작용하며, 공격 대상이 정기적으로 DBMS 및 운영 체제를 업데이트하지 않는다면 이미 알려진 취약점을 통해 서버를 쉽게 장악할 수 있다. 또한 DBMS별로 제공하는 유용한 함수 및 문법을 통해 더 많은 데이터베이스의 정보를 획득할 수 있다. 강의에서 다룬 내용 외에도 각각의 DBMS는 운용되는 포트 번호가 다르기에 포트 스캐닝 기법으로 알아낼 수도 있다.!

 

 

사실, 요 근래 학생회 일과, 기말고사, 방학하자마자하 시작 된 자격증 강의 수강, 아르바이트 등으로 인해서 굉장히 바쁘게 지내 오랜만에 다시 공부를 하려니 여전히 쿼리 작성 방법은 막막하다. 다시 꾸준히 공부를 해야 할 것 같다고 스스로를 한번 채찍질해 본다

 

 

본 포스터의 내용은 DREAMHACK 사이트에 내용을 기반으로 작성하였으며, 모든 저작권은 DREAMHACK에 있고, 상업적 이용을 하지 않음을 밝힙니다. 

반응형

'IT > 웹해킹' 카테고리의 다른 글

오늘의 공부: Bypass WAT  (0) 2023.07.21
오늘의 공부  (0) 2023.07.20
SQL Injection -Part2 -1  (0) 2023.01.26
SQL injection -4  (2) 2023.01.25
SQL Injection -3  (0) 2023.01.24