SQL Injection이란?
SQL Injection은 공격자가 웹 애플리케이션의 데이터베이스에 악의적인 SQL 쿼리를 삽입하여 비정상적인 동작을 유도하거나, 데이터를 탈취하거나, 데이터베이스를 손상시키는 공격 기법이다.
주로 입력값이 제대로 검증되지 않고 SQL 쿼리에 포함될 때 발생한다.
SQL Injection은 여러 유형이 있으며, 각 유형에 따라 공격방법과 피해가 달라진다. 주요 SQL Injection 종류에 대해 살펴보자.
Error based SQL Injection
논리적 에러를 활용한 SQL Injection이다.
의도적으로 오류를 발생시켜 공격자가 시스템에 대한 정보를 얻을 수 있다.
-- 정상적인 쿼리
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
-- SQL 인젝션 공격
SELECT * FROM users WHERE username = 'admin' AND password = 'anything' OR 1=1;
위의 예시 처럼 항상 참인 조건을 삽입하여 인증 우회를 하는 등 악의적으로 접근할 수 있다.
Union-based SQL Injection
UNION SQL 연산자를 사용하여 공격자가 다른 테이블의 데이터를 결합하도록 하는 방식이다.
공격자는 원래 쿼리의 결과와 함께 다른 테이블의 데이터를 반환할 수 있습니다.
-- 정상적인 쿼리
SELECT *
FROM users
WHERE username = 'admin'
AND password = 'password';
-- SQL 인젝션 공격 (다른 테이블에서 데이터 추출)
SELECT *
FROM users
WHERE username = 'admin'
AND password = 'password'
UNION
SELECT username, password
FROM other_table;
Blind SQL Injection
공격자가 직접적인 결과를 얻을 수 없을 때 발생한다.
쿼리 실행 결과가 나타나지 않지만, 공격자는 쿼리가 실행된 후의 응답 시간이나 데이터베이스의 동작을 통해 정보를 추론한다.
Boolean-based Blind SQL Injection
쿼리에서 조건이 참인지 거짓인지에 따라 응답을 달리하여 조건을 조작함으로써 데이터베이스의 정보를 추론하는 방식이다.
-- 정상적인 쿼리
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
-- SQL 인젝션 공격
SELECT * FROM users WHERE username = 'admin' AND password = 'anything' OR 1=1; -- 참
SELECT * FROM users WHERE username = 'admin' AND password = 'anything' OR 1=2; -- 거짓
일부러 참 조건과 거짓인 조건을 실행시켜 참일때는 어떻게 동작하는지, 거짓일때는 어떻게 동작하는지 알아낼 수 있다.
-- 첫 번째 문자 추측
SELECT *
FROM users
WHERE username = 'admin'
OR 1=1
AND SUBSTRING(password, 1, 1) = 'a'
이 쿼리는 비밀번호의 첫 번째 문자가 'a'인지를 확인한다.
만약 a가 맞다면, 참이 되어 정상적인 응답이 오고, 거짓이라면 다른 응답이 올 것이다.
참/거짓에 대한 동작을 알고 있으므로 추론 가능하다.
Time-based Blind SQL Injection
쿼리 내에서 SLEEP() 함수나 WAITFOR DELAY를 사용하여 쿼리가 얼마나 지연되는지를 통해 데이터를 추론한다.
TRUE일 때 일정 시간 동안 지연시켜 응답 시간을 측정할 수 있다.
-- 첫 번째 문자 추측
SELECT *
FROM users
WHERE username = 'admin'
AND IF(SUBSTRING(password, 1, 1) = 'a', SLEEP(5), NULL);
이 쿼리는 password의 첫 번째 문자가 'a'인지를 확인한다.
만약 password의 첫 번째 문자가 a라면 서버는 5초 동안 지연되고, 아니면 즉시 응답이 돌아올 것이다.
공격자는 응답 시간이 5초가 되는지 확인하여, 비밀번호의 첫 번째 문자가 무엇인지 추측할 수 있다.
Second-Order SQL Injection
첫 번째 쿼리에서 공격자가 입력한 값이 직접적으로 실행되지 않지만,후속 쿼리에서 그 값이 사용될 때 발생한다.
ㄴ 때문에 지연 기반 SQL Injection 이라고 한다.
공격자는 첫 번째 요청에서 악성 데이터를 삽입하고, 후속 요청에서 그 데이터를 실행하여 공격을 수행한다.
-- 첫 번째 요청에서 사용자 입력
INSERT INTO users (username, password) VALUES ('admin', 'password');
-- 두 번째 요청에서 실행되는 SQL 인젝션
SELECT * FROM users WHERE username = 'admin' AND password = 'anything' OR '1'='1';
첫 번째 요청에서 공격자가 username에 악성 값을 입력하고, 두 번째 요청에서 그 값이 사용될 때 공격이 실행된다.
🆙 그 외의 SQL Injection 종류
- 사용자 입력 기반 SQL Injection
웹 폼을 통해 악의적인 SQL문 주입
- 쿠키 기반 SQL Injection
쿠키를 수정하여 데이터베이스 쿼리를 조작
- HTTP 헤더 기반 SQL Injection
HTTP 헤더를 통해 SQL 코드를 주입
- Stored Procedure SQL Injection
저장 프로시저에 악성코드를 삽입해 실행
SQL Injection 방지 방법
- 준비된 쿼리 (Prepared Statements)
SQL 쿼리를 사전 정의하고 파라미터화하여 악성 SQL 코드가 삽입되지 않도록 한다. - 입력 값 검증 (Input Validation)
모든 사용자 입력에 대해 적절한 필터링과 검증을 통해 악성 코드가 포함되지 않도록 한다. - ORM (Object-Relational Mapping)
ORM 프레임워크를 사용하여 SQL 쿼리 작성 시 자동으로 안전한 쿼리가 생성되도록 한다. - 최소 권한 원칙
데이터베이스 사용자의 권한을 최소화하여, SQL 인젝션 공격이 성공하더라도 피해를 최소화한다. - 에러 메시지 숨기기
공격자가 시스템에 대한 정보를 얻지 않도록, 상세한 오류 메시지를 사용자에게 노출하지 않도록 한다.
'Computer Science > Database' 카테고리의 다른 글
정규화 (0) | 2024.11.25 |
---|---|
SQL과 NoSQL (2) | 2024.11.24 |
조인(JOIN) - ANSI SQL, MySQL, Oracle 예 (0) | 2024.11.22 |
트랜잭션(Transaction) & 트랜잭션 격리성 (0) | 2024.11.18 |
키(Key) (0) | 2024.11.11 |