有一个安全设计原则——“数据与代码分离”原则,它可以说是专门为了解决注入攻击而生的。
而注入攻击的本质,是把用户输入的数据当做代码执行。
这里有两个关键条件:
var Shipcity;
ShipCity = Request.form ("ShipCity");
var sql = "select * from OrdersTable where ShipCity = '" + ShipCity + "'";
变量ShipCity的值由用户提交,在正常情况下,假如用户输入“Beijing”,那么SQL语句会执行:
SELECT * FROM OrdersTable WHERE ShipCity = 'Beijing'
但假如用户输入一段有语义的SQL语句,比如:
Beijing'; drop table OrdersTable--
那么,SQL语句在实际执行时就会如下:
SELECT * FROM OrdersTable WHERE ShipCity = 'Beijing'; drop table OrdersTable--'
我们看到,原本正常执行的查询语句,现在变成了查询完后,再执行一个drop表的操作,而这个操作,是用户构造了恶意数据的结果。
回过头来看看注入攻击的两个条件:
(1)用户能够控制数据的输入——在这里,用户能够控制变量ShipCity。
(2)原本要执行的代码,拼接了用户的输入:
这个“拼接”的过程很重要,正是这个拼接的过程导致了代码的注入。
在SQL注入的过程中,如果网站的Web服务器开启了错误回显,则会为攻击者提供极大的便利。
比如攻击者在参数中输入一个单引号“'”,引起执行查询语句的语法错误,服务器直接返回了错误信息:
Microsoft JET Database Engine错误 ’80040e14'
字符串的语法错误 在查询表达式 ’ID=49'’ 中。
/showdetail.asp,行8
从错误信息中可以知道,服务器用的是Access作为数据库,查询语句的伪代码极有可能是:
select xxx from table_X where id = $id
错误回显披露了敏感信息,对于攻击者来说,就更容易构造SQL注入的语句。
所以在我们网站的web服务器中,我们最好不要直接把数据库错误信息未经处理的返回给用户。
当Web服务器关闭了错误回显,这时就没有办法成功实施SQL注入攻击了吗?
攻击者为了应对这种情况,研究出了“盲注”(Blind Injection)的技巧。
所谓“盲注”,就是在服务器没有错误回显时完成的注入攻击。
服务器没有错误回显,对于攻击者来说缺少了非常重要的“调试信息”,
所以攻击者必须找到一个方法来验证注入的SQL语句是否得到执行。
最常见的盲注验证方法是: 构造简单的条件语句,根据返回页面是否发生变化,来判断SQL语句是否得到执行。