Перейти к содержимому
Назад к пути
Теория 4 мин чтения

1. Сравнительный анализ методов защиты

Сравнительный анализ методов защиты от SQL-инъекций

На протяжении всего курса мы изучали различные методы защиты от SQL-инъекций: от prepared statements до network policies. В этом завершающем обзоре мы сведём все техники в единую картину и определим, когда и какой метод применять.

Уровни защиты: Defence in Depth

Надёжная защита от SQL-инъекций строится по принципу эшелонированной обороны (defence in depth). Ни один метод не является универсальным — комбинация техник на разных уровнях обеспечивает максимальную безопасность.

Уровень 1: Код приложения

Метод Защищает от Ограничения Когда применять
Prepared Statements Все классические SQLi (UNION, Boolean, Time-based, Second-Order) Не применимы к динамическим идентификаторам (ORDER BY, имена таблиц) Всегда — это основа защиты
ORM (GORM, sqlx) Классические SQLi через автоматическую параметризацию Raw-запросы в ORM остаются уязвимыми Для стандартных CRUD-операций
Whitelist валидация ORDER BY injection, динамические идентификаторы Требует ручного обновления при изменении схемы Для динамических колонок, сортировки, фильтров
Типизация ввода Инъекции в числовые параметры Не помогает для строковых полей Для ID, limit, offset
// Prepared Statements — основа защиты
row := db.QueryRowContext(ctx, "SELECT * FROM users WHERE id = ?", userID)

// Whitelist — для динамических идентификаторов
allowedColumns := map[string]bool{"name": true, "email": true, "created_at": true}
if !allowedColumns[sortColumn] {
    sortColumn = "created_at" // безопасное значение по умолчанию
}
query := fmt.Sprintf("SELECT * FROM users ORDER BY %s", sortColumn)

// Типизация — для числовых параметров
id, err := strconv.Atoi(rawID)
if err != nil {
    http.Error(w, "Invalid ID", http.StatusBadRequest)
    return
}

Уровень 2: База данных

Метод Защищает от Ограничения Когда применять
Принцип наименьших привилегий Эскалацию последствий (DROP, INSERT в системные таблицы) Не предотвращает саму инъекцию Всегда — при настройке БД
Отдельные пользователи для read/write Утечку данных через write-only контексты Сложнее управление миграциями Для production-систем
Ограничение доступа к системным таблицам Enumeration через information_schema Ограничивает возможности администрирования Для production
-- Создание пользователя только для чтения
CREATE USER app_reader WITH PASSWORD 'secure_password';
GRANT SELECT ON users, products, orders TO app_reader;

-- Создание пользователя для записи
CREATE USER app_writer WITH PASSWORD 'another_password';
GRANT SELECT, INSERT, UPDATE ON users, products, orders TO app_writer;
-- НЕ давать DELETE, DROP, ALTER

Уровень 3: Инфраструктура

Метод Защищает от Ограничения Когда применять
WAF (Web Application Firewall) Известные паттерны атак Обход через кодировки, JSON, нестандартный синтаксис Как дополнительный слой
Network Policies (Egress) Out-of-Band exfiltration Не предотвращает in-band атаки Для K8s / облачных сред
Таймауты (context.WithTimeout) Time-based blind SQLi, DoS через тяжёлые запросы Не предотвращает быстрые инъекции Всегда — для всех запросов к БД
Rate Limiting Автоматизированные атаки (sqlmap) Не помогает против ручной эксплуатации Для публичных эндпоинтов
// Таймаут запроса — обязательная практика
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()

row := db.QueryRowContext(ctx, "SELECT * FROM users WHERE email = ?", email)

Уровень 4: Мониторинг и детекция

Метод Защищает от Ограничения Когда применять
Логирование аномальных запросов Помогает обнаружить атаку постфактум Не предотвращает атаку Всегда
Alerting на SQL-ошибки Раннее обнаружение попыток инъекции Ложные срабатывания Для production
Slow query log Обнаружение time-based атак Шум от легитимных тяжёлых запросов Для production

Матрица: Тип атаки vs Метод защиты

Тип атаки Prepared Statements Whitelist Типизация WAF Таймауты Network Policies
Classic (UNION) + - - +/- - -
Boolean-based Blind + - - +/- - -
Time-based Blind + - - +/- + -
Second-Order + - - - - -
ORDER BY injection - + - +/- - -
Out-of-Band (OOB) + - - - - +
WAF Bypass + + + - - -
Automated (sqlmap) + + + +/- - -

Легенда: + = эффективно, - = не помогает, +/- = частично помогает

Рекомендуемый минимум для Go-проекта

Каждый Go-проект, работающий с базой данных, должен включать как минимум:

// 1. Prepared Statements для ВСЕХ запросов
db.QueryContext(ctx, "SELECT ... WHERE col = ?", param)

// 2. Таймауты на каждый запрос
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()

// 3. Whitelist для динамических частей
func safeSortColumn(input string) string {
    allowed := map[string]string{
        "name": "name",
        "date": "created_at",
        "price": "price",
    }
    if col, ok := allowed[input]; ok {
        return col
    }
    return "created_at"
}

// 4. Типизация числовых параметров
func safeIntParam(raw string, defaultVal int) int {
    val, err := strconv.Atoi(raw)
    if err != nil || val < 0 {
        return defaultVal
    }
    return val
}

Антипаттерны: что НЕ делать

  1. Не полагаться только на WAF — он обходится (см. Модуль 9)
  2. Не использовать чёрные списки (blacklisting) — всегда найдётся способ обхода
  3. Не экранировать вручную (strings.ReplaceAll(input, "'", "''")) — это ненадёжно
  4. Не доверять данным из БД — Second-Order SQLi использует именно это доверие
  5. Не игнорировать ORM raw-запросыdb.Raw("SELECT * FROM users WHERE name = '" + name + "'") так же уязвим

Заключение

Защита от SQL-инъекций — это не один инструмент, а система мер на всех уровнях: от написания безопасного кода до настройки инфраструктуры и мониторинга. Prepared statements являются фундаментом, но без дополнительных слоёв (whitelist, таймауты, network policies, логирование) защита остаётся неполной.

Продолжить чтение

Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу

Когда закончишь — отметь раздел, чтобы продолжить.

🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru