Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое 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-инъекция — это серьезная уязвимость, которая может привести к катастрофическим последствиям. Основное правило защиты: всегда используй параметризованные запросы. Это простой, но эффективный способ защиты, поддерживаемый всеми современными БД и фреймворками.