Каков наилучший способ избежать инъекции sql?

Я использую рубин 1.8.7 и рельсы 2.3.2.

Следующий код подвержен SQL-инъекциям

params[:id] = "1) OR 1=1--"
User.delete_all("id = #{params[:id]}")

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

User.delete_all("id = #{params[:id].to_i}")

person Richa Sinha    schedule 20.10.2014    source источник


Ответы (4)


Что о:

User.where(id: params[:id]).delete_all

Хорошо, извините за Rails 2.x:

User.delete_all(["id = ?", params[:id]])

Проверить документ

Кстати, убедитесь, что вы хотите использовать delete_all вместо destroy_all, первый не вызывает обратных вызовов.

person apneadiving    schedule 20.10.2014
comment
Спасибо. Я полагаю, что это лучший способ избежать инъекции sql. Есть ли недостаток использования to_i? - person Richa Sinha; 21.10.2014
comment
Не особо, но и смысла в этой паудовалидации тоже не вижу - person apneadiving; 21.10.2014
comment
Я имею в виду, что Rails сделает это за вас, так что не загрязняйте свой код. - person apneadiving; 21.10.2014

Вы также можете использовать это

User.delete(params[:id])
person anusha    schedule 20.10.2014

Другие ответы хорошо отвечают на этот вопрос для Rails, и все будет хорошо, если вы будете следовать их предложениям. В более общем случае, когда вам нужно справиться с этим самостоятельно, вы обычно можете использовать регулярное выражение для извлечения значения в ожидаемом формате. Это действительно просто с целочисленным идентификатором. Подумайте об этом так:

if params[:id] =~ /(\d+)/
  safe_id = $1.to_i
  # do something with safe_id now
end

Это становится немного сложнее, когда вы работаете со строками и произвольными данными. Если вам необходимо обрабатывать такие данные, вы можете использовать методы цитирования, доступные для адаптеров баз данных. В Rails это в конечном итоге превращается в согласованный интерфейс:

safe_string = ActiveRecord::Base.connection.quote(unsafe_string)

Для большинства систем баз данных это будет обрабатывать одинарные кавычки и обратную косую черту особым образом.

Если вы не используете Rails, вам придется использовать методы цитирования, специфичные для вашего адаптера базы данных, но их использование очень похоже.

Вывод:

  1. Если ваши данные имеют определенный формат, задайте формат с помощью регулярного выражения.
  2. В противном случае используйте функцию цитирования вашего адаптера базы данных, чтобы сделать данные «безопасными» для использования в запросе.
  3. Rails справится с большей частью этого за вас, если вы правильно используете различные методы и «условия».
person Michael Chaney    schedule 20.10.2014

Используйте методы rails для передачи параметров where. Вы всегда можете жестко закодировать их, как в приведенном вами примере, но обычный способ будет выглядеть примерно так:

User.where(:id => params[:id]).delete_all
User.where("id = ?", params[:id]).delete_all
User.where("id = :id", :id => params[:id]).delete_all

Они хорошо протестированы, и в случае обнаружения новой уязвимости обновление устранит проблему, и ваш код не нужно будет менять.

Кстати, если вы просто хотите удалить 1 запись на основе ее идентификатора, я бы сделал следующее:

User.find(params[:id]).destroy

person Fer    schedule 20.10.2014