Избегание риска SQL-инъекций

Вы можете избежать риска SQL-инъекций, передавая значения параметров SQL в качестве аргументов функций пакета sql. Многие функции пакета sql предоставляют параметры для SQL-запроса и значения, которые будут использоваться в параметрах этого запроса (другие предоставляют параметр для подготовленного запроса и параметры).

Код в следующем примере использует символ ? в качестве заполнителя для параметра id, который передается как аргумент функции:

<code>// Корректный формат выполнения SQL-запроса с параметрами.
rows, err := db.Query("SELECT * FROM user WHERE id = ?", id)
</code>

Функции пакета sql, выполняющие операции с базой данных, создают подготовленные запросы из переданных вами аргументов. Во время выполнения пакет sql преобразует SQL-запрос в подготовленный запрос и отправляет его вместе с параметром, который передаётся отдельно.

Примечание: Заполнители параметров могут различаться в зависимости от используемой СУБД и драйвера. Например, драйвер pq для Postgres принимает форму заполнителя вида $1 вместо ?.

Вы можете быть соблазнены использовать функцию из пакета fmt для сборки SQL-запроса в виде строки с включенными параметрами — например, так:

<code>// РИСК БЕЗОПАСНОСТИ!
rows, err := db.Query(fmt.Sprintf("SELECT * FROM user WHERE id = %s", id))
</code>

Это небезопасно! Когда вы делаете это, Go собирает весь SQL-запрос, заменяя форматный спецификатор %s значением параметра, прежде чем отправить полный запрос в СУБД. Это создаёт риск SQL-инъекции, поскольку вызывающий код может передать неожиданный фрагмент SQL в качестве аргумента id. Этот фрагмент может завершить SQL-запрос неожиданным образом, что представляет опасность для вашего приложения.

Например, передавая определённое значение %s, можно получить следующий результат, который может вернуть все записи пользователей из вашей базы данных:

<code>SELECT * FROM user WHERE id = 1 OR 1=1;
</code>
GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang