SQL injection(SQL 인젝션)은 공격자가 애플리케이션의 보안 취약점을 이용해 악의적인 SQL코드를 데이터베이스에 삽입함으로써, 데이터베이스를 조작하거나 민감한 정보를 탈취하는 공격 기법이다. 이는 주로 애플리케이션에서 사용자 입력을 제대로 검증하지 않을 때 발생한다.
작동원리
SQL 인젝션은 사용자가 입력한 값이 SQL 쿼리의 일부로 실행될 때, 이 입력 값에 포함된 악의적인 SQL 코드가 실행되어 공격이 발생합니다. 예를 들어, 아래와 같은 SQL쿼리가 있다고 가정하자.
SELECT * FROM users WHERE username = 'user' AND password = 'password';
만약 사용자 입력이 아래와 같이 쿼리에 삽입된다면
username: ' OR '1'='1
password: ''
쿼리는 다음과 같이 변환된다.
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
'1'='1'은 항상 참이므로, 데이터베이스는 모든 사용자의 정보를 반환하게 된다.
SQL Injection의 유형
1. Classic SQL Injection
기본적인 SQL 코드 조작방식
예: ' OR '1'='1' --
2. Blind SQL Injection
응답 메시지나 페이지가 직접적인 정보 대신 참/거짓 여부로 결과를 반환시킨다.
예: ' AND 1=1 -- , ' AND 1=2--
3. Union-Based SQL Injection
UNION 키워드를 사용하여 공격자가 원하는 데이터를 반환한다.
' UNION SELECT username, password FROM users --
4. Boolean-Based SQL Injection
조건문을 삽입하여 참/거짓을 통해 데이터베이스를 추측한다.
5. Time-Based SQL Injection
데이터베이스 쿼리의 실행 시간을 조작해 정보를 얻는다.
' OR IF(1=1, SLEEP(5), 0) --
피해
데이터 유출: 민감한 정보(사용자 이름, 암호, 금융 정보 등) 탈취
데이터베이스 손상: 데이터 삭제, 변경 또는 손상
권한 상승: 공격자가 데이터베이스 관리자 권한을 획득
서비스 장애: 데이터베이스를 과도하게 사용하거나 손상시켜 서비스 중단
방어 방법
1. 사용자 입력 검증 및 정규화
모든 입력값을 철저히 검증한다.
특정 문자들 ' ; -- 등을 제거하거나 제한하는 것.
2. Prepared Statement 및 Parameterzied Query 사용
SQL 쿼리를 실행할 때, 사용자 입력값과 쿼리를 분리한다.
예:
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
3. Stored Procedure 사용
SQL 쿼리를 미리 정의된 프로시저로 처리한다.
4. ORM (Object-Relational Mapping) 사용
Hibernate와 같은 ORM 툴은 기본적으로 SQL Injection 방지 기능 제공한다.
5. 최소 권한 원칙 적용
애플리케이션 계정에 최소한의 권한만 부여한다.
6. 에러 메시지 제한
데이터베이스 구조를 노출하지 않도록 에러 메시지를 제한한다.
7. WAF(Web Application Firewall)
SQL Injection 공격을 탐지 및 차단하는 방화벽 사용한다.
결론
SQL Injection은 웹 애플리케이션의 보안 취약점을 이용해 데이터베이스를 조작하거나 정보를 탈취하는 강력한 공격 방법이다. 이를 방지하기 위해서는 철저한 사용자 입력 검증과 보안 코딩, 그리고 강화 도구 사용이 필수적입니다.