[Web Hacking] SQL Injection : Error Based SQL Injection #3

2023. 12. 15. 15:21정보 보안/Web

 

Error Based SQL Injection

  

  Error Based SQL Injection 공격은 SQL Injection 공격 중 한 종류로서 SQL 질의문에 문제가 있을 때 출력되는 에러 메시지를 이용한다. SQL 질의문이 에러가 발생하는 원인에는 여러 가지가 존재하며 그중에서도 특정 에러를 유발하는 SQL 질의문을 사용해야 한다. 

 

  SQL 질의문에서 유발할 수 있는 에러는 두 가지가 존재한다.

 

  1. 문법 에러 : 문법 에러는 질의문 자체가 문법적으로 문제가 있어 실행 자체가 안 되는 에러다. 그렇기에 해당 에러를 발생시켜 출력되는 에러 메시지는 이용 가치가 없다.
  2. 로직 에러 : 로직 에러는 질의문으로서는 문제가 없어 실행은 되나 그 안에 문제가 되는 부분을 에러 메시지로 출력한다. 해당 에러를 유발함으로써  Error Based SQL Injection 공격을 실행할 수 있다.

  결과적으로 Error Based SQL Injection 공격을 실행하기 위해서는 SELECT 질의문이 우선적으로 실행되어야 하기 때문에 에러가 발생해도 질의문이 실행되는 로직 에러를 SQL 질의문으로 유발시켜야 한다. 

 

Error Based SQL Injection Payload

 

  Error Based SQL Injection Payload는 다음과 같은 순서로 작성해나간다. SQL 질의문의 'normaltic'은 공격대상 DB에 저장되어있는 ID 중 하나로 해당 위치에 삽입되는 문자열은 공격대상 DB에 저장되어있는 ID 중 하나여야 한다.

 

  1. normaltic' and '1'='1
  2. normaltic' and extractvalue('1', ':test') and '1'='1
  3. normaltic' and extractvalue('1', concat(0x3a,(select 'test'))) and '1'='1

1) normaltic' and '1'='1

 

  SQL Injection 하기 위한 기본적인 형태로서 공격대상의 질의문 형태에 맞춰 작성한다. 이때 해당 질의문의 결과값은 상관없이 SQL Injection이 정상 작동하는지 확인한다.

 

2) normaltic' and extractvalue('1',':test') and '1'='1

 

  공격대상이 사용하고 있는 DB에 맞춰 로직 에러를 유발하는 함수를 입력한다. 예시로는 MySQL의 extractvalue함수를 사용하였다.

* extractvalue('xml 글자', 'xml 표현식')

  extractvalue 함수는 xml로 표현된 문자 내에서 특정 문자를 나타낸다. 예를 들어 '<a>abc<b>kkk</b></a>'라는 xml 문자가 존재할 때 'abc'라는 문자열을 나타내고 싶다 하면 '/a' 으로 xml 문자 내 위치를 표현한다. 함수로 표현하면 다음과 같다.

- extractvalue('<a>abc<b>kkk</b></a>','/a') = abc
- extractvalue('<a>abc<b>kkk</b></a>','/a/b') = kkk

 

  extractvalue 함수는 로직 에러를 유발하는 함수로서 'xml 표현식' 인자에 쓰이는 특수문자(/,@ 등) 대신 다른 특수문자를 사용하게 되면 에러 메시지를 출력하게 된다. 이 방식으로 'xml 표현식' 인자에 '특수문자+select 질의문'을 입력하여 질의문이 실행되도록 한다.

 

유효한 특수문자(/) 사용 시 에러 메시지 출력 X
유효하지 않은 특수문자(:) 사용 시 에러 메시지 출력 O

 

3) normaltic' and extractvalue('1', concat(0x3a,(select 'test'))) and '1'='1

 

  SQL Injection 공격은 반복적인 작업이다. 그렇기에 Payload를 Format화 시켜 반복 작업에 들이는 수고를 덜어줘야 한다. Payload에서 계속해서 값이 바뀌는 부분은 extractvalue 함수의 'xml 표현식' 인자 위치이다. 해당 위치에서는 데이터 추출을 위한 select 질의문의 내용이 지속적으로 변경되기 때문에 concat 함수를 사용하여 특수문자(:)와 select 질의문의 위치를 구분 지어준다. 이때 특수문자는 8진수를 사용하여 표현한다. 이는 특수문자가 필터링되어 Payload가 작동하지 않음을 배제하기 위함이다.

 

완성된 Payload 적용

 

Error Based SQL Injection을 이용한 DB 추출 공격

 

  Error Based SQL Injection을 이용한 DB 추출 공격은 아래의 과정에 따라 진행한다.

 

  1. SQL Injection 작동 여부
  2. 로직 에러 유발 함수 찾기
  3. 공격 Format 만들기
  4. DB 이름 찾기
  5. TABLE 이름 찾기
  6. COLUMN 이름 찾기
  7. DATA 추출

 

[1] SQL Injection 작동 여부

 

실습용 웹 어플리케이션

 

  Error Based SQL Injection 공격에 사용될 실습용 웹 어플리케이션으로서 ID 중복 검사 기능을 가진 프로그램이다. ID를 입력하면 해당 ID가 DB에 존재하는지 확인하여 존재여부에 대한 결과를 출력한다. 

 

  SQL Injection이 작동하는지 확인하기 위해 해당 기능에 쓰인 질의문에 맞춰 항등원의 역할을 하는 질의문을 입력한다.

 

 

  입력 결과 정상적으로 작동함으로써 SQL Injection 공격이 가능한 것을 확인하였다.

  

[2] 로직 에러 유발 함수 찾기

 

  로직 에러 유발 함수로는 MySQL의 extractvalue 함수를 사용하도록 한다.

 

[3] 공격 Format 만들기

 

  Error Based SQL Injection 공격에 쓰이는 Format을 만들어 반복 작업을 하기 쉽도록 한다. 

 

normaltic' and extractvalue('1', concat(0x3a,(__'입력할 질의문'__))) and '1'='1

 

  extractvalue 함수 뒤 문장은 주석으로 처리할 수도 있으나 DB마다 쓰이는 주석이 다르기 때문에 어떤 DB가 쓰여도 Format의 형태가 변하지 않도록 and '1'='1을 입력해 준다.

 

[4] DB 이름 찾기

 

  이 단계부터는 다른 SQL Injection 공격들과 같다. 만들어진 Format에 알맞은 질의문을 입력하여 데이터를 추출한다.

 

 

  DB의 이름을 찾는 질의문은 select database()로 Format에 넣어 삽입한 결과, 'errSqli'라는 DB를 찾아냈다.

 

[5] TABLE 이름 찾기

 

 

  Error Based SQL Injection 공격으로는 출력되는 데이터가 1개뿐이기에 limit 문법을 사용하여 데이터를 하나하나 출력해봐야 한다. 그 결과, 'flagTable, member'이라는 두 테이블 이름을 찾아냈다.

 

 

  테이블 데이터가 총 두 개였으므로 3행에 존재하는 데이터는 존재하지 않는다. 그래서 3행에 존재하는 데이터를 찾으려고 했을 때는 그 결과로 false를 반환한다.

 

[6] COLUMN 이름 찾기

 

  총 두 개의 테이블을 찾았으므로 각 테이블마다 컬럼을 찾아준다.

 

1. flagTable

 

  flagTable 테이블에서는 'idx, flag'라는 두 컬럼을 찾아냈다.

 

2. member

 

  member 테이블에서는 'id, pass, email, info'라는 네 컬럼을 찾아냈다.

 

[7] DATA 추출

 

  데이터 추출에 필요한 모든 정보를 찾아냈으니 이제 본격적으로 데이터를 추출해 보도록 하자.

 

1. flagTable

 

  flagTable 테이블 내에는 하나의 데이터만 존재하였다. 그 데이터는 문제의 플레그를 나타낸다.

 

2. member

 

  member 테이블에는 id 컬럼으로 데이터를 추출해 본 결과 'normaltic, dol'라는 두 데이터만 존재하였다.