← Назад к вопросам

Что такое SQL-инъекция?

1.0 Junior🔥 201 комментариев
#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое SQL-инъекция?

SQL-инъекция (SQL Injection) — это вид кибератаки, при которой злоумышленник вставляет (инъектирует) вредоносный SQL код в поле ввода приложения. Результат: несанкционированный доступ к базе данных, кража данных, удаление информации или модификация БД.

Пример уязвимого кода

# ОПАСНО: SQL-инъекция возможна
username = input("Введите имя пользователя: ")
password = input("Введите пароль: ")

query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
result = db.execute(query)

# Если пользователь введет:
# username: admin' --
# query станет: SELECT * FROM users WHERE username='admin' --' AND password='...'
# Комментарий -- отключит проверку пароля!

Как работает SQL-инъекция

Нормальный запрос:

SELECT * FROM users WHERE username='john' AND password='pass123'

Со взломом:

-- Input: admin' --
SELECT * FROM users WHERE username='admin' --' AND password='...'
-- Всё после -- игнорируется, пароль не проверяется!

Другой вариант:

-- Input: ' OR '1'='1
SELECT * FROM users WHERE username='' OR '1'='1' AND password='...'
-- '1'='1' всегда true, вернутся все пользователи!

Типы SQL-инъекций

1. Union-based SQL Injection

# Уязвимый код
search = input("Поиск: ")
query = f"SELECT id, name FROM products WHERE name LIKE '%{search}%'"

# Атака: ' UNION SELECT username, password FROM users --
# Результат: возвращаются пароли пользователей!

2. Error-based SQL Injection

# Уязвимый код
product_id = input("ID: ")
query = f"SELECT * FROM products WHERE id={product_id}"

# Атака: 1 OR 1=1; DROP TABLE users; --
# Может удалить таблицу!

3. Blind SQL Injection

# Уязвимый код
username = input("Username: ")
query = f"SELECT * FROM users WHERE username='{username}'"
result = db.execute(query)

# Атака: admin' AND '1'='1
# Сообщение об ошибке раскрывает информацию о структуре БД

Защита: Parameterized Queries (Подготовленные запросы)

Это главная защита от SQL-инъекций!

# БЕЗОПАСНО: используются параметризованные запросы
import sqlite3

conn = sqlite3.connect(':memory:')
cursor = conn.cursor()

username = input("Введите имя пользователя: ")
password = input("Введите пароль: ")

# ? — параметр-заполнитель
query = "SELECT * FROM users WHERE username=? AND password=?"
result = cursor.execute(query, (username, password))

# Даже если ввести: admin' -- 
# SQL база обработает это как строку, не как SQL код

Примеры защиты в популярных библиотеках

SQLAlchemy ORM

# БЕЗОПАСНО: ORM автоматически использует параметризацию
from sqlalchemy import select
from sqlalchemy.orm import Session

username = "admin' --"  # Потенциально опасный ввод

# ORM защищает от инъекций
user = session.query(User).filter(User.username == username).first()

# Или с select API
stmt = select(User).where(User.username == username)
user = session.execute(stmt).scalar()

Использование параметров в raw SQL

from sqlalchemy import text

# БЕЗОПАСНО: raw SQL с параметрами
username = input("Username: ")
password = input("Password: ")

query = text(
    "SELECT * FROM users WHERE username=:username AND password=:password"
)
result = db.execute(query, {"username": username, "password": password})

# :username и :password — параметры, не подставляются напрямую

Django ORM

# БЕЗОПАСНО: Django ORM защищает от инъекций
from django.contrib.auth.models import User

username = request.GET.get('username')
user = User.objects.filter(username=username).first()  # Безопасно

# Или с raw SQL (все равно безопасно):
User.objects.raw(
    'SELECT * FROM auth_user WHERE username = %s',
    [username]  # Параметры как массив
)

Худший сценарий

# ЭКСТРЕМАЛЬНО ОПАСНО
username = input("Username: ")
password = input("Password: ")

# Прямое выполнение пользовательского SQL
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
db.execute(query)

# Злоумышленник может:
# - Украсть все данные
# - Удалить базу данных
# - Вставить вредоносные данные
# - Отключить аудит и логирование

Чеклист защиты

✓ Всегда используй параметризованные запросы
✓ Используй ORM (SQLAlchemy, Django ORM и т.д.)
✓ Валидируй входные данные (но не полагайся только на это)
✓ Используй Principle of Least Privilege для учетных записей БД
✓ Логируй все попытки доступа к БД
✓ Регулярно обновляй базу данных
✓ Используй WAF (Web Application Firewall)
✓ Проводи security testing и penetration testing
✓ Не показывай подробные ошибки БД пользователю
✓ Шифруй чувствительные данные

Примеры правильной валидации

import re
from typing import Optional

def validate_username(username: str) -> bool:
    # Проверяем формат, но не полагаемся только на это!
    return bool(re.match(r'^[a-zA-Z0-9_]{3,20}$', username))

def get_user_secure(username: str, password: str) -> Optional[User]:
    # 1. Валидируем входные данные
    if not validate_username(username):
        raise ValueError("Invalid username format")
    
    # 2. Используем параметризованный запрос
    query = "SELECT * FROM users WHERE username = ? AND password = ?"
    user = db.execute(query, (username, password)).first()
    
    # 3. Не показываем деталей ошибок
    if not user:
        logger.warning(f"Failed login attempt for {username}")
        raise AuthenticationError("Invalid credentials")
    
    return user

OWASP Top 10

SQL-инъекция является частью OWASP Top 10 — списка самых критичных веб-уязвимостей. Это одна из самых важных проблем безопасности, которую необходимо знать каждому разработчику.

Заключение

SQL-инъекция — это серьезная уязвимость, которая может привести к катастрофическим последствиям. Основное правило защиты: всегда используй параметризованные запросы. Это простой, но эффективный способ защиты, поддерживаемый всеми современными БД и фреймворками.

Что такое SQL-инъекция? | PrepBro