12

In Rails 3 Potrei usare sanitize_sql_array per disinfettare SQL raw per quei momenti occasionali in cui è necessaria una query SQL raw. Ma sembra che sia stato rimosso in Rails 4, o non così tanto rimosso, ma spostato su ActiveRecord :: Sanitization. Tuttavia, non riesco a capire come chiamare sanitize_sql_array ora, quindi qual è il modo migliore per disinfettare SQL raw in Rails 4?Come disinfettare SQL raw in Rails 4

Desidero chiarire che sto parlando di una query SQL completa completa qui, non utilizzando i modelli di Rail. Sono consapevole che questa non è una buona pratica, questo è proprio quello che devo fare per questa specifica query poiché non può essere rappresentata dalla bella interfaccia ActiveRecord di Rails (credimi, ho provato).

Ecco un esempio di richiamo, che è ovviamente più semplice di quello che la mia interrogazione si presenta come:

query = "SELECT * FROM users 
LEFT OUTER JOIN posts ON users.id=posts.user_id 
AND posts.topic_id = '#{topic.id}'" 
# ^- Obviously bad and very vulnerable, this is what we're trying to fix 
ActiveRecord::Base.connection.select_all(query) 

risposta

0

Dal Active Record docs, il modo migliore per disinfettare una query SQL è quello di evitare a costruire il nostro condizioni stringhe puri, in altre parole, inserisce i parametri direttamente nella query, in questo modo:

User.find_by("user_name = '#{user_name}' AND password = '#{password}'") 

invece utilizzare condizioni array o di hash.

condizioni Array:

Client.where("orders_count = ? AND locked = ?", params[:orders], false) 

condizioni Hash:

Client.where(is_active: true) 

Un esempio chiarificatore:

class User < ActiveRecord::Base 
    # UNSAFE - susceptible to SQL-injection attacks 
    def self.authenticate_unsafely(user_name, password) 
    where("user_name = '#{user_name}' AND password = '#{password}'").first 
    end 

    # SAFE 
    def self.authenticate_safely(user_name, password) 
    where("user_name = ? AND password = ?", user_name, password).first 
    end 

    # SAFE 
    def self.authenticate_safely_simply(user_name, password) 
    where(user_name: user_name, password: password).first 
    end 
end 

Ecco alcuni riferimenti:

+2

Ehi Nick, grazie per la risposta, ma ero alla ricerca di una risposta che avrebbe lavorato per le query SQL prime che non passano attraverso i modelli ActiveRecord. Ho aggiornato la mia domanda per renderlo un po 'più chiaro. –

+0

@ColtonVoege Mi dispiace, ho frainteso la domanda. Come ha detto @gabrielhilal, 'quote' è il modo giusto per disinfettare una query sql raw senza utilizzare il modello ActiveRecord – NickGnd

+0

Questa risposta è così sbagliata, usando' '# {user_name}' è venerabile all'iniezione SQL. – Hardik

11

Se avete veramente bisogno di scrivere SQL prime è possibile utilizzare quote per igienizzare esso:

conn = ActiveRecord::Base.connection 
name = conn.quote("John O'Neil") 
title = conn.quote(nil) 
query = "INSERT INTO users (name,title) VALUES (#{name}, #{title})" 
conn.execute(query)