Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

SQL 인젝션(SQL Injection)이란? 공격 원리와 예방 방법 총정리

SQL 인젝션이란 무엇인가?

SQL 인젝션(SQL Injection)은 대표적인 웹 해킹 기법 중 하나입니다. 웹 페이지의 입력 폼을 통해 악성 코드를 삽입하여 데이터베이스를 조작하거나 파괴하는 코드 인젝션(code injection) 기술로, 해커가 데이터베이스 내부의 민감한 정보에 접근할 수 있게 만드는 심각한 보안 취약점입니다.

SQL 인젝션의 주요 원인은 사용자 입력값을 충분히 검증하지 않고 SQL 쿼리에 그대로 전달하는 것입니다. 이렇게 되면 공격자는 쿼리 구조를 조작해 데이터베이스 안의 데이터를 마음대로 열람하거나 변경할 수 있습니다.

SQL 인젝션 공격 예시

학생 정보를 담은 테이블이 있다고 가정해 보겠습니다. 각 학생은 자신의 학번(student id)을 입력하여 본인의 정보만 조회할 수 있도록 SQL 쿼리가 설계되어 있습니다.

그런데 만약 학생이 학번 입력란에 "12345 or 1=1"이라고 입력하면 어떻게 될까요? 이 입력값은 다음과 같은 쿼리로 변환됩니다.

SELECT * FROM Students WHERE id==12345 or 1=1

위 쿼리에서 1=1은 항상 참(true)이기 때문에, WHERE 조건이 무력화됩니다. 그 결과 해당 학생뿐만 아니라 다른 학생들의 레코드까지 모두 반환됩니다. 즉, 타인의 데이터가 노출되며 해커에 의해 악용될 위험에 그대로 놓이게 됩니다.

SQL 인젝션 예방 방법: 플레이스홀더(Placeholder) 사용

SQL 인젝션을 막는 가장 기본적인 방법은 사용자 입력값을 쿼리에 직접 연결하지 않고, 이스케이프 처리된 매개변수 형태로 전달하는 것입니다. Python의 MySQL 커넥터(mysql.connector) 모듈은 쿼리 값을 안전하게 이스케이프할 수 있는 방법을 제공하며, 이때 플레이스홀더 %s를 사용합니다.

예를 들어, 다음과 같은 "MyTable" 테이블이 있다고 가정합니다.

+----------+---------+-----------+------------+
|    Name  | Class   |    City   |    Marks   |
+----------+---------+-----------+------------+
|    Karan |    4    | Amritsar  |    95      |
|    Sahil |    6    | Amritsar  |    93      |
|    Kriti |    3    | Batala    |    88      |
|   Khushi |    9    | Delhi     |    90      |
|    Kirat |    5    | Delhi     |    85      |
+----------+---------+-----------+------------+

예제 코드

import mysql.connector

db=mysql.connector.connect(host="your host", user="your username", password="your password", database="database_name")

cursor=db.cursor()

query="SELECT * FROM Students WHERE Name=%s"
name=("Karan",)

cursor.execute(query,name)

for row in myresult:
    print(row)

위 코드에서 볼 수 있듯이, 쿼리 문자열에 값이 아닌 플레이스홀더 %s를 넣고, 실제 값은 execute() 메서드의 매개변수로 별도 전달합니다. 이렇게 하면 입력값이 쿼리 구조의 일부로 해석되지 않고 순수한 데이터로만 처리되므로, SQL 인젝션 공격을 효과적으로 차단할 수 있습니다.

실행 결과

('Karan', 4, 'Amritsar', 95)

마무리: 추가 보안 권장 사항

플레이스홀더를 활용한 매개변수화된 쿼리(prepared statement)는 SQL 인젝션 방어의 핵심입니다. 여기에 더해 다음과 같은 조치를 함께 적용하면 더욱 안전한 웹 애플리케이션을 만들 수 있습니다.

- 입력값 검증: 숫자 필드에는 숫자만 허용하는 등 화이트리스트 방식으로 입력을 검증합니다.
- 최소 권한 원칙: 애플리케이션이 사용하는 DB 계정에 불필요한 권한(DROP, DELETE 등)을 부여하지 않습니다.
- 에러 메시지 최소화: 상세한 DB 에러 메시지를 사용자에게 노출하지 않아 공격자에게 단서를 주지 않습니다.
- ORM 또는 보안 라이브러리 활용: 검증된 프레임워크의 쿼리 빌더나 ORM을 사용하면 실수로 인한 취약점을 줄일 수 있습니다.