这个SQL注入是如何工作的? 需要说明
我正在学习RoR /数据库,这个话题让我特别困惑。 在“使用Rails 4开发敏捷开发”一书中,他们给出了一个例子,查找名为Dave的条目的所有订单列表:
pos = Order.where("name = 'Dave' and pay_type = 'po")
这本书继续说,你永远不会想要做这样的事情:
name = params[:name]
pos = Order.where("name = '#{name}'and pay_type = 'po'")
相反,你应该这样做:
name = params[:name]
pos = Order.where(["name = ? and pay_type = 'po'",name])
我明白,SQL注入是一个概念,但有一些细节让我感到困惑。 对于初学者来说,SQL注入是如何作为语法的。
我知道危险在于如果你像第一个例子那样插入一个外部表单参数,那么有人可以删除一个表/数据库,但是如何?
可以说你有这个:
name = params[:name] #DROP DATABASE database_name
pos = Order.where("name = '#{DROP DATABASE database_name}'and pay_type = 'po'")
这是SQL注入的工作原理吗? SQL是一种语法,数据库中应该没有字段,其中“name = DROP DATABASE database_name”,是否不会返回错误而不是丢失数据库?
此外,问号版本如何防止这种情况发生。 再次,假设您有这种情况。
name = params[:name] #DROP DATABASE database_name
pos = Order.where(["name = ? and pay_type = 'po'", DROP DATABASE database_name])
这是否不会用DROP DATABASE database_name语法替换问号,然后我们是否会遇到与第一个示例中相同的问题? 这究竟是如何保护针对SQL的应用程序? 我在http://hub.tutsplus.com/上搜索了一些教程并在Google上搜索,但我没有看到它背后的概念。 任何帮助?
我可以给出什么SQL注入最简单的解释是:
这可能会使SQL查询如下所示:
SELECT * FROM Order WHERE name = 'Dan' AND pay_type = 'po'
现在一个好用户会提供像上面这样的名字。
但是一个邪恶的用户(让我们称他为鲍比),将会提供这个名字: Bobby Tables'; DROP DATABASE master; --
Bobby Tables'; DROP DATABASE master; --
这会创建一个查询,如:
SELECT * FROM Order WHERE name = 'Bobby Tables'; DROP DATABASE master; --' AND pay_type = 'po'
这有效地执行了两个查询:
SELECT *
FROM Order
WHERE name = 'Bobby Tables';
DROP DATABASE master;
现在数据库不见了。 当他们将私人信息从数据库中提取出来时(比如用户名/密码或信用卡信息)
至于为什么这个问号现在神奇地保护你:
在RoR中使用问号使用称为参数化的模式。 当你参数化一个SQL查询时,你可以这样写它,以防止任何人进入一个成功的SQL注入。 在任何地方使用问号,它都被一个参数取代。 然后通过转义任何引号将该参数安全地设置为查询顶部的值。
如果您现在将Dan的名字提供给:
Order.where(["name = ? and pay_type = 'po'", params[:name])
该查询将如下所示:(RoR可能在内部略有不同,但效果相同)
DECLARE @p0 nvarchar(4000) = N'po',
@p1 nvarchar(4000) = N'Dan';
SELECT [t0].[ID], [t0].[name], [t0].[pay_type]
FROM Order AS [t0]
WHERE ([t0].[name] = @p1) AND ([t0].[pay_type] = @p1)
现在,如果邪恶的鲍比带着他的名字:鲍比桌子, DROP DATABASE master; -
如果将参数化(和转义引号)如下查询:
DECLARE @p0 nvarchar(4000) = N'po',
@p1 nvarchar(4000) = N'Bobby Tables''; DROP DATABASE master; --';
SELECT [t0].[ID], [t0].[name], [t0].[pay_type]
FROM Order AS [t0]
WHERE ([t0].[name] = @p1) AND ([t0].[pay_type] = @p1)
这现在是一个完全安全的查询
希望能帮助你理解
它与代码解释器的工作方式有关。
在第一个示例中,该参数只是作为文本插入,然后处理整个命令。 因此,问题。
在第二个示例中,首先解释命令,然后插入参数。 (IE,它解释“do语句where name = [some parameter]”,然后在它完成之后,添加参数)。所以你会得到一个非常奇怪的平等,其中name =“); drop table blah ;” 这当然不会工作,除非你的数据中有一些奇怪的名字。
请注意,注射必须实际正确地结束您的命令并启动一个新的命令 - 否则这只会导致错误。
这可能看起来像一个小问题,但如果你没有做到这一点,它会产生巨大的影响。 纪律非常重要。 如果你忘记了这一点,那么你将会面临糟糕的一天,因为一旦人们发现漏洞,人们可以做一些非常令人讨厌的事情。
每天都有另外一个例子,说明如果从一开始就不认真对待事情造成严重问题,导致一个小小的错误。 今天的例子:4chan由于单个参数没有被转义而被黑掉。 这就是所需要的。 一个错误。
尽可能为值使用SQL占位符。 不要采取捷径。 风险太高。
ActiveRecord有很多方法来编写不涉及直接操作查询的查询:
Order.where(name: 'name', pay_type: 'po')
只要有可能,就使用这些。 如果您遇到限制,尽可能安全地进行操作:
Order.where([ 'name LIKE ?', "%#{name}" ])
您也可以更直接地使用转义功能:
Order.sanitize(name)
如果您必须在查询中引入一些任意文本,请确保它已经通过验证。 始终制定一个非常狭窄的可接受参数列表。 不要因为排除规则而增加一些规则,从而让你忘记了一个规则。 严格得太严格了,太松懈了。
有了Rails,你的基础很好。 不要把它搞砸。 避免大量混乱的一种方法是使用单引号字符串,以便内插处于禁用状态:
Order.where('name="#{name}"') # Won't work, isn't interpolated.
这应该,如果养成了习惯,让你很不愿意切换到内插字符串。
如果您掌握了所有这一切,则需要牢记在HTML空间中完全相同的模式需要注意需要相同级别的规范的XSS和HTML注入问题。 在现代Rails中,所有用户数据都会在视图中自动进行HTML转义,但这对嵌入式JavaScript并不总是有帮助。 每当你有问题时,询问你所做的事情是否安全或不确定。
链接地址: http://www.djcxy.com/p/16769.html上一篇: How this SQL injection works? Explanation needed
下一篇: How can prepared statements protect from SQL injection attacks?