본문 바로가기

IT/웹해킹

SQL Injection -Part2 -1

ExplotiTech: System Table Fingerprinting

 

1.intro 

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

 

모의 해킹은 penetration Testing Execution Standard (PTES0에 의하면 총 일곱 가지 단계로 구성되어 있다. 

이는 체계화된 방법으로 모의 해킹을 수행할 수 있도록 돕는다. 처음 과정을 살퍼보면, 먼저 공격 대상을 지정하고, 대상의 정보를 수집한다. 이때, 대상의 정보를 수집하는 과정을 핑거프린팅이라고 한다. 정보 수집은 모의 해킹에 있어 가장 중요한 단계이다. 공격 대상이 사용하는 웹 서버와 개발 언어, 그리고 DBMS 내부 정보등을 알아내는 과정이 이에 해당한다. 

 

이번에는 SQL Injection 취약점이 발생할 때 데이터베이스의 테이블과 컬럼 등 데이터 베이스가 저장하고 있는 중요 정보를 수집하는 방법에 대해 알아볼 것이다. 

 

2.System Tablese

DBMS마다 데이터베이스의 정보를 포괄하는 시스템 테이블이 존재한다. 시스템 테이블에는 설정 및 계정정보 외에도 테이블과 컬럼 정보, 그리고 현재 실행되고 있는 쿼리의 정보 등 다양한 정보를 포함하고 있다. 

SQLI 발생한다면 시스템 테이블을활용해 테이블과 컬럼명을 쉽게 획득할 수 있따. 예를 들어 게시판 서비스에서 SELECT 구문을 통해 게시물을 조회하는 기능이 있다고 가정한다. 이때, 공격자는 게시판 관련 테이블이 아닌 시스템 테이블을 조회하는 쿼리를 작성해서 게시물을 통해 데이터베이스의 정보를 획득한다. 

 

실제로 SQLI로 원하는 정보 즉, 계정과 비밀번호를 알아내기 위해 해당 정보가 포함된 테이블과 컬럼명을 알아내기 위해 해당 정보가 포함된 테이블과 컬럼명을 알아내야 한다. 시스템 테이블을 활용한 공격은 SQLI에 있어 빠질 수 없는 가장 중요한 공격 방법 중 하나이다. 그렇다면 각 DBMS의 시스템 테이블에 대해 알아보도록 하자.

 

3.MySQL

(1) 시스템 테이블 

MySQL의 시스템 테이블에 대해 소개 한다. 가장 먼저, MySQL은 스키마와 데이터 베이스가 같으며 초기 설치시 아래와 같이 information_schema와 mysql, perfomance_schema, 그리고 sys 데이터 베이스가 있다.

mysql> show databases;

/*
+--------------------+
| Database           |
+--------------------+
| information_schema |
|Junior Faust        | # 이용자 정의 데이터베이스
| mysql              |
| performance_schema |
| sys                |
+--------------------+
*/

위 Junior Faust는 임의 생성 데이터 베이스이다. 

 

(2)스키마 정보 

TABLES 테이블을 통해 스키마의 정보를 조회할 수 있다. 아래를 살펴보면 TABLES 테이블의 내용 중 TABLE_SCHEMA에 해당하는 정보를 그룹화하여 조회한다. 쿼리의 결과로 스키마에 대한 정보가 출력된 것을 확인할 수 있다.

mysql> select TABLE_SCHEMA from information_schema.tables group by TABLE_SCHEMA;


/*
+--------------------+
| TABLE_SCHEMA       |
+--------------------+
| information_schema |
| JUNIOR FAUST       |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)
*/

(3) 테이블 정보 

TABLES 테이블을 통해 테이블의 정보를 조회할 수 있따. 아래를 살펴보면 TABLES 테이블의 내용 중 TABLE_SCHEMA와  TABLE_NAME에 해당하는 정보를 조회한다. 쿼리 결과에 스키마와 테이블 이름이 출력된 것을 확인할 수 있다.

mysql> select TABLE_SCHEMA, TABLE_NAME from information_schema.TABLES;


/*
+--------------------+----------------+
| TABLE_SCHEMA       | TABLE_NAME     |
+--------------------+----------------+
| information_schema | CHARACTER_SETS |
...
| JUNIORFAUST        | users          |
| mysql              | db             |
...
+--------------------+----------------+
292 rows in set (0.01 sec)
*/

(4)컬럼 정보 

COLUMNS 테이블을 통해 컬럼의 정보를 조회할 수 있따. 아래를 살펴보면 COLUMNS 테이블의 내용 중 TABLE_SCHEMA와 TABLE_NAME, 그리고 COLUMNS_NAME을 모두 조회한다. 쿼리 결과에 컬럼의 이름이 출력된 것을 확인할 수 있다. 공격자는 이 모든 정보를 조합해 계정 정보를 탈취할 수 있다.

mysql> select TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from information_schema.COLUMNS;

/*
+--------------------+----------------+--------------------+
| TABLE_SCHEMA       | TABLE_NAME     | COLUMN_NAME        |
+--------------------+----------------+--------------------+
| information_schema | CHARACTER_SETS | CHARACTER_SET_NAME |
...
| juniorfaust        | users          | uid                |
| juniorfaust        | users          | upw                |
...
| mysql              | db             | Db                 |
| mysql              | db             | User               |
...
+--------------------+----------------+--------------------+
3132 rows in set (0.07 sec)
*/

 (5) 실시간 실행 쿼리 정보 

PROCESSLIST 테이블을 통해 실시간으로 실행되는 쿼리를 조회할 수 있다. 아래를 보면 PROCESSLIST 테이블의 내용을 모두 출력한다. 쿼리 결과에 조회하기 위해 입력한 쿼리가 포함되어 있는 것을 확인할 수 있다.

mysql> select * from information_schema.PROCESSLIST;

/*
+-------------------------------------------------+
| info                                            |
+-------------------------------------------------+
| select info from information_schema.PROCESSLIST |
+-------------------------------------------------+
1 row in set (0.00 sec)
*/

이 외에도 아래와 같이 sys 데이터베이스의 SESSION 테이블을 통해 실행중인 계정과 함께 조회하는 방법도 있다.

mysql> select user,current_statement from sys.session;

/*
+----------------+------------------------------------------------+
| user           | current_statement                              |
+----------------+------------------------------------------------+
| root@localhost | select user,current_statement from sys.session |
+----------------+------------------------------------------------+
1 row in set (0.05 sec)
*/

(6) DBMS 계정 정보 

USER_PRIVILEGES 테이블을 통해 MySQL 서버의 계정 정보를 조회할 수 있따. 아래를 보면 USER_PRIVILEGES테이블의 GRANTEE, PRIVEILEGE_TYPE, 그리고 IS_GRANTABLE을 조회한다. 쿼리 결과에는 계정 정보와 각 권한에 대한 내용이 포함될 수 있다.

mysql> select GRANTEE,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.USER_PRIVILEGES;


/*
+-------------------------+-------------------------+--------------+
| GRANTEE                 | PRIVILEGE_TYPE          | IS_GRANTABLE |
+-------------------------+-------------------------+--------------+
| 'root'@'localhost'      | SELECT                  | YES          |
...
| 'root'@'localhost'      | SUPER                   | YES          |
...
| 'user_test'@'localhost' | USAGE                   | NO           |
+-------------------------+-------------------------+--------------+
58 rows in set (0.00 sec)
*/

이 외에도 아래와 같이 MySQL 데이터 베이스의 USER 테이블을 통해 조회하는 방법도 있다.

mysql> select User, authentication_string from mysql.user;

/*
+------------------+-------------------------------------------+
| User             | authentication_string                     |
+------------------+-------------------------------------------+
| root             | *...                                      |
| mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.session    | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| user_test        | *...                                      |
+------------------+-------------------------------------------+
4 rows in set (0.00 sec)
*/

 

4.MSSQL

(1) 시스템 테이블 

MSSQL의 시스템 테이블에 대해 소개한다. 초기 설치시 아래와 같이 master와 tempdb, model, msdb 데이터 베이스가 있다.

SELECT name FROM sys.databases

/*
name
-------
master
tempdb
model
msdb
JuniorFaust# 이용자 정의 데이터베이스 (예시)
*/

(2) 데이터 베이스 정보 

SYSDATABASES 테이블을 통해 데이터베이스의 정보를 조회할 수 있다. 아래를 살펴보면 master데이터베이스의 SYSDATABASES 내 테이블 내용 중 name에 해당하는 정보를 조회한다. 쿼리의 결과로 데이터 베이스에 대한 정보가 출력된 것을 확인할 수 있다.

SELECT name FROM master..sysdatabases;

/*
name
-------
master
tempdb
model
msdb
juniorFaust # 이용자 정의 데이터베이스 (예시)
*/

또는 아래와 같이 DB_NAME(num)형식으로 데이터 베이스의 정보를 알아낼 수 있따. 인자로 전달되는 숫자 중 0은 현재 데이터베이스를 의미한다.

SELECT DB_NAME(1);
/*
master
*/

 

(3) 테이블 정보 

SYSOBJECTS 테이블을 통해 주니어파우스트의 테이블 정보를 조회할 수 있다. 아래를 살펴보면, SYSOBJECTS 테이블 내용 중 name에 해당하는 정보를 조회하데, xtype이  'U'인 조건을 적용한다. 이떄,  xtype-'U'는 이용자 정의 테이블을 의미한다. 쿼리의 결과를 보면 이용자 정의 테이블인 "user"가 출력된 것을 확인할 수 있다.

SELECT name FROM juniorfaust..sysobjects 
WHERE xtype = 'U';
# xtype='U' 는 이용자 정의 테이블을 의미합니다.

/*
name
-------
users
*/

또 아래와 같이 INFORMATION_SCHEMA 스키마의 TABLES테이블의 table_name을 조회하는 방법도 있다.

SELECT table_name FROM dreamhack.information_schema.tables;

/*
table_name
-----------
users
*/

 

(4) 컬럼 정보 

SYSCOLUMS 테이블을 통해 컬럼의 정보를 조회할 수 있다. 아래를 보면 SYSCOLUMNS 테이블의 name을 조회한ㅡㄴㄴ데, 서브쿼리를 사용해 조건을 적용한다. 쿠러ㅣ 결과에 컬럼의 이름이 출력된 것을 확인할 수 있다.

SELECT name FROM syscolumns WHERE id = 
(SELECT id FROM sysobjects WHERE name = 'users');

/*
name
-----
uid
upw
*/

또는 아래와 같이 INFORMATION_SCHEMA와 COLUMNS 테이블을 참조해 조회하는 방법도 있다. 

SELECT table_name, column_name FROM dreamhack.information_schema.columns;

/*
table_name	column_name
-------------------------
users		uid
users		upw
*/

 

(5)DBMS 계정 정보 

master 데이터베이스의 sys,sql_logins 테이블을 통해 MSSQL 서버의 계정 정보를 조회 할 수 있다. 아래를 살펴보면 sql_logins 테이블의 name, password_hash를 조회한다.쿼리 결과에는 계정 정보와 비밀번호의 해시 정보가 포함되어있다.

SELECT name, password_hash 
FROM master.sys.sql_logins;

/*
name		password_hash
--------------------------
sa			NULL
juniorFaust	NULL
*/

이 외에도 아래와 같이 master 데이터베이스의 syslogins 테이블을 통해 조회하는 방법도 있다. 

SELECT * FROM master..syslogins;

 

5.PostgreSQL

(1) 초기 데이터 베이스 

이 시스템 테이블은 초기 설치시 아래와 같이 postgres와 template1, template0 데이터베이스가 있다.

postgres=$ select datname from pg_database;

/*
  datname  
-----------
 postgres
 template1
 template0
(3 rows)
*/

(2) 스키마(카탈로그) 정보 

 주요 정보를 담고있는 테이블을 포함한 스키마는 pg_catalog, information_schema가 있다.

postgres=$ select nspname from
pg_catalog.pg_namespace;

/*
      nspname       
--------------------
 pg_toast
 pg_temp_1
 pg_toast_temp_1
 pg_catalog
 public
 information_schema
(6 rows)
*/

(3) 테이블 정보 

information_schema를 통해 각 테이블의 정보를 조회할 수 있다. 아래를 보면 pg_catalog의 table_name과 informaiton_schema의 table_name 정보를 조회하고, 쿼리결과에 각 스키마의 테이블 이름이 출력된 것을 확인할 수 있다.

postgres=$ select table_name from 
information_schema.tables where 
table_schema='pg_catalog';

/*
           table_name
---------------------------------
pg_shadow
pg_settings
pg_database
pg_stat_activity
...
*/

postgres=# select table_name from 
information_schema.tables where 
table_schema='information_schema';

/*
              table_name
---------------------------------------
schemata
tables
columns
...
*/

(4)DBMS 계정 정보 

pg_catalog.pg_shadow 테이블을 통해 PostgreSQL서버의 게정 정보를 조회할 수 있다. 아래를 살펴보면 쿼리 결과에는 계정 정보와 비밀번호의 예시 정보가 포함되어 있다.

postgres=$ select usename, passwd from
pg_catalog.pg_shadow;

/*
 usename  |               passwd
----------+-------------------------------------
 postgres | md5df6802cb10f4000bf81de27261c1155f
(1 row)
*/

(5) DBMS 설정 정보 

pg_catalog.pg_setting 테이블을 통해 PostgreSQL 서버의 설정 정보를 조회할 수 있따. 

아래를 살펴보면 쿼리결과에 설정 정보가 포함되어 있다.

postgres=$ select name, setting from
pg_catalog.pg_settings;

/*
                  name                  |                 setting
----------------------------------------+------------------------------------------
 allow_system_table_mods                | off
 application_name                       | psql
 ...
*/

(6) 실시간 실행 쿼리 확인 

pg_catalog.pg_stat_activity 테이블을 통해 실시간으로 실행되는 쿼리를 조회할 수 있다. 아래를 보면 쿼리 결과에 조회하기 위해 입력한 쿼리가 포함되어 있는 것을 확인할 수 있다.

postgres=$ select usename, query from 
pg_catalog.pg_stat_activity;

/*
 usename  |                          query                          
----------+---------------------------------------------------------
 postgres | select usename, query from pg_catalog.pg_stat_activity;
(1 row)
*/

(7) 테이블 정보 

information_schema,tables 테이블을 통해 데이터베이스의 스키마 및 테이블 정보등을 조회할 수 있다. 아래를 살펴보면 information_schema.tables 테이블을 통해 table_name, table_schema를 조회한 결과를 확인할 수 있다.

postgres=$ select table_schema, table_name from
information_schema.tables;

/*
    table_schema    |              table_name
--------------------+---------------------------------------
 pg_catalog         | pg_statistic
...
 information_schem  | information_schema_catalog_name
...
*/

(8) 컬럼 정보 

information_schema.columns 테이블을 통해 컬럼의 정보를 조회할 수 있다. 아래를 살펴보면 information_schema.columns 테이블의 table_schema, table_name, columns_name을 조회한 결과를 확인할 수 있다.

postgres=$ select table_schema, table_name, column_name from
information_schema.columns;

/*
    table_schema    |      table_name         |    column_name
--------------------+-------------------------+------------------
 pg_catalog         | pg_stat_user_indexes    | relid
...
 information_schema | view_routine_usage      | specific_name
...
*/

 

6.Oracle

(1) 데이터 베이스 정보

all_tables는 현재 사용자가 접근할 수 있는 테이블의 집합이다.

SELECT DISTINCT owner FROM all_tables
SELECT owner, table_name FROM
all_tables

(2) 컬럼 정보 

all_tab_columns를 통해 특정 테이블의 컬럼 정보를 확인할 수 있다. 아래와 같이 where 구문을 통해 table_name이 user 인 테이블의 컬럼 이름을 조회할 수 있다.

SELECT column_name FROM all_tab_columns WHERE table_name = 'users'

(3)DBMS 계정 정보 

all-users 테이블을 통해 DBMS 계정 정보를 획득할 수 있다.

SELECT * FROM all_users

 

7,SQLite

(1)시스템 테이블

SQLite에서는 sqlite_mater 시스템 테이블을 이용할 수 있다. 해당 테이블에는 생성되어 있는 테이블 등의 정보와 sql을 획득할 수 있따. 아래를 보면 sqlite_mater 테이블을 조회한 결과이다.

sqlite> .header on
-- 콘솔에서 실행 시 컬럼 헤더를 출력하기 위해 설정합니다.

sqlite> select * from sqlite_master;

/*
type|name|tbl_name|rootpage|sql
table|users|users|2|CREATE TABLE users (uid text, upw text)
*/

 

8.Review

한번에 너무 많은 정보가 들어온것 같다. 정보의 양이 많다보니 머리에 잘 들어오지 않고, 구조화 되지 않는다. 아마도 복습이 필요한 시점일 것 같다.

반응형

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

오늘의 공부  (0) 2023.07.20
오늘의 공부  (0) 2023.07.19
SQL injection -4  (2) 2023.01.25
SQL Injection -3  (0) 2023.01.24
SQL injection-2  (0) 2023.01.24