[DB] SQL Injection

·2025년 1월 9일

데이터베이스

목록 보기
14/22
post-thumbnail

SQL Injection


SQL 인젝션이란?

  • SQL 인젝션(Injection)은 공격자가 웹 애플리케이션의 데이터베이스를 조작하기 위해 악의적인 SQL 코드를 삽입하는 공격 방법

SQL 인젝션의 원리

  • 애플리케이션에서 사용자 입력을 제대로 검증하지 않고 SQL 쿼리에 포함시킬 때 발생
  • 공격자가 입력값에 SQL 명령어를 포함하여 데이터베이스 쿼리를 변조

예시:
아래와 같은 쿼리가 있다고 가정

SELECT * FROM users WHERE username = '사용자입력값' AND password = '사용자비밀번호';
  1. 공격자가 username에 아무렇게 입력하고 password에 ' OR '1'='1 입력
SELECT * FROM users WHERE username = '사용자입력값' AND password = '' OR '1'='1';
  • AND가 OR보다 연산자 우선순위가 먼저이기 때문에 (username = '사용자입력값' AND password = '') OR '1'='1'
  • 1=1 라는 조건이 항상 참이 되어, 모든 데이터가 조회됨
  1. 공격자가 admin' -- 를 입력 (admin 존재한다고 가정)
SELECT * FROM users WHERE username = 'admin' --' AND password = '사용자비밀번호';
  • -- 뒷 부분이 주석처리가 되기 때문에 해당 데이터 조회됨
  1. 공격자가 username에 admin을 입력하고admin'; Drop table users; -- (admin 존재한다고 가정)
SELECT * FROM users WHERE username = 'admin'; Drop table users; --' AND password = '사용자비밀번호';
  • users 테이블 데이터 삭제됨

공격 유형에 따른 분류

1. Error Based SQL Injection

  • 데이터베이스의 에러 메시지를 통해 데이터베이스명, 테이블, 컬럼 등 구조나 정보를 알아내는 방식
SELECT * FROM users WHERE id = 1' AND extractvalue(1, concat(0x7e, database())) -- ;

2. Union SQL Injection

  • UNION 키워드를 사용해 원래의 SQL 쿼리에 민감한 데이터를 추출하는 SQL 쿼리를 덧붙힘
SELECT username, password FROM users WHERE id = 1 
UNION SELECT table_name, column_name FROM information_schema.tables -- ;

3. Blind SQL Injection

  • 서버가 직접적인 응답(데이터)을 반환하지 않고, 참/거짓 결과나 시간 지연을 통해 간접적으로 정보를 추출
  • Boolean-Based Blind SQL Injection
    • 서버 응답이 참/거짓에 따라 정보를 추출
SELECT * FROM users WHERE id = 5 AND LENGTH(username) = 1 --+;  // 거짓
SELECT * FROM users WHERE id = 5 AND LENGTH(username) = 3 --+; // 참 - 컬럼 길이가 3인걸 의미

SELECT * FROM users WHERE id = 5 AND ASCII(SUBSTRING(username, 1, 1)) = 97 --+; // 거짓 - 첫번째 값 ASCII 값 97 아님
SELECT * FROM users WHERE id = 5 AND ASCII(SUBSTRING(username, 1, 1)) = 97 --+; // 참 -  첫번째 값 ASCII 값 100임
  • Time-Based Blind SQL Injection
    • 응답 시간 지연을 이용해 데이터를 추출
-- 데이터베이스 이름 길이가 5일 경우 5초 대기
SELECT * FROM users WHERE id = 1 AND IF(LENGTH(DATABASE()) = 5, SLEEP(5), 0) -- ;

SQL 인젝션 예방 방법

1. Prepared Statement 사용

  • SQL 구문이 미리 컴파일되어 있으며, 입력값을 변수에 바인딩하여 처리하는 방식
  • 또한, 파싱 단계가 캐싱되므로 동일한 쿼리를 반복 실행할 때 성능을 개선

일반적인 Statement (취약)

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
...
String sql = "SELECT * FROM MEMBER WHERE ID = '"+param_id+"' AND PW = '"+param_ passwd+"'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);

Prepared Statement 사용

String param_id=request.getParameter("id");
String param_passwd=request.getParameter("passwd");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;String sql = "SELECT * FROM MEMBER WHERE ID = ? AND PW = ?";
pstmt.setString(1, param_id);
pstmt.setString(2, param_passwd);
rs = pstmt.executeQuery(sql);

2. 입력 값에 대한 검증

  • 공격에 사용될 가능성이 있는 예약어 및 특수문자를 검증

3. 데이터베이스 권한 제한

4. Error Message 노출 금지


Reference

https://blog.naver.com/sk_shieldus/222878789136

0개의 댓글