SQL Injection
사용자의 입력값을 제대로 검증하지 않고 SQL 쿼리에 사용해 공격자가 악의적인 구문을 주입·실행할 수 있는 취약점
이를 통해 로그인 우회, 데이터 유출, 변조 등 다양한 공격이 가능
종류
1. 클래식
- 예시 : 로그인
- 입력값 :
admin' --
- 입력값 :
SELECT * FROM users WHERE uid = '[입력값]' AND upw = '[입력값]';
SELECT * FROM users WHERE uid = 'admin' --' AND upw = 'Dummy';
2. Union
- 두 개 이상의 SELECT문에 대한 결과를 하나로 묶어 데이터베이스에서 추출
- 조건
- 이전 SELECT 구문과 UNION 사용한 구문의 column 개수가 같아야 함
- 이전 SELECT 구문과 UNION 사용한 구문의 column type이 같아야 함
- 예시 : 검색
- 입력값 :
화전동' UNION SELECT NULL, NULL, TABLE_NAME FROM ALL_TABLES --
- 입력값 :
SELECT zip, region, address FROM locations WHERE region = '[입력값]';
SELECT zip, region, address FROM locations WHERE region = '화전동' UNION SELECT NULL, NULL, TABLE_NAME FROM ALL_TABLES --';
3. Blind
- 참/ 거짓 쿼리문 삽입 시 반환 값을 통해 데이터를 추출
- 종류
- Boolean-based : 쿼리 실행 결과가 참/거짓일 때 응답의 차이를 이용해 데이터 추출
- Time-based : 쿼리 실행 결과와 상관없이 특정 조건일 때 의도적으로 SLEEP시켜, 서버 응답 시간 차이를 통해 데이터 추출
- 예시 : 검색
- Boolean :
notice' AND SUBSTRING((SELECT upw FROM users WHERE uid='admin'), 1, 1) = 'a' -- - Time :
notice' AND IF(SUBSTRING((SELECT upw FROM users WHERE uid='admin'), 1, 1) = 'a', SLEEP(5), 0) --
- Boolean :
SELECT * FROM board WHERE title = '[입력값]';
SELECT * FROM board WHERE title = 'notice' AND SUBSTRING((SELECT upw FROM users WHERE uid='admin'), 1, 1) = 'a' --';
SELECT * FROM board WHERE title = 'notice' AND IF(SUBSTRING((SELECT upw FROM users WHERE uid='admin'), 1, 1) = 'a', SLEEP(5), 0) --';
4. Error
- 데이터베이스의 문법에 맞지 않은 쿼리문 입력 시 반환되는 에러 정보를 기반으로 공격
보안 대책
- Prepared Statement : SQL 구문과 입력 데이터를 분리하여, 사용자의 입력값이 SQL 문법에 영향을 주지 못하도록 방어
// Java 예시
String sql = "SELECT * FROM users WHERE uid = ? AND upw = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, uid); // 사용자 입력값 바인딩
pstmt.setString(2, upw);
ResultSet rs = pstmt.executeQuery();
- Filtering
- White List : 허용된 값 또는 패턴만 입력받도록 제한하여 예상치 못한 입력값을 원천 차단
- Black List : 공격 기법에 사용되는 예약어 및 특수 문자들을 감지 또는 제거하여 위험 가능성 낮춤
# Python 예시 (지역 입력값 검증)
VALID_REGIONS = {"Seoul", "Busan", "Gwangju"}
user_input = request.args.get("region")
if user_input not in VALID_REGIONS:
raise ValueError("허용되지 않는 값입니다.")
query = "SELECT zip, region, address FROM locations WHERE region = %s"
cursor.execute(query, (user_input,))
# Python 예시 (블랙리스트 문자 제거)
BLACKLIST = ['--', ';', '/*', '*/', '@@', '@']
user_input = input_value
for keyword in BLACKLIST:
user_input = user_input.replace(keyword, '')
query = "SELECT * FROM board WHERE title = %s"
cursor.execute(query, (user_input,))
- 에러 노출 제한 : SQL 실행 중 발생하는 상세 에러 메세지를 클라이언트에 직접 노출하지 않도록 처리
더보기
[점검 tip]
1. SQL 쿼리가 작동되는 기능 찾기 (검색, 정렬, 날짜 등)
2. 구조가 어떻게 되어 있을지 모르는 상황에서 작동되는 SQL 쿼리문 구조를 생각하기
3. 생각한 SQL 가설에 맞는 입력값 주입시도
'Study > Web Hacking' 카테고리의 다른 글
| [Web] Log4Shell 취약점 (0) | 2025.12.07 |
|---|---|
| [Web] 불충분한 인증? 인가? (0) | 2025.11.15 |
| [Web] Command Injection과 대응법 (0) | 2025.10.13 |
| [Web] 파일 취약점 (0) | 2025.10.12 |
| [Web] 쿠키? 세션? 토큰? (0) | 2025.10.09 |