Programming

🔎 Python에서 조건별로 MSSQL 쿼리 동적 생성하기 (f-string과 SQL Injection 방지법)

quantoasis 2025. 3. 26. 14:56
반응형

Python으로 MSSQL에 접속할 때, 사용자의 선택이나 조건에 따라 동적으로 SQL 쿼리를 생성해야 하는 상황이 많습니다.
하지만 잘못된 방식으로 쿼리를 구성하면 보안에 치명적인 SQL Injection 문제가 발생할 수 있죠.

이번 포스팅에서는 아래 내용을 쉽게 정리해보겠습니다.

  • f-string을 이용한 동적 쿼리 생성법
  • SQL Injection 방지법 (✅ params 사용)
  • 실전 예제와 비교

📌 1. 기본 구조: MSSQL 접속과 쿼리 실행

import pyodbc

conn = pyodbc.connect(
    'DRIVER={ODBC Driver 17 for SQL Server};SERVER=서버주소;DATABASE=DB명;UID=아이디;PWD=비번'
)
cursor = conn.cursor()

💥 2. 잘못된 방법: f-string으로 직접 값을 넣는 경우

# ❌ SQL Injection 위험!
table = 'users'
status = 'active'

query = f"SELECT * FROM {table} WHERE status = '{status}'"
cursor.execute(query)

이런 방식은 입력값이 조작될 경우, 다음과 같은 공격이 가능합니다:

status = "'; DROP TABLE users; --"

실행 시:

SELECT * FROM users WHERE status = ''; DROP TABLE users; --'

🚨 실제 테이블이 삭제될 수도 있습니다.


✅ 3. 안전한 방법: 파라미터 바인딩 (? 또는 params)

table = 'users'
status = 'active'

# 테이블 이름은 f-string (주의 필요), 값은 parameter 바인딩
query = f"SELECT * FROM {table} WHERE status = ?"
cursor.execute(query, (status,))

? 위치에 안전하게 값이 바인딩되므로, SQL Injection 공격을 방지할 수 있습니다.

⚠️ 테이블명, 컬럼명은 바인딩할 수 없으므로 f-string 사용 시 꼭 화이트리스트 검증 필요!


🧠 4. 테이블 이름도 유동적인 경우 → 화이트리스트 사용

allowed_tables = ['users', 'orders', 'products']
input_table = 'users'

if input_table not in allowed_tables:
    raise ValueError("허용되지 않은 테이블명입니다.")

query = f"SELECT * FROM {input_table} WHERE status = ?"
cursor.execute(query, (status,))

✅ 이렇게 하면 f-string을 써도 안전하게 테이블명을 동적으로 넣을 수 있습니다.


🛠 5. 실전 예제: 날짜 필터 + 상태 필터 동적 조합

filters = []
params = []

# 날짜 조건
start_date = '2024-01-01'
end_date = '2024-12-31'
filters.append("created_at BETWEEN ? AND ?")
params += [start_date, end_date]

# 상태 조건
status = 'active'
if status:
    filters.append("status = ?")
    params.append(status)

where_clause = " AND ".join(filters)
query = f"SELECT * FROM users WHERE {where_clause}"

cursor.execute(query, params)

📌 동적 조건 조합 + 파라미터 바인딩 = 실무에서 가장 자주 사용하는 패턴!


🎯 마무리 요약

항목 설명
f-string 쿼리 구성은 편리하지만 값 직접 넣지 말 것
? 파라미터 SQL Injection 방지용 필수
테이블/컬럼명 반드시 화이트리스트 검증
복수 조건 조합 리스트로 조건 쌓고 join()으로 조합

✅ 쿼리를 동적으로 구성할 땐 항상 보안과 가독성을 동시에 고려해야 합니다.


🏷 태그

#Python #MSSQL #SQLInjection #파라미터바인딩 #쿼리자동화 #동적SQL #pyodbc

반응형