我一直在读一篇关于sql注入攻击的文章,在那里,他们一直在说这个语句容易受到注入攻击:
"SELECT * from tblBlah where userId" +userId
但这个查询不是”
"SELECT * from tblBlah where userId = @userId";
我试图找到解释为什么会这样。他们都在期待一个参数。可能是第一个查询可以接受来自 URL 的参数而第二个不能?
在第一个查询的情况下,有人可以为 传递以下值userId:
= 3; DELETE FROM tblBlah;
Run Code Online (Sandbox Code Playgroud)
这将是字符串连接并产生以下 SQL 语句:
SELECT * from tblBlah where userId= 3; DELETE FROM tblBlah;
Run Code Online (Sandbox Code Playgroud)
当然,这对您的数据库来说是灾难性的。
我认为在第二个查询的情况下,数据库会在内部将其编译为单个SELECT语句。参数的值将插入占位符所在的位置,但仅作为数据插入。即使我们尝试了以下分配:
@userId = '= 3; DELETE FROM tblBlah;';
Run Code Online (Sandbox Code Playgroud)
我们最终会得到以下查询:
SELECT * from tblBlah where userId = '= 3; DELETE FROM tblBlah;';
Run Code Online (Sandbox Code Playgroud)
换句话说,我们试图注入代码,但我们真正能做的只是注入一个字符串参数。这可能会导致触发错误的查询,但它不会允许恶意用户调用DELETE. 事实上,用户对执行哪个语句的控制为零。
这是一个简单的例子,展示了准备好的语句的威力。使用准备好的语句,查询的通用模板或结构在查询实际运行之前就已经编译好了。语句的某些部分具有参数占位符,但是它们不会通过连接改变查询,而只能通过分配定位值来改变查询。