2015-07-24 4 views
0

Я создаю API с RoR 4 и PostgreSQL. Я хочу дать своим пользователям некоторые функции поиска через действие индекса в моих контроллерах. С этой целью я построил следующую функцию.Избегайте потенциальных SQL-инъекций

query_params является результатом params.permit в одном контроллере.

Вывод этой функции затем отправляется на активную запись where функция.

def searchable (query_params) 
    query = ''  
    query_params.each do |key, value| 
     value = value.to_s # Ensure this is a string or you will have crashes below 
     # Equals any of multiple values 
     if value[/\A(mul-)/] 
     value[0..3] = '' 
     query += "#{key} IN (#{value}) AND " 
     # Not a single value 
     elsif value[/\A(<>)/] 
     value[0..1] = '' 
     query += "(#{key} <> #{value}) AND "  
     # Bigger or smaller than a single value 
     elsif value[/\A[><]/] 
     operator = value[/\A[><]/] 
     value[0] = '' 
     query += "(#{key} #{operator} #{value}) AND "  
     # Equals a single value 
     else 
     query += "#{key} = '#{value}' AND " 

     end 
    end 
    query = query[0..-5] # removes the last AND 
    end 

Я беспокоюсь, что этот метод открывает мои DB до инъекций sql. Я прав? Если у вас есть пример возможной инъекции, это было бы здорово. Наконец, есть ли что-нибудь, что я могу сделать, чтобы блокировать инъекции?

Спасибо!

+2

должны использовать подготовленные заявления для смягчения против SQL инъекций – smoggers

+0

@smoggers как бы вы сделать это и сделать его динамичным, что позволяет пользователю API, чтобы выбрать, что искать? – UKatz

+1

Есть несколько довольно аккуратных решений для поиска с postgreSQL. Я думаю о gem pg_search (https://github.com/Casecommons/pg_search Если этого недостаточно =>, вы можете посмотреть http://api.rubyonrails.org/classes/ActiveRecord/Sanitization /ClassMethods.html#method-i-sanitize_sql –

ответ

3

Вы должны использовать функции запроса ActiveRecord по умолчанию, поскольку они защищают вас от большинства ошибок программистов. Кроме того, вы должны всегда проверять ввод пользователей, прежде чем передавать его на запросы БД.

Вопрос о RoR и его моделях заключается в том, чтобы отвлечь вас от БД, сделав ваше приложение (почти) DB-агностиком.

Кстати, этот сайт может быть полезным: http://rails-sqli.org/

EDIT: Еще одна вещь: никогда не передавать строки непосредственно в запросах модели. Вместо этого просто передайте хэш. Пример:

Не используйте:

Model.where("id = #{params[id]}") 

Вместо этого используйте:

Model.where(id: params[id]) 
+0

Вы имели в виду «Не использовать» Model.where («id = # {params [id]}») '?? –

+0

Да, мой плохой.) –

+1

Спасибо, сайт, на который вы ссылаетесь, вместе с собственной документацией Rail означает, что эта реализация не может быть и речи. Я буду искать другие методы или изучать драгоценные камни. – UKatz

0

После прочтения ответа @Miguel Кунья, я переписал код и он теперь в безопасности. Я хотел загрузить эти изменения, поскольку, по-моему, это могло бы быть полезно для других сравнить. В любом случае я рекомендую сначала посмотреть на драгоценные камни (и, возможно, на эластичный поиск).

# Permitted params makes sure keys cannot cause SQL injections! 
    def searchable (query_params) 
    query_keys = '' # Using array to prevent SQL injection 
    query_values = {} 
    query_params.each do |key, value| 
     value = value.to_s # Ensure this is a string or you will have crashes below 

     # Equals any of multiple values 
     if value[/\A(mul-)/] 
     query_keys += "#{key} IN (:#{key}) AND " 
     value[0..3] = '' 
     query_values[key.to_sym] = value.split(',') 
     # Not a single value 
     elsif value[/\A(<>)/] 
     query_keys += "#{key} <> :#{key} AND " 
     value[0..1] = '' 
     query_values[key.to_sym] = value 
     # Bigger or smaller than a single value 
     elsif value[/\A[><]/] 
     operator = value[/\A[><]/] 
     query_keys += "#{key} #{operator} :#{key} AND " 
     value[0] = '' 
     query_values[key.to_sym] = value 
     # Equals a single value 
     else 
     query_keys += "#{key} = :#{key} AND " 
     query_values[key.to_sym] = value 
     end 
    end 
    query_keys = query_keys[0..-5] # removes the last AND 
    query = [query_keys, query_values] 
    end 
Смежные вопросы