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

6. Защита: ORM vs Raw SQL

Защита: ORM vs Raw SQL

Один из самых частых вопросов Go-разработчика: «Обезопасит ли меня использование ORM?». Ответ прост: ORM помогает, но не является панацеей. Мы разберем, почему популярные библиотеки вроде GORM считаются «безопасными по дизайну» и как неосторожный вызов может свести всю эту защиту на нет.

Сравним разные подходы к работе с БД и выясним, где затаились ловушки.


1. Механика: "Автоматическая безопасность"

В чистом Go (database/sql) вы ДОЛЖНЫ помнить про плейсхолдеры ? или $1. Если вы забудете — вы уязвимы. В ORM, таких как GORM, вы работаете с объектами:

// ✅ ПРАВИЛЬНЫЙ Go-код (GORM)
var user User
db.Where("username = ?", username).First(&user)

GORM по умолчанию использует Prepared Statements под капотом. Вам не нужно об этом думать.


2. Ловушка: Сырые запросы в ORM

Но даже в самых лучших ORM есть способ выстрелить себе в ногу. Это функции "сырого" SQL или неверное использование фильтров.

// ❌ СМЕРТЕЛЬНО ОПАСНО в GORM
db.Where(fmt.Sprintf("username = '%s'", username)).First(&user)

Если вы внутри ORM используете fmt.Sprintf — вы ПОВТОРЯЕТЕ всё те же ошибки, о которых мы говорили раньше. ORM не магическая стена, это просто помощник.


3. Таблица сравнения: Raw SQL vs sqlx vs GORM

Характеристика Чистый Go (Raw SQL) sqlx GORM (ORM)
Безопасность 🌕 Нужно бдеть самому 🌖 Помогает с именами 🌕 По умолчанию безопасно
Гибкость 🟢 Максимальная 🟢 Высокая 🟡 Ограниченная
Риск 🔴 Очень высокий (Sprintf) 🟡 Средний (Raw SQL) 🟢 Низкий (если не Raw)

4. Почему GORM иногда подводит?

Иногда разработчики пишут сложные JOIN или сортировки, используя ввод пользователя напрямую в db.Order(userInput). Именно здесь рождаются SQL-инъекции в современных Go-приложениях.


5. sqlx: именованные параметры как защита от ошибок

В чистом database/sql с тремя–четырьмя ?-плейсхолдерами легко перепутать порядок аргументов. Библиотека github.com/jmoiron/sqlx — это тонкая надстройка над stdlib, которая добавляет именованные параметры (:param) и автоматический маппинг строк в структуру.

import "github.com/jmoiron/sqlx"

// Один раз оборачиваем *sql.DB → *sqlx.DB
dbx := sqlx.NewDb(db, "sqlite3")

// Именованный параметр :search вместо позиционного ?
query := "SELECT id, name, description, price FROM products WHERE name LIKE :search"

rows, err := dbx.NamedQuery(query, map[string]interface{}{
    "search": "%" + userInput + "%",
})
if err != nil { /* ... */ }
defer rows.Close()

for rows.Next() {
    var p Product
    if err := rows.StructScan(&p); err == nil { /* ... */ }
}

Почему это безопасно: под капотом NamedQuery использует ту же параметризацию, что и database/sql — значение :search передаётся отдельно от шаблона. Даже если ввод содержит ' UNION SELECT ..., база воспримет это как обычную строку для LIKE-сравнения. Бонус: при четырёх и более параметрах именованная форма читается лучше позиционной, а ошибка «перепутал аргументы» становится практически невозможной.


6. Сравнение Fix A (stdlib) vs Fix B (sqlx) для UNION-защиты

Критерий Fix A: db.Query("... LIKE ?", "%"+v+"%") Fix B: sqlx.NamedQuery(":search")
Зависимости Только stdlib github.com/jmoiron/sqlx
Читаемость при 3+ параметрах Средняя (позиционные ?) Высокая (именованные :param)
Маппинг в структуру Ручной Scan(&p.ID, &p.Name, ...) Автоматический StructScan(&p)
Производительность Максимальная Минимальный оверхед
Защита от SQLi Полная (parametrized) Полная (parametrized)
Когда выбрать Простые запросы, минимум зависимостей Проекты с большим количеством SQL

Оба подхода эквивалентны по уровню безопасности — драйвер всё равно отправляет в БД отдельный pre-compiled шаблон. Выбор только между «ничего лишнего в зависимостях» и «удобство при росте кодовой базы».


ORM — не панацея, но мощный союзник. Если вы понимаете, как они работают, и не пытаетесь их обмануть сырыми запросами, вы существенно снижаете риск взлома своего приложения.

Вы изучили теорию UNION-атак и готовы к практике. Проверьте свои знания в квизе, а затем приступайте к лабораторной работе по извлечению данных из базы.

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

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

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

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