SQL Injection: 두 판 사이의 차이

기술노트
(CS 용어 정리 - SQL Injection 추가)
 
(컴퓨터 과학 용어 정리 - SQL Injection 추가)
 
1번째 줄: 1번째 줄:
=== SQL Injection ===
= SQL Injection =


> 해커에 의해 조작된 SQL 쿼리문이 데이터베이스에 그대로 전달되어 비정상적 명령을 실행시키는 공격 기법
== 개념 ==
SQL Injection은 웹 애플리케이션의 주요 보안 취약점으로, 공격자가 악의적인 SQL 코드를 삽입하여 데이터베이스를 비정상적으로 조작하는 공격 기법입니다. 이 공격은 애플리케이션이 사용자 입력을 적절히 검증하지 않고 SQL 쿼리에 직접 포함시킬 때 발생합니다.


<br>
== 유형 ==
=== 기본적인 SQL Injection ===
* 사용자 입력이 SQL 쿼리의 구조를 변경하는 경우
* 예: <code>SELECT * FROM users WHERE username='admin' AND password='' OR '1'='1'</code>
* <code>'1'='1'</code>은 항상 참이므로 인증 우회 가능


===== 공격 방법 =====
=== Blind SQL Injection ===
* 직접적인 결과를 볼 수 없지만 참/거짓 응답으로 정보를 유추
* 예: <code>SELECT * FROM users WHERE username='admin' AND (SELECT 1 FROM information_schema.tables WHERE table_name='users' LIMIT 1)=1</code>
* 시스템 반응을 통해 특정 테이블 존재 여부 확인


##### 1) 인증 우회
=== Error-based SQL Injection ===
* 데이터베이스 오류 메시지를 통해 정보 획득
* 예: <code>SELECT * FROM users WHERE id=1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))</code>
* 오류 메시지에 데이터베이스 버전 정보가 포함됨


보통 로그인을 할 때, 아이디와 비밀번호를 input 창에 입력하게 된다. 쉽게 이해하기 위해 가벼운 예를 들어보자. 아이디가 abc, 비밀번호가 만약 1234일 때 쿼리는 아래와 같은 방식으로 전송될 것이다.
=== Time-based SQL Injection ===
* 시간 지연을 통해 정보 유추
* 예: <code>SELECT * FROM users WHERE id=1 AND IF(1=1, SLEEP(5), 0)</code>
* 조건이 참이면 5초간 지연됨


<syntaxhighlight>
=== Union-based SQL Injection ===
SELECT * FROM USER WHERE ID = "abc" AND PASSWORD = "1234";
* UNION 구문을 이용해 추가 쿼리 실행
</syntaxhighlight>
* 예: <code>SELECT name, email FROM users WHERE id=1 UNION SELECT username, password FROM admin</code>
* 관리자 테이블의 정보 획득 가능


SQL Injection으로 공격할 때, input 창에 비밀번호를 입력함과 동시에 다른 쿼리문을 함께 입력하는 것이다.
== 방어 방법 ==
 
=== 매개변수화된 쿼리(Prepared Statements) 사용 ===
<syntaxhighlight>
* SQL 쿼리와 데이터를 분리하여 처리
1234; DELETE * USER FROM ID = "1";
* 예:
<syntaxhighlight lang="java">
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, username);
stmt.setString(2, password);
</syntaxhighlight>
</syntaxhighlight>


보안이 완벽하지 않은 경우, 이처럼 비밀번호가 아이디와 일치해서 True가 되고 뒤에 작성한 DELETE 문도 데이터베이스에 영향을 줄 수도 있게 되는 치명적인 상황이다.
=== 입력 값 검증 ===
 
* 사용자 입력에 SQL 명령어나 특수문자가 포함되었는지 확인
이 밖에도 기본 쿼리문의 WHERE 절에 OR문을 추가하여 `'1' = '1'`과 같은 true문을 작성하여 무조건 적용되도록 수정한 뒤 DB를 마음대로 조작할 수도 있다.
* 화이트리스트 방식으로 유효한 입력만 허용
 
<br>
 
##### 2) 데이터 노출
 
시스템에서 발생하는 에러 메시지를 이용해 공격하는 방법이다. 보통 에러는 개발자가 버그를 수정하는 면에서 도움을 받을 수 있는 존재다. 해커들은 이를 역이용해 악의적인 구문을 삽입하여 에러를 유발시킨다.


즉 예를 들면, 해커는 '''GET 방식으로 동작하는 URL 쿼리 스트링을 추가하여 에러를 발생'''시킨다. 이에 해당하는 오류가 발생하면, 이를 통해 해당 웹앱의 데이터베이스 구조를 유추할 수 있고 해킹에 활용한다.
=== ORM(Object-Relational Mapping) 사용 ===
* SQL 쿼리를 직접 작성하지 않고 객체 모델을 통해 데이터베이스에 접근
* 예: Hibernate, Entity Framework, Django ORM 등


<br>
=== 최소 권한 원칙 ===
* 데이터베이스 계정에 필요한 최소한의 권한만 부여
* 읽기 전용 작업에는 SELECT 권한만 부여된 계정 사용


<br>
=== 오류 메시지 숨기기 ===
* 상세한 데이터베이스 오류 메시지를 사용자에게 노출하지 않음
* 일반적인 오류 메시지로 대체


===== 방어 방법 =====
=== WAF(Web Application Firewall) 사용 ===
* 웹 애플리케이션 방화벽을 통해 SQL Injection 패턴 차단


##### 1) input 값을 받을 때, 특수문자 여부 검사하기
== 실제 사례 ==
=== Sony Pictures (2011) ===
* LulzSec 해커 그룹이 SQL Injection 취약점을 이용해 100만 명 이상의 사용자 정보 유출


> 로그인 전, 검증 로직을 추가하여 미리 설정한 특수문자들이 들어왔을 때 요청을 막아낸다.
=== Yahoo (2012) ===
* 약 45만 명의 계정 정보가 SQL Injection을 통해 유출됨


##### 2) SQL 서버 오류 발생 시, 해당하는 에러 메시지 감추기
=== LinkedIn (2012) ===
* 약 650만 명의 사용자 비밀번호 해시가 유출


> view를 활용하여 원본 데이터베이스 테이블에는 접근 권한을 높인다. 일반 사용자는 view로만 접근하여 에러를 볼 수 없도록 만든다.
=== TalkTalk (2015) ===
* 영국 통신회사 TalkTalk의 고객 정보 15만 건이 SQL Injection 공격으로 유출


##### 3) preparestatement 사용하기
== 보안 인식의 중요성 ==
* SQL Injection은 OWASP Top 10에서 지속적으로 상위권에 포함되는 심각한 보안 위협
* 개발자 교육과 코드 리뷰를 통해 SQL Injection 취약점 예방 가능
* 정기적인 보안 테스트와 코드 스캐닝으로 취약점 조기 발견


> preparestatement를 사용하면, 특수문자를 자동으로 escaping 해준다. (statement와는 다르게 쿼리문에서 전달인자 값을 `?`로 받는 것) 이를 활용해 서버 측에서 필터링 과정을 통해서 공격을 방어한다.
== 관련 주제 ==
* 웹 보안
* OWASP
* 데이터베이스 보안
* 입력 검증
* 보안 코딩 가이드라인

2025년 4월 17일 (목) 15:33 기준 최신판

SQL Injection

개념

SQL Injection은 웹 애플리케이션의 주요 보안 취약점으로, 공격자가 악의적인 SQL 코드를 삽입하여 데이터베이스를 비정상적으로 조작하는 공격 기법입니다. 이 공격은 애플리케이션이 사용자 입력을 적절히 검증하지 않고 SQL 쿼리에 직접 포함시킬 때 발생합니다.

유형

기본적인 SQL Injection

  • 사용자 입력이 SQL 쿼리의 구조를 변경하는 경우
  • 예: SELECT * FROM users WHERE username='admin' AND password= OR '1'='1'
  • '1'='1'은 항상 참이므로 인증 우회 가능

Blind SQL Injection

  • 직접적인 결과를 볼 수 없지만 참/거짓 응답으로 정보를 유추
  • 예: SELECT * FROM users WHERE username='admin' AND (SELECT 1 FROM information_schema.tables WHERE table_name='users' LIMIT 1)=1
  • 시스템 반응을 통해 특정 테이블 존재 여부 확인

Error-based SQL Injection

  • 데이터베이스 오류 메시지를 통해 정보 획득
  • 예: SELECT * FROM users WHERE id=1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))
  • 오류 메시지에 데이터베이스 버전 정보가 포함됨

Time-based SQL Injection

  • 시간 지연을 통해 정보 유추
  • 예: SELECT * FROM users WHERE id=1 AND IF(1=1, SLEEP(5), 0)
  • 조건이 참이면 5초간 지연됨

Union-based SQL Injection

  • UNION 구문을 이용해 추가 쿼리 실행
  • 예: SELECT name, email FROM users WHERE id=1 UNION SELECT username, password FROM admin
  • 관리자 테이블의 정보 획득 가능

방어 방법

매개변수화된 쿼리(Prepared Statements) 사용

  • SQL 쿼리와 데이터를 분리하여 처리
  • 예:
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, username);
stmt.setString(2, password);

입력 값 검증

  • 사용자 입력에 SQL 명령어나 특수문자가 포함되었는지 확인
  • 화이트리스트 방식으로 유효한 입력만 허용

ORM(Object-Relational Mapping) 사용

  • SQL 쿼리를 직접 작성하지 않고 객체 모델을 통해 데이터베이스에 접근
  • 예: Hibernate, Entity Framework, Django ORM 등

최소 권한 원칙

  • 데이터베이스 계정에 필요한 최소한의 권한만 부여
  • 읽기 전용 작업에는 SELECT 권한만 부여된 계정 사용

오류 메시지 숨기기

  • 상세한 데이터베이스 오류 메시지를 사용자에게 노출하지 않음
  • 일반적인 오류 메시지로 대체

WAF(Web Application Firewall) 사용

  • 웹 애플리케이션 방화벽을 통해 SQL Injection 패턴 차단

실제 사례

Sony Pictures (2011)

  • LulzSec 해커 그룹이 SQL Injection 취약점을 이용해 100만 명 이상의 사용자 정보 유출

Yahoo (2012)

  • 약 45만 명의 계정 정보가 SQL Injection을 통해 유출됨

LinkedIn (2012)

  • 약 650만 명의 사용자 비밀번호 해시가 유출

TalkTalk (2015)

  • 영국 통신회사 TalkTalk의 고객 정보 15만 건이 SQL Injection 공격으로 유출

보안 인식의 중요성

  • SQL Injection은 OWASP Top 10에서 지속적으로 상위권에 포함되는 심각한 보안 위협
  • 개발자 교육과 코드 리뷰를 통해 SQL Injection 취약점 예방 가능
  • 정기적인 보안 테스트와 코드 스캐닝으로 취약점 조기 발견

관련 주제

  • 웹 보안
  • OWASP
  • 데이터베이스 보안
  • 입력 검증
  • 보안 코딩 가이드라인