SQL Injection 공격 방어

728x90

 

SQL Injection 취약점이란?

SQL Injection(이하 SQLi)은 웹 애플리케이션이 사용자 입력을 적절히 검증하지 않고 직접 SQL 쿼리에 삽입할 때 발생하는 보안 취약점이다. 이를 악용하면 공격자가 데이터베이스를 조작하거나, 비인가된 데이터를 조회하고 수정할 수 있다.

 

 

[SQL Injection 방어 방법]

 

1. 특수문자 필터링

' (싱글쿼터) 문자열을 닫고 SQL 구문을 조작하는 데 사용됨
" (더블쿼터) 일부 DBMS에서 문자열을 감쌀 때 사용됨
-- (더블 대시) SQL에서 한 줄 주석 처리 (-- 이후 내용 무시)
# MySQL 등에서 주석 처리에 사용됨
; (세미콜론) 여러 개의 SQL 문을 실행하는 데 사용됨 (특히 배치 쿼리 공격)
/* ... */ SQL 블록 주석 처리 (멀티라인 주석)
() 서브쿼리 공격에 사용됨
= 조건 조작 (예: 1=1 항상 참이 되도록 유도)
<, >, != 논리 연산자로 조건을 변형하는 데 사용됨
% 와일드카드 문자 (LIKE 연산자와 함께 사용됨)
_ LIKE 검색에서 단일 문자 와일드카드로 사용됨

 

 

 

2. DB 계정 권한 분리, 최소화 및 화이트리스트 방식 사용

DB 계정의 권한을 최소화하여 DROP, UPDATE 등의 실행을 제한

특정 사이트에서는 SQL 관리 목적으로? 페이지에서 직접 쿼리를 실행하는 사이트가 있다

이러한 경우에는 가장 좋은 조치 방법은사용해야 될 쿼리문만 버튼형 방식으로 사용하여 서버에서 쿼리가 실행 될수 있도록 하는 것이다.

 

 

 

 

3. 바인딩 방식 사용

Prepared Statement 방식을

ps. 통상 기능(SQL에서 미리 컴파일된 보안 기능)이라고 표현 하는데

아래와 같이
기능=함수=코드=로직=메서드=API=바인딩 
등으로 여러 단어로 표현 되기도 합니다.

 

Java -> Prepared Statement

Python -> cursor.execute()

PHP -> mysqli_prepare()

 

 

 

[잘못된 코드 예시]

String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

 

username에 ' OR '1'='1 을 입력하게 되면

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''

으로 실행되어 조건이 항상 참이 됨, 때문에 비밀번호 없이 로그인이 가능함

 

 

[Prepared Statement 사용 예시]

String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();

 

문자열 처리가 되어 실제 실행되는 쿼리는 아래와 같음

SELECT * FROM users WHERE username = '\' OR \'1\'=\'1' AND password = ''

 

 

4. ORM (Object-Relational Mapping) 사용
Hibernate, JPA 같은 ORM을 사용하면 SQL 직접 조작을 최소화할 수 있음.

 

 

5. 웹방화벽 사용

공격 패턴, 시그니처 방식으로 차단

 

 

 

 

[점검 방법]

Cheat Sheet 

https://www.sqltutorial.org/sql-cheat-sheet/

 

 

 

또는

 

SQL MAP 과 같은 자동점검 툴로 점검이 가능

 

728x90