|
6 X5 h& g" c3 a0 A% \
在WEB领域中安全一直是个热门的话题,时常可以听到,某某公司的数据被盗了,某某网站又被攻击。目前无论是什么类型的公司都会采取相应的安全防护。而今天分享的就是WEB攻击类型中的----SQL注入
2 U I: i2 l9 @* k# T+ N. e! P: h; ^, a 什么是SQL注入所谓SQL注入,就是提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力也是程序开发者没有对用户提交参数进行过滤处理, 直接把提交的 2 |8 y O/ T4 L& `! h2 s* [
参数值拼接到SQL语句中,在发送给数据库执行因为PHP操作数据库是需要经过PDO、MySQLi等扩展经过TCP/IP或者socket连接后在把PHP拼接好的SQL语句发送到MySQL数据库而MySQL数据接收了,再去直接SQL语句并把查询后的结果返回给PHP。
& O- q$ M) r* |, g" {6 W SQL注入是怎么产生的?构造动态字符串,开发人员利用动态SQL来创建通用、灵活的应用动态SQL语句是在执行过程中构造的,它根据不同的条件产生不同的 SQL语句当开发人员在运行过程中需要根据不同的查询标准来决定提取什么字段(如SELECT语句),或者根据不同的条件来选择不同的查询表时,动态构造SQL语句会非常有用。 9 K! T/ Q! r C* F4 ]+ e3 X
数据库没有做安全配置开发人员没有无法保证所有参数都过滤在 PHP 中动态构造 SQL 语句字符串:$query = "SELECT * FROM user WHERE username = ".$_GET["name"];: b3 ?3 }9 U+ @8 M
9 B$ |0 g7 M8 R' [0 _: Y 通过控制输入参数name,修改所要执行SQL语句逻辑,达到攻击的目的例如:http://xxx.com?name= -1 OR 1=1 这样的请求如果构成了上面的SQL语句,提交到mysql那边那么就是获取所有的所有user表的数据。 - U- a0 c3 L5 ~& f. H! j+ s" t I6 D
因为username != -1 ,就会选择OR后面的条件1=1它是永远成立既然是基于动态字符串的构建,那么就会从后端在获取用户参数地方进行注入GET 请求:该请求在 URL 中发送参数POST 请求:数据被包含在请求体中。
% r% L9 c" ?' s& g; L 其他注入型数据:HTTP 请求的头部字段也可能会触发 SQL 注入漏洞如何防范前面我们理解了,攻击就是伪造不成立的sql执行条件。所以我们防御就是让这样的条件失去原本的意义常见的攻击类型集结:  
3 g1 A$ `& n6 O {+ A >>输入验证输入验证是指要验证所有应用程序接收到的输入是否合法有两中不同类型的输入验证方法:白名单和黑名单验证白名单验证:比如id值,那么我们判断它是否为数字黑名单验证:使用正则表达式禁止使用某些字符和字符串。 % W. y* P# s( c! M: L7 v b
应该尽量使用白名单,对于无法使用白名单的,使用黑名单提供局部限制>>编码输出所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口结合预编译语句可以非常有效的防止SQL注入攻击。 2 d; |; E6 p, E" b# I" a) X
例如:PDO、MySQLi的预处理语句对进入数据库的特殊字符("<>&*;-- 等)进行转义处理,或编码转换确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。
6 A$ X1 s! L! O0 ]! i' G7 s$ f0 a( P 网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过使用低权限账号启动数据库,禁用数据库的危险函数如 xp_cmd ,禁用危险存储过程用户权限使用最小权限原则,比如只使用到读权限的用户,只分配查询权限。 & `! s4 m8 U6 b' F* K
如何判断网站是否已经做了防范既然sql注入是动态构造的,所以我们在判断的时候我们可以借助它们会转义的特性,如果我们给出特殊字符,如果报错了,那是不是就存在漏洞呢?有错误信息提示在注入参数中添加单/双引号 / G. Z: j' p4 k# B3 R) i& T
,因为引号是sql的条件包含体看是否会返回错误信息:error:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near at line 16 l( U* D3 f- u5 n) _
。
, N* T" R7 d. S* Y( ]) ~) S& T 无错误信息提示and : 同为真时为真or : 同为假时为假如果页面无任何错误信息,我们就可以借助该方法来推断了,首先我们在参数后面加上 and 1=1 和 and 1=2 看看有什么不同and 1=1 能返回数据,而 and 1=2 没有,这是由于 1=1是一个为真的条件,前面的结果是 true,true and true 所以没有任何问题,第二个 1=2 是个假条件, true and false 还是 false,所以就没有数据返回。 ! z0 A" g, F3 F$ v! M! |
先把参数改为很大的数或负数,要让它查询不到数据,我们加上 or 1=1 就成功返回了数据,这是因为 1=1 为真,不管前面是不是假,数据都会返回当 or 1=2 时,因为 1=2 为假,前后都为假,最终也是假,数据就不会返回了。
/ d/ [/ {: _5 }
' b& l: ?) g' Y- q8 t' w% w# \3 [* M9 X) _
( q5 D k" h9 i9 x1 l8 X+ I
$ C; r# R9 R7 b; d* {! V& Q* i |