카테고리 없음

SQL 인젝션이 어떻게 발생하는가?

JUNGKEUNG 2025. 3. 9. 17:09
반응형

인젝션이란?

외부에서 입력된 데이터가 애플리케이션을 실행 흐름을 변경하거나, 보안 추약점을 악용할 수 있돌고 하는 공격 기법이다.

 

 

예를 들어 보안이 취한 검색 코드를 보여주겠다.

String query = "SELECT * FROM users WHERE username = '" + userInput + "'";

 

사용자가 admin' --을 입력하면?

 

SELECT * FROM users WHERE username = 'admin' --'

-- 이후는 주석 처리되어 전체 사용자 데이터가 노출될 수도 있다

 

 

1. SQL 인젝션 방지 원리

1. PreparedStatement 사용 ( 가장 기본적인 해결 방법)

   - PreparedStatement는 SQL에 ? 플레이스홀더를 사용하여 안전하게 값을 바인딩 한다.

String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userInput); // 사용자 입력값을 안전하게 바인딩
ResultSet rs = pstmt.executeQuery();

SQL과 입력값을 분리하여 해킹을 방지할 수 있음.


 

2. 사용자 입력값 검증 (Validation)

검색어가 너무 길거나, SQL 키워드(SELECT, DELETE 등)를 포함하면 차단해야 한다.

if (userInput.length() > 50 || userInput.matches(".*([';--]).*")) { 
	throw new IllegalArgumentException("잘못된 검색어입니다."); 
}

특수문자(', ;, --) 포함 여부를 체크하여 SQL 공격을 방지!


3. 검색어가 없을 때 처리 (빈 검색어 방지)

검색 필드가 비어 있을 때 무조건 쿼리를 실행하면 성능 저하 또는 전체 데이터 유출 위험이 있다.

if (userInput == null || userInput.trim().isEmpty()) {
	throw new IllegalArgumentException("검색어를 입력하세요."); 
}

빈 검색어는 즉시 차단하여 불필요한 쿼리 실행 방지!


4. 대소문자 문제 해결 (LOWER() 또는 UPPER())

데이터베이스는 보통 대소문자를 구분하므로, 검색 시 동일한 결과를 얻기 위해 LOWER() 또는 UPPER()를 사용한다.

 
String sql = "SELECT * FROM users WHERE LOWER(username) = LOWER(?)"; 
PreparedStatement pstmt = connection.prepareStatement(sql); pstmt.setString(1, userInput);

모든 입력을 소문자로 변환하여 대소문자 구분 문제를 해결!


5. SQL 인덱스를 활용하여 성능 향상

검색어를 빠르게 찾기 위해 검색 대상 컬럼에 인덱스를 추가하면 성능이 개선

CREATE INDEX idx_username ON users(username);
 
인덱스를 추가하면 검색 속도가 빨라지고 데이터베이스 부하를 줄일 수 있다

정리 (SQL 인젝션 방지 원칙)

방법 및 설명

PreparedStatement SQL과 입력값을 분리하여 해킹 방지
사용자 입력 검증 SQL 특수문자(', --) 차단
빈 검색어 방지 불필요한 쿼리 실행 방지
대소문자 변환 LOWER(), UPPER()를 활용하여 검색 일관성 유지
SQL 인덱스 사용 검색 속도를 향상하여 성능 개선

 

결론

- 검색 기능에서 SQL 인젝션 방지는 필수!
- PreparedStatement, 입력 검증, 빈 검색어 체크로 보안 강화!
- LOWER(), UPPER() 활용 및 인덱스로 성능까지 개선!