Self-Improvement

Time 기반 SQLi (DB 내장함수, Heavy Query) 본문

SQLi

Time 기반 SQLi (DB 내장함수, Heavy Query)

JoGeun 2020. 4. 23. 13:45

Time 기반 SQLi는 조건과 무관하게 동일한 응답이 회신될때 사용이 가능하여 Time을 이용하여 응답을 분석한다.

방법으로는 DB 내장함수와 과도한 연산이 수반되는 SQL 쿼리문을 주입하여 시간을 지연시키는 방법이 있다.

 

DB 내장함수

시간 지연 내장함수는 DB별로 상이하며 현실적으로 사용이 가능한 데이터베이스는 MySQL, MSSQL라고 할 수있다.

Oracle은 PL/SQL 환경에서만 사용이 가능하기 때문에 SQLi 방식으로는 사용이 불가능하다.

MySQL SLEEP()
MSSQL WAITFOR DELAY 'hh:mm:ss'
WAITFOR TIME 'hh:mm:ss'
Oracle DMBS_LOCK.SLEEP()

 

MySQL

가장 먼저 MySQL 데이터베이스의 SLEEP() 함수를 사용해본다.

수행 결과는 정상일 경우 "0"이 리턴되며 리턴 값이 "null"이거나 음수이면 수행결과 경고 또는 에러가 발생한 경우이다.

select sleep(5)

select count(*) from Products where ProductID=1 and sleep(5)

 

여기서 주의해야할 사항이 2가지 존재한다. 첫번째는 아래의 쿼리를 수행하면 5초가 아닌 10초의 시간이 소요된다. 원인은 where절의 ProductID가 1과 2인 것을 2번연산으로 인해 발생하는 것이다. 결론적으로 SLEEP 함수를 사용할 때는 쿼리 구문의 수행결과 연산에 사용된 레코드 수를 고려해서 시간 값을 정해야 한다.

select count(*) from Products where ProductID in (1,2) and sleep(5)

두번째는 OR연산을 수행할 때이다. and 연산과는 다르게 OR 연산자는 다른 모든 레코드의 연산에 영향을 미친다.

select count(*) from Employees where EmployeeID=1 or sleep(5)

 

실제로 사용하기 위해서는 다음과 같이 마이크로 초 단위에서부터 시작하는 것이 바람직하며 점차 늘려가며 응답 지연이 발생하는지 확인해야 한다.

select count(*) from Employees where EmployeeID=1 or sleep(0.01)

 

MSSQL

MSSQL 데이터베이스는 시간 지연에 WAITFOR DELAY 또는 WAITFOR TIME 구문을 사용하면 되지만 시간 지연 목적이라면 전자인 DELEY 명령을 사용하는게 바람직하다

WAITFOR DELAY '00:00:05'

 

MySQL 데이터베이스와는 달리 지연 시간은 칼럼의 레코드 수와 무관하며 쿼리 구문의 맨 마지막에 위치해야 한다.

SQL > select count(*) from products where productid=1 waitfor delay '00:00:05'

실행 완료. Time used: 5014 Millis
SQL > select count(*) from products where productid=1 or 1=1 waitfor delay '00:00:05'

실행 완료. Time used: 5010 Millis
SQL > select count(*) from products where productid=1 waitfor delay '00:00:05' or 1=1

키워드 'or' 근처의 구문이 잘못되었습니다.
SQL > select count(*) from products where productid=1 waitfor delay '00:00:05' and 1=1

키워드 'and' 근처의 구문이 잘못되었습니다.

 

ORACLE

Oracle 데이터베이스는 PL/SQL 에서만 시간 지연 내장 함수 사용이 가능하여 SQL 인젝션 방식으로 사용이 불가능하다.

PL/SQL이란 SQL 언어를 확장하기 위해 사용하는 컴퓨터 프로그래밍 언어이다.

PL/SQL 문을 이용한 시간 지연 내장함수는 쿼리박스에서는 불가능하며 SQLPlus에서 이용이 가능하다

#sqlplus "/as sysdba"
SQL > EXECUTE DBMS_LOCK.SLEEP(5);

 

Heavy Query

시간 지연 내장함수는 MySQL을 제외하고는 적합한 조건에서만 사용이 가능하다는 제약이 있다. 그러함으로 과도한 연산 쿼리를 주입하여 시간을 지연시키는 방식이 존재한다.

이 방식은 시간 지연 내장함수에 비해서 데이터베이스에 종속되지 않고 유연하게 사용이 가능하지만 DBMS의 자원을 과도하게 사용한다는 점을 유의해야 한다.

 

과도한 연산 쿼리는 데이터베이스에서 접근이 가능한 스키마 객체 등 알려진 테이블을 셀프 조인방식으로 동일한 객체를 여러번 조인하는 것이다.

MySQL select count(*) from information_schema.tables tab1, information_schema.tables tab2, information_schema.tables tab3
MSSQL select count(*) from sysobjects sys1, sysobjects sys2, sysobjects sys3, sysobjects sys4
Oracle select count(*) from col c1, colc2, colc3, colc4

셀프 조인 횟수가 많아 질 수록 시간 소요가 급격하게 증가함으로 주의해야 하며 미리 테스트로 하나씩 증가해보면서 몇초가 지연되는지 필수로 확인을 해야한다.