如何对Rails API参数进行清理处理

3
我正在制作自己的API,想知道如何保护接收到的参数?
例如:
  • 我有一个Car模型,具有“brand”和“color”属性。
我的端点接收到这些参数后,我会在数据库中进行搜索。
car = Car.where(color: params[:color])
# or
car = Car.find_by(brand: params[:brand])
# or writing
Car.first.update!(brand: params[:brand])

但是我非常担心如果有人试图利用SQL或XSS漏洞会怎么样? 你是如何处理这个问题的?
2个回答

6

你问题中的示例已经自动受到了防止 SQL 注入攻击的保护。

以下是官方 Rails Guides 中相关的引用:

7.2.1 Introduction

SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query:

Project.where("name = '#{params[:name]}'")

然后在同一篇文档中:

7.2.4 Countermeasures

Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character, and line breaks. Using Model.find(id) or Model.find_by_some thing(something) automatically applies this countermeasure. But in SQL fragments, especially in conditions fragments (where("...")), the connection.execute() or Model.find_by_sql() methods, it has to be applied manually.

Instead of passing a string, you can use positional handlers to sanitize tainted strings like this:

Model.where("zip_code = ? AND quantity >= ?", entered_zip_code, entered_quantity).first

The first parameter is a SQL fragment with question marks. The second and third parameter will replace the question marks with the value of the variables.

You can also use named handlers, the values will be taken from the hash used:

values = { zip: entered_zip_code, qty: entered_quantity }
Model.where("zip_code = :zip AND quantity >= :qty", values).first

Additionally, you can split and chain conditionals valid for your use case:

Model.where(zip_code: entered_zip_code).where("quantity >= ?", entered_quantity).first

嘿!谢谢你的一切!我非常开心。当我在谷歌上搜索时,我没有找到这个指南。再次感谢您的信息! :) - NaughtyDestiny
1
[Rails Guides] 是 Ruby on Rails 官方文档的一部分。我强烈建议阅读它。 - spickermann

-1
在大多数情况下,Rails会处理SQL注入问题。 因此,你应该避免将字符串作为参数传递给Active Records方法。避免使用以下方式:

Car.where("color = '#{params[:color]'")

而是使用数组或哈希表:

car = Car.where(color: params[:color])

car = Car.where(["color = ?", params[:color])

通过这样做,Active Records会自动转义不需要的字符,以防止SQL注入。

更多信息,请参阅Rails文档:https://guides.rubyonrails.org/security.html#sql-injection-countermeasures


我在@spickermann报告了一个重大错误之后更新了这个回复。

嗨,感谢您的回答!我花时间阅读了您的回答和链接。谢谢! 我明白了如何避免大多数SQL注入攻击。但是我不明白技术上“将其放入数组中”如何避免SQL注入攻击。 - NaughtyDestiny
car = Car.where(color: params[:color]) 在 Rails 中更为惯用,可以防止 SQL 注入。请注意 wherefind_by 是非常不同的方法,where 返回可链式操作的关系集合,而 find_by 则返回单个记录。 - spickermann
哦,所以你不同意亚历山德罗的观点?(抱歉我的英语不太好哈哈)。啊啊,我现在还没决定。编辑:是的,我可以接受findwhere之间的差异,谢谢! :) - NaughtyDestiny
2
是的,我不同意。请参考Rails指南中有关如何预防SQL注入的第三个示例。这正是您在提问中所应该做的。这是保护应用程序的首选方法。使用Hash语法没有任何问题。 - spickermann
是的@spickermann,我同意你的观点。我已经更新了回复。谢谢! - Alessandro De Simone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接