我一直在读一篇关于sql注入攻击的文章,在那里,他们一直在说这个语句容易发生注入攻击:
"SELECT * from tblBlah where userId" +userId
但此查询不是"
"SELECT * from tblBlah where userId = @userId";
我试图找到解释为什么会这样的情况。他们俩都期待一个参数。可能是第一个查询可以接受来自URL的参数而第二个不可以吗?
答案 0 :(得分:4)
如果是第一个查询,有人可以为userId
传递以下值:
= 3; DELETE FROM tblBlah;
这将是字符串连接,并将导致以下SQL语句:
SELECT * from tblBlah where userId= 3; DELETE FROM tblBlah;
当然,这对您的数据库来说是灾难性的。
我认为在第二个查询的情况下,数据库会在内部将其编译为单个SELECT
语句。参数的值将插入占位符所在的位置,但仅作为数据插入。即使我们尝试了以下任务:
@userId = '= 3; DELETE FROM tblBlah;';
我们最终会得到以下查询:
SELECT * from tblBlah where userId = '= 3; DELETE FROM tblBlah;';
换句话说,我们尝试注入代码,但我们真正能够做的就是注入一个字符串参数。这可能会导致查询错误,但不允许恶意用户调用DELETE
。实际上,用户无法控制执行哪个语句。
这是一个简单的例子,展示了准备好的陈述的力量。使用预准备语句,在查询实际运行之前已经编译了查询的一般模板或结构。语句的某些部分具有参数占位符,但不会通过连接更改查询,而只能通过分配定位值。
答案 1 :(得分:1)
通过第一次查询,数据库不知道它是否有更多条件或者查询的目的是什么,那么数据库就会盲目地信任查询。
在第二个数据库中,启动时的数据库将获取查询并确切地知道您要执行的操作以及查询应该具有多少参数,如果来自参数的内容更改了初始行为,或者根本不存在,则查询它将不受信任,并会抛出错误。
我现在将用例子解释。
如果你喜欢这样:
SELECT * FROM table WHERE User=' + User + ' AND Pwd=' + Pass
有人可以轻松地在那里注入SQL,只需向用户填充'' AND 1=1--
,因为--
将注释掉查询的第二部分并且条件为真,然后它将打印表数据。
查询看起来像:
SELECT * FROM table WHERE User='' AND 1=1-- AND Pwd=' + Pass
现在让我们用参数:
SELECT * FROM custTable WHERE User= @user AND Pass=@password
//Someone filled the userfield with SQL injection:
@user = "'' AND 1=1--"
@password = ""
然后查询看起来像:
SELECT * FROM custTable WHERE User= '' AND 1=1-- AND Pass=@password
查询看起来相同,但工作方式不同,数据库将处理查询,获取@username参数和空白密码,然后它将变为false。
我想添加它取决于你如何使用SQL参数以及你编写哪种语言,它或多或少都是安全的,但最安全的一个是使用带参数化查询的存储过程。