FlawOpen

flawopen.com/SQL Injection em Ruby/ActiveRecord where()

Interpolação em where() do Rails é segura?

Página de referência
Resposta curta

Pense no SQL como um formulário com instruções fixas e campos vazios para valores. Um parâmetro vinculado preenche um campo; a interpolação Ruby insere o texto da requisição nas instruções antes que Rails possa separar as partes. Mantenha a estrutura SQL fixa e passe valores não confiáveis como parâmetros.

UNSAFE
User.where(
  "id = #{params[:id]}"
)
SAFE
User.where(id: params[:id])
# or, for more complex conditions:
User.where("id = ?", params[:id])

Por que a interpolação altera a consulta

Ruby avalia #{...} antes de Active Record receber a condição. Por exemplo, where("id = #{params[:id]}") entrega ao Rails uma string SQL já combinada; a entrada da requisição pode então alterar o predicado. Active Record documenta esse padrão de montagem de strings como inseguro. Use um hash para condições compatíveis de igualdade, intervalo ou subconjunto, ou use marcadores ? para outros predicados. Os marcadores vinculam valores, não identificadores nem palavras-chave SQL; mantenha a estrutura da consulta fixa ou selecione identificadores por uma lista de permissões estrita.

Como verificar seu código

rg -n 'where\s*\(' app/
Revise os resultados em busca de dados da requisição interpolados ou concatenados em strings de condição. Brakeman relata riscos de SQL Injection quando sua análise identifica fluxo de dados inseguro; uma varredura limpa não prova que todas as consultas são seguras.

Perguntas frequentes

Posso usar condições hash em qualquer consulta?

Não. As condições hash do Rails aceitam igualdade, intervalo e subconjunto (IN). Para outros predicados, use uma condição SQL fixa com valores vinculados, como where("price > ?", amount). A vinculação protege valores; ela não torna seguros nomes dinâmicos de tabelas, colunas ou fragmentos SQL.

Referências

Veja também SQL Injection (CWE-89): como funciona e como evitar em todas as linguagens — flawopen.com Sequelize query() é seguro contra SQL Injection? SQLAlchemy text() é seguro contra SQL Injection? A verificação de consultas do sqlx em compilação evita SQL injection? Procedimentos armazenados evitam SQL injection? O QueryBuilder do TypeORM é seguro contra SQL Injection? Django ORM e SQL Injection: padrões seguros