项目接口常见SQL注入漏洞攻击及解决办法
1、弱口令漏洞
解决方案:使用至少6位的数字、字母及特殊字符组合作为密码。数据库不要存储明文密码,应存储加密后的密文。
2、未使用用户名及密码登录后台可直接输入后台URL登录系统。
解决方案:通过配置拦截器过滤掉无效用户的连接请求。
3、接口返回的信息中抛出的异常可能暴露程序信息。有经验的入侵者,可以从抛出的异常中获取很多信息,比如程序的部分架构、程序的物理路径、SQL注入爆出来的信息等。
解决方案:自定义一个Exception,将异常信息包装起来不要抛到页面上。
4、SQL注入
原理:
SQL注入是一种将SQL代码添加到输入参数中,传递到服务器解析并执行的一种攻击手法。
SQL注入攻击指的是通过构建特殊的输入作为参数传入,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而达到预想之外的一种行为,称之为SQL注入攻击。其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
4.1、数字注入
在浏览器地址栏输入:web/findData.do?id=1,这是一个get型接口,发送这个请求相当于调用一个查询语句:
sql="SELECT FROM table WHERE id="+id
正常情况下,应该返回一个id=1的信息。那么,如果在浏览器地址栏输入:web/findData.do?id=-1 OR 1 =1,这就是一个SQL注入攻击了,可能会返回所有的相关信息。为什么会这样呢?
这是因为,id = -1永远是false,1=1永远是true,所有整个where语句永远是ture,所以where条件相当于没有加where条件,那么查询的结果相当于整张表的内容。
4.2、字符串注入
有这样一个用户登录场景:登录界面包括用户名和密码输入框,以及提交按钮。输入用户名和密码,提交。
这是一个post请求,登录时调用接口web/login.do,首先连接数据库,然后后台对post请求参数中携带的用户名、密码进行参数校验,即sql的查询过程。假设正确的用户名和密码为admin和pwd12345678,输入正确的用户名和密码、提交,相当于调用了以下的SQL语句:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin' ADN password = 'pwd12345678'
由于用户名和密码都是字符串,SQL注入方法即把参数携带的数据变成mysql中注释的字符串。mysql中有2种注释的方法:
1、'#':'#'后所有的字符串都会被当成注释来处理
用户名输入:admin'# (单引号闭合admin左边的单引号),密码随意输入,如:111,然后点击提交按钮。等价于SQL语句:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin'#' AND password = '111'
'#'后面都被注释掉了,相当于:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin'
用户名输入:admin' OR NAME LIKE 'a%'# (单引号闭合a%左边的单引号),密码随意输入,如:abcd,然后点击提交按钮。等价于SQL语句:
SELECT * FROM SYS_ADMIN
WHERE NAME = 'admin' OR NAME LIKE 'a%'#' AND password=' abcd '
'#'后面都被注释掉了,相当于:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin' OR NAME LIKE 'a%'
2、'-- ' (--后面有个空格):'-- '后面的字符串都会被当成注释来处理
用户名输入:admin'-- (注意--后面有个空格,单引号闭合user左边的单引号),密码随意输入,如:111,然后点击提交按钮。等价于SQL语句:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin'-- ' AND password = '111'
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin'-- ' AND password = '1111'
'-- '后面都被注释掉了,相当于:
SELECT * FROM SYS_ADMIN WHERE NAME = 'admin'
因此,以上两种情况可能输入一个错误的密码或者不输入密码就可登录用户名为'admin'的账号,这是十分危险的事情。
根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:
1) 不当的类型处理;
2) 不安全的数据库配置;
3) 不合理的查询集处理;
4) 不当的错误处理;
5) 转义字符处理不合适;
6) 多个提交处理不当。
防护:
1) 严格检查输入变量的类型和格式,对于整数参数,加判断条件:不能为空、参数类型必须为数字,对于字符串参数,可以使用正则表达式进行过滤:如:必须为[0-9a-zA-Z]范围内的字符串。
2) 永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3) 过滤和转义特殊字符, 在变量前进行转义,对'、"、\等特殊字符进行转义。
4) 不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5) 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6) 利用mysql的预编译机制, 把sql语句的模板(变量采用占位符进行占位)发送给mysql服务器,mysql服务器对sql语句的模板进行编译,编译之后根据语句的优化分析对相应的索引进行优化,在最终绑定参数时把相应的参数传送给mysql服务器,直接进行执行,节省了sql查询时间,以及mysql服务器的资源,达到一次编译、多次执行的目的,除此之外,还可以防止SQL注入。具体是怎样防止SQL注入的呢?实际上当将绑定的参数传到mysql服务器,mysql服务器对参数进行编译,即填充到相应的占位符的过程中,做了转义操作。