12

W Rails 3 mogę użyć sanitize_sql_array do odkażenia surowego SQL dla chwilowych momentów, w których potrzebne jest surowe zapytanie SQL. Wydaje się, że zostało to usunięte w Railsach 4 lub nie zostało usunięte, ale przeniesione do ActiveRecord :: Sanitization. Jednak nie mogę teraz dowiedzieć się, jak nazwać sanitize_sql_array teraz, więc jaki jest najlepszy sposób na odkażenie surowego SQL w Rails 4?Jak odkazić surowego SQL w Railsach 4

Chcę wyjaśnić, że mówię tu o pełnym surowym zapytaniu SQL, nie używając modeli Rail. Jestem świadomy, że to nie jest najlepsza praktyka, to jest właśnie to, co muszę zrobić dla tego konkretnego zapytania, ponieważ nie może być reprezentowany przez ładny interfejs ActiveRecord Railsów (Zaufaj mi, próbowałem).

Oto wezwanie próbki, co jest oczywiście prostsze niż to, co moje zapytanie faktycznie wygląda:

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) 

Odpowiedz

0

Z Active Record docs, najlepszym sposobem, aby zdezynfekować zapytanie SQL jest uniknąć zbudować nasz własny warunki czystego łańcucha, innymi słowy, wprowadza parametry bezpośrednio do zapytania, w następujący sposób:

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

i zamiast warunków użytkowania tablicy lub mieszania.

warunki tablicy:

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

warunki Hash:

Client.where(is_active: true) 

klarujący przykład:

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 

Oto niektóre odniesienia:

+2

Hej Nick, dzięki za odpowiedź, ale szukałem odpowiedzi, że będzie pracować dla surowych zapytań SQL, które nie przechodzą przez modele ActiveRecord. Zaktualizowałem moje pytanie, aby było to trochę bardziej zrozumiałe. –

+0

@ColtonVoege Przepraszam, źle zrozumiałem pytanie. Jak powiedział @gabrielhilal, 'quote' jest właściwą metodą dezynfekcji surowego zapytania sql bez użycia ActiveRecord Model – NickGnd

+0

Ta odpowiedź jest tak bardzo zła, używając' '# {user_name}' 'jest czcigodny dla SQL injection. – Hardik

11

Jeśli naprawdę trzeba pisać surowego SQL można używać quote aby je zdezynfekować:

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) 
Powiązane problemy