如果我从 SQL 查询中删除所有 ' 字符,还有其他方法可以对数据库进行 SQL 注入攻击吗?
如何做呢?谁能给我例子?
就在这里。摘自维基百科
"SELECT * FROM data WHERE id = " + a_variable + ";"
从该声明中可以清楚地看出,作者希望 a_variable 是与“id”字段相关的数字。但是,如果它实际上是一个字符串,那么最终用户可以根据他们的选择来操作语句,从而绕过对转义字符的需要。例如,将 a_variable 设置为
1;DROP TABLE users
将从数据库中删除(删除)“用户”表,因为 SQL 将呈现如下:
SELECT * FROM DATA WHERE id=1;DROP TABLE users;
SQL注入不是简单的攻击。如果我是你,我会做非常仔细的研究。
是的,取决于您使用的语句。您最好通过使用存储过程或至少参数化查询来保护自己。
有关预防样本,请参见Wikipedia 。
是的,这绝对是可能的。
如果您有一个表单,其中您希望一个整数来创建您的下一个 SELECT 语句,那么您可以输入任何类似的内容:
SELECT * FROM thingy
WHERE 属性 ID=
users
;(糟糕,糟糕,糟糕……)以下网站详细介绍了经典的 SQL 注入技术:SQL Injection cheat sheet。
使用参数化查询或存储过程也好不到哪里去。这些只是使用传递参数的预制查询,也可以是注入源。本页也对此进行了描述:攻击 SQL 中的存储过程。
现在,如果你禁止简单的引用,你只能阻止一组给定的攻击。但不是全部。
一如既往,不要相信来自外部的数据。在这 3 个级别过滤它们:
玩得开心,别忘了查看维基百科的答案。
我建议您将变量作为参数传递,而不是构建自己的 SQL。否则,总会有一种方法来进行 SQL 注入,以我们目前不知道的方式进行。
您创建的代码类似于:
' Not Tested
var sql = "SELECT * FROM data WHERE id = @id";
var cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.AddWithValue("@id", request.getParameter("id"));
如果你有一个像我这样的名字,里面有一个'。所有 ' 字符都被删除或标记为无效是非常烦人的。
您可能还想查看有关 SQL 注入的 Stackoverflow 问题。
参数化内联 SQL 或参数化存储过程是保护自己的最佳方式。正如其他人指出的那样,仅仅剥离/转义单引号字符是不够的。
您会注意到我专门讨论了“参数化”存储过程。如果您恢复将过程传递的参数连接在一起,那么仅使用存储过程是不够的。换句话说,将完全相同的易受攻击的 SQL 语句包装在存储过程中并不会使其更安全。您需要在存储过程中使用参数,就像使用内联 SQL 一样。
. . . 呃大约 50000000 其他方式
也许像5; drop table employees; --
生成的 sql 可能类似于:
select * from somewhere where number = 5; drop table employees; -- and sadfsf
(--
开始评论)
此外 - 即使您只是寻找撇号,您也不想删除它。你想逃避它。您可以通过用两个撇号替换每个撇号来做到这一点。
但是参数化查询/存储过程要好得多。
由于这是一个相对较旧的问题,我不会费心写一个完整而全面的答案,因为该答案的大部分方面都已被一位或另一位海报提到过。
然而,我确实认为有必要提出另一个在这里没有人提到的问题——SQL Smuggling。在某些情况下,即使您尝试将引号字符 ' 删除,也有可能将其“走私”到您的查询中。事实上,即使您使用了正确的命令、参数、存储过程等,这也是可能的。
在http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf上查看完整的研究论文(披露,我是这方面的主要研究人员)或者只是谷歌“SQL Smuggling”。
是的,绝对是:根据您的 SQL 方言等,有很多方法可以实现不使用撇号的注入。
针对 SQL 注入攻击的唯一可靠防御是使用数据库接口提供的参数化 SQL 语句支持。
而不是试图找出要过滤掉的字符,我会坚持使用参数化查询,并完全消除问题。
这取决于您如何组合查询,但本质上是的。
例如,在 Java 中,如果你要这样做(故意令人震惊的例子):
String query = "SELECT name_ from Customer WHERE ID = " + request.getParameter("id");
那么你很有可能会面临注射攻击。
Java 有一些有用的工具来防止这些,例如 PreparedStatements(您在其中传递一个字符串,例如“SELECT name_ from Customer WHERE ID = ?”,并且 JDBC 层在替换 ? 标记时为您处理转义),但还有一些其他语言对此没有太大帮助。
事情是撇号可能是真正的输入,当您在代码中使用内联 SQL 时,您必须通过将它们加倍来逃避它们。您正在寻找的是一个正则表达式模式,如:
\;.*--\
一个分号用于过早结束正版语句,一些注入的 SQL 后跟双连字符以注释掉原始正版语句中的尾随 SQL。连字符可以在攻击中省略。
因此答案是:不,简单地删除撇号并不能保证您免受 SQL 注入的影响。
我只能重复别人说过的话。参数化的 SQL 是要走的路。当然,对它进行对接编码有点痛苦 - 但是一旦你完成了一次,那么剪切和粘贴该代码并进行所需的修改并不难。我们有很多 .Net 应用程序允许网站访问者指定整个范围的搜索条件,并且代码动态构建 SQL Select 语句 - 但用户可能输入的所有内容都进入了参数。
当您期望一个数字参数时,您应该始终验证输入以确保它是数字的。除了帮助防止注入之外,验证步骤将使应用程序更加用户友好。
如果您在期望 id = 1044 时收到 id = "hello",那么最好向用户返回一个有用的错误,而不是让数据库返回一个错误。