SQL 注入学习总结

1. 何为sql  注入

所谓 sql 注入,指的是在动态构造sql 后向数据库引擎直接发送完整的sql 语句,从而导致可能动态构造的参数 被当成 语义语句执行,产生非期望效果,被恶意注入时甚至能产生删除、改变、全部获取数据库内容等效果。

sql 注入产生的根本原因是,动态构造的sql  所传递进的参数,被当成了 执行语句 而非 一个简单的参数。支持 sql 的数据库引擎,本身可接受文本的sql , 而当文本的sql 是拼接而来(一部分是程序本身固定的语句,一部分由用户输入填充的参数)而未加处理 或者处理程度不够时,用户通过参数传递极其容易 进行sql 注入。

如  

sql  = "select user.name from user where user.name= %(name) and user.password =%(password)" %(name ,password)

name,和password 由用户输入,从而进行身份认证;而当 name的 输入内容为 testing  or 1 =1 " -- 1 时 ,拼接的sql 语句则变成

sql  = "select user.name from user where user.name= testing  or 1 =1 "  -- 1 and user.password =%(password)" %(name ,password)""

"--"双短线 在sql 语句中是起到注释的作用,也即实际上起作用的sql 语句为

sql  = "select user.name from user where user.name= testing  or 1 =1 "

 后面的where语句恒为真,也就是 攻击者甚至不用知道账号 和密码就轻易登陆了你的系统,这就是sql 的可怕之处。不过sql 注入已经是为大家所熟知的一种攻击技术,

相应的防范措施也相对成熟。常见的防范方法如下:

2. 怎样防御

2.1 检测输入 

既然 sql 注入是用户输入导致,那很自然的一钟方法就是检测用户的输入,只允许合法的输入通过。比如,对 单引号'、双引号"、斜杠\ 在输入测就行转义或者替换,再或者限定参数的类型,如id 为int 类型,只允许此类型的参数通过等。不过此种方法为所遇到攻击的有限枚举防御,也就是你可能没想到的一些攻击方式被攻击者采用了,没有防御到,还是会被攻击。 所以说,这种方法相对还是不彻底,还是存在隐患的,也非主流的防御方式,只在特定的情景下起到很好的效果。

2.2  采用数据库引擎的prepare statement 

这是当前最主流、也是基本上能从根本上杜绝 sql 注入的方法。

其核心就是,把 sql  语句(缺少的参数用占位符代替,? 或者%(参数名)s 等)和 参数分开传递,这样数据库引擎在接收到 sql 语句时,预先对其进行编译,

而参数传递进来时,则是一个萝卜一个坑地填到 sql 语句上,引擎本身经过了一系列的处理,使得这样传递进来的参数不会被当成语义语句执行。

从而达到 防止sql 注入的目的。

写到这,其实访注入的核心,还是没弄明白引擎本身是如何进行的参数处理,这应该会涉及到sql 的预编译。是否就是经过预编译的 会被当做语义语句执行,而参数则是另外一种编译方式,或者在编译时被标志了不可语义执行,然后在最终运行时,遇到sql 当语义执行,遇到参数只当参数处理,这样?

下面的摘抄分别解释了为什么prepare 语句可以防止sql 注入,与及prepare 对sql 注入是否是100%安全的?

3. why  prepare state works?

Explanation

What happens is that the SQL statement you pass to prepare is parsed and compiled by the database server. By specifying parameters (either a ? or a named parameter like :name in the example above) you tell the database engine where you want to filter on. Then when you call execute, the prepared statement is combined with the parameter values you specify.

The important thing here is that the parameter values are combined with the compiled statement, not an SQL string. SQL injection works by tricking the script into including malicious strings when it creates SQL to send to the database. So by sending the actual SQL separately from the parameters, you limit the risk of ending up with something you didn't intend. Any parameters you send when using a prepared statement will just be treated as strings (although the database engine may do some optimization so parameters may end up as numbers too, of course). In the example above, if the $name variable contains 'Sarah'; DELETE FROM employees the result would simply be a search for the string "'Sarah'; DELETE FROM employees", and you will not end up with an empty table.

Another benefit with using prepared statements is that if you execute the same statement many times in the same session it will only be parsed and compiled once, giving you some speed gains.

 

4 .Are prepared statements 100% safe against SQL injection?

I have never heard of any of these attacks on prepared statements on real databases in the field and strongly suggest using bound parameters to prevent SQL injection. Without bound parameters or input sanitation, its trivial to do SQL injection. With only input sanitation, its quite often possible to find an obscure loophole around the sanitation.

posted @ 2017-08-15 10:10  草色青青  阅读(155)  评论(0编辑  收藏  举报