FlawOpen

flawopen.com/Injeção SQL em Go/GORM Raw SQL e injeção SQL

GORM Raw() é seguro contra injeção SQL? Vinculação de parâmetros em Go

CWE-89: SQL InjectionPágina de referência
Resposta curta

Pense no placeholder como um envelope fechado para um valor: o driver envia o valor separado das instruções SQL. GORM Raw() pode vincular o valor com segurança se o placeholder ficar na consulta e o valor for passado como argumento. Formatar entrada do usuário dentro da string SQL mistura o envelope às instruções e pode alterar a consulta.

INSEGURO
// Entrada controlada pelo usuário vira sintaxe SQL
db.Raw(fmt.Sprintf(
  "SELECT * FROM users WHERE id = %s",
  userID,
)).Scan(&user)
SEGURO
// O driver vincula userID como valor
db.Raw(
  "SELECT * FROM users WHERE id = ?",
  userID,
).Scan(&user)

SQL Raw seguro e vinculação de parâmetros no GORM

GORM e database/sql do Go vinculam valores quando os placeholders permanecem no SQL e os argumentos são passados separadamente, por exemplo db.Where("name = ?", userInput) ou db.Raw("SELECT ... WHERE id = ?", userID). Um placeholder representa um valor, não sintaxe SQL: nomes de tabelas, colunas, direções de ordenação e operadores não ficam seguros ao vinculá-los como valores. Escolha identificadores dinâmicos de uma allowlist fixa. Métodos como Order, Select, Table e Raw podem permitir injeção se a entrada do usuário for concatenada em seus fragmentos SQL.

Como procurar no código

rg -n --glob '*.go' '\.(Raw|Exec|Order|Select|Table)\s*\(' . rg -n --glob '*.go' 'fmt\.(Sprintf|Sprint)' .

Perguntas frequentes sobre GORM Raw SQL e vinculação de parâmetros

Os métodos encadeáveis do GORM são sempre seguros?

Não. Condições que passam valores separadamente, como Where("name = ?", input), usam vinculação de parâmetros. Concatenar a entrada na condição ou passá-la como sintaxe SQL bruta ainda permite injeção. Alguns métodos aceitam identificadores ou fragmentos SQL que não são escapados; revise os argumentos e use allowlists para a estrutura dinâmica.

Um placeholder pode vincular o nome de uma tabela ou coluna?

Não. Placeholders representam valores de dados. Para identificadores ou direções de ordenação dinâmicos, escolha opções fixas definidas pela aplicação e insira somente a constante validada na estrutura SQL.

Fontes oficiais e referências

Veja também SQL Injection (CWE-89): como funciona e como evitar em todas as linguagens — flawopen.com É suficiente escapar aspas contra SQL Injection? Usar um ORM basta para prevenir SQL Injection? Knex.js é seguro contra SQL Injection? MyBatis ${} vs #{}: evitar SQL Injection MySQLi vs PDO: prepared statements seguros NHibernate protege contra SQL Injection?