Learning
토픽 196 / 210·애플리케이션 보안

SQL Injection

SQL Injection

사용자 입력값에 악의적인 SQL 구문을 삽입하여 데이터베이스를 비인가 조회/변조/삭제하는 웹 애플리케이션 공격

특징: OWASP Top 10 상위, 가장 오래되고 위험한 웹 공격, 데이터 유출/인증 우회/DB 파괴 가능

구성요소: 입력 필드(사용자 입력 포인트), 취약한 쿼리(문자열 연결 방식), 데이터베이스(공격 대상)

기술요소: Union 기반(UNION SELECT로 다른 테이블 조회), Boolean 기반(참/거짓 응답 차이 분석), Time 기반(SLEEP/BENCHMARK로 시간차 분석), 블라인드 SQLi(에러 메시지 없이 추론)

공격 유형별 동작원리 상세

  • Error-based SQLi: DB 에러 메시지에 데이터 노출 유도, ' AND 1=CONVERT(int,(SELECT TOP 1 table_name FROM information_schema.tables))--, 에러 메시지에서 테이블명/컬럼명 추출
  • Union-based SQLi: UNION SELECT로 추가 쿼리 결합, 컬럼 수 일치 필요(ORDER BY 또는 UNION SELECT NULL,NULL,...로 확인), 다른 테이블 데이터 직접 조회
  • Blind Boolean-based SQLi: 응답의 참/거짓 차이로 데이터 1비트씩 추론, ' AND SUBSTRING(password,1,1)='a'--, 자동화 도구(sqlmap) 필수, 느리지만 에러 메시지 없어도 가능
  • Blind Time-based SQLi: 시간 지연으로 참/거짓 판단, ' AND IF(1=1,SLEEP(5),0)--, 5초 지연 발생 시 참, 가장 느리지만 가장 범용적
  • 2차(Second-Order) SQLi: 악성 입력을 DB에 저장 → 나중에 다른 쿼리에서 사용될 때 실행, Prepared Statement로도 방어 어려울 수 있음(저장된 값을 재사용하는 쿼리)

Prepared Statement 동작원리

  • SQL 구문과 데이터를 분리하여 DB에 전달
  • SELECT * FROM users WHERE id = ? → 구문 먼저 컴파일(파싱/최적화) → 이후 파라미터 바인딩
  • 파라미터는 항상 데이터로만 처리, SQL 구문으로 해석 불가 → 근본적 방어
  • 예시(Java): PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); ps.setString(1, userInput);

공격예시: ' OR '1'='1 (인증 우회), UNION SELECT username,password FROM users (데이터 탈취)

대응: Prepared Statement(파라미터화 쿼리/근본 대책), ORM 사용(자동 파라미터화), 입력 검증(화이트리스트), 최소 권한(DB 계정), WAF(보조)

적용사례: 로그인 폼, 검색 기능, URL 파라미터, API 파라미터

비교: 1차 SQLi(직접 주입/즉시 실행) vs 2차 SQLi(저장 후 나중에 실행) vs 블라인드 SQLi(응답 차이로 추론/시간 소요)

연관: OWASP Top 10, Injection, 시큐어 코딩, WAF, Prepared Statement