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

4. Тотальное использование Prepared Statements

Тотальное использование Prepared Statements: Золотое правило

Стратегия «тотального использования Prepared Statements» (Universal Prepared Statements) — это единственный надежный способ полностью исключить риск инъекций второго порядка. Правило предельно простое: ни одного SQL-запроса не должно создаваться через конкатенацию строк или fmt.Sprintf. Это ограничение должно действовать даже для данных, которые вы считаете «проверенными».

Разберем, почему отказ от исключений в этом правиле делает ваш код по-настоящему устойчивым.


1. Механика: "Ни одного исключения"

В разработке легко поддаться соблазну: «Я точно знаю, что userID — это число, поэтому напишу fmt.Sprintf("WHERE id=%d", id)». Это опасный путь. Даже если данные кажутся безопасными, любая конкатенация создает потенциальную точку взлома.

Золотой стандарт Go-разработки:

// Всегда используйте плейсхолдеры
query := "SELECT name FROM users WHERE id = $1"
db.QueryRow(query, id)

Такой подход делает ваш код однообразным, предсказуемым и, что важнее всего, на 100% защищенным от атак на внедрение кода.


2. Безопасность с использованием sqlx

Библиотека sqlx популярна в Go-сообществе за её удобство, и она поощряет использование параметров на уровне дизайна:

// ✅ ПРАВИЛЬНЫЙ Go-код с sqlx
user := User{}
// sqlx автоматически корректно подставит userID
err := db.Get(&user, "SELECT * FROM users WHERE id=$1", userID)

В такой архитектуре инъекция становится технически невозможной, даже если входные данные содержат вредоносные инструкции вроде 1 OR 1=1.


3. Query Builder: squirrel (Masterminds)

Для динамических запросов, где SQL конструируется по условиям (фильтры, сортировка, пагинация), удобен query builder squirrel. Он генерирует параметризованный SQL программно, исключая ручную конкатенацию:

import sq "github.com/Masterminds/squirrel"

// ✅ ПРАВИЛЬНЫЙ Go-код с squirrel
query, args, err := sq.Select("username", "fullname").
    From("users").
    Where(sq.Like{"fullname": "%" + searchTerm + "%"}).
    Where(sq.NotEq{"id": currentUserID}).
    ToSql()

rows, err := db.Query(query, args...)

Squirrel автоматически подставляет плейсхолдеры — вы не можете случайно вставить данные в SQL-строку. Это особенно ценно для second-order сценариев, где данные из БД повторно используются в запросах.


4. Сравнение инструментов: database/sql, sqlx, squirrel и GORM

Инструмент Риск ошибки Лучшая практика Оценка безопасности
database/sql Высокий Использование QueryContext 🟡 Требует дисциплины
sqlx Средний Get() и Select() с плейсхолдерами 🟢 Рекомендуется
squirrel Низкий Select().From().Where() — fluent API 🟢 Безопасно по дизайну
GORM Низкий Методы Where(), First() 🟢 Безопасно по умолчанию

5. Эффективность и производительность

Существует миф, что подготовленные выражения замедляют систему. На практике всё наоборот: современные СУБД кэшируют план выполнения для запросов с плейсхолдерами. Повторный вызов функции с новыми параметрами будет работать быстрее, чем парсинг новой SQL-строки, созданной через fmt.Sprintf. Безопасность в Go идет рука об руку с производительностью.


Тотальное использование плейсхолдеров — это ваша гарантия качества кода. Если вы полностью исключите конкатенацию из работы с базой данных, любые попытки хакера совершить инъекцию второго порядка останутся лишь бесполезным текстом в ваших таблицах.

Мы завершили изучение инъекций второго порядка. После квиза нас ждет погружение в одну из самых современных и сложных тем — Out-of-Band и OAST атаки.

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

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

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

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