pikachu---SQL注入(2)

http header注入
有些时候,后台开发人员为了验证客户端头信息(比如cookie验证)
或者通过http header获取客户端的一些信息,比如useragent,accept字段等
会对客户端的http header信息进行获取并使用SQL进行处理,如果此时并没有足够的安全考虑
则可能会导致基于 http header 的 SQL 注入漏洞
首先打开pikachu,http header登陆,登录账号:admin / 123456

登陆后我们可以发现会记录我们的信息,根据这个功能,我们知道后台会获取 http header 里的数据,比如 user agent 等。那么这样它有对数据库操作吗?
下面我们看一下BurpSuite抓包内容

把 User-Agent 后面改为一个单引号,抓包看看后台处理的结果

这个时候我们发现直接报了 SQL 语法错误,这说明存在 SQL 注入漏洞,后台可能会 insert 到数据库中,这样我们可以构造payload。
1' or updatexml(1, concat(0x7e, database()), 0) or '

这样我们就可以获取数据库名,后面的操作就是一样的了。
还有 cookie 也是可以注入的,后端可能会取得我们的 cookie,后端通过拼接 SQL 语句进行验证
我们可以在用户名后面加一个'

我们可以发现直接报了 SQL 语法错误这说明存在 SQL 注入漏洞,我们可以构造下面的 payload
admin' or updatexml(1, concat(0x7e, database()), 0)#

这样我们就可以获取数据库名,后面的操作就是一样的了
盲注
在有些情况下,后台使用了错误屏蔽方法屏蔽了报错
此时无法根据报错信息来进行注入的判断
这种情况下的注入,称为“盲注”
based on boolean
基于真假的盲注主要特征
没有报错信息
不管是正确的输入,还是错误的输入,都只有两种情况(可以看做 0 or 1)
在正确的输入下,后面跟 and 1=1 / and 1=2 进行判断
我们在皮卡丘平台一进行实验,输入下面的测试语句
kobe' and 1=1#

kobe' and 1=2#

发现一条正确执行,一条显示用户名不存在,说明后台存在 SQL 注入漏洞
因为这里的输出只有 用户名存在 和 用户名不存在 两种输出,所以前面基于报错的方式在这不能用。
我们只能通过 真 或者 假 来获取数据,所以手工盲注是很麻烦的。

我们可以先用 length(database()) 判断 数据库名称的长度
kobe' and length(database())>...#(...为任意整数)
通过用户名存在 和 用户名不存在 两种输出可能来判断数据库长度是否正确
这一种方法可以确定当前数据库的长度
再用 substr() 和 ascii() 判断数据库由哪些字母组成(可以用二分法)
kobe' and ascii(substr(database(), 1, 1)) > ...#(...为任意整数)
kobe' and ascii(substr(database(), 1, 1)) = ...#(...为任意整数)
不断重复,然后取得数据库名。
再和 information_schema 和 length 猜测 表名 的长度。
当然我们可以用下面的 SQL 语句替代上面的 database()
(select table_name from information_schema.tables where table_schema=database() limit 0,1)
同样的方法去猜解列名、数据,就是麻烦,我们可以用工具会方便些。
based on time
基于真假的盲注可以看到回显的信息,正确 or 错误
基于时间的注入就什么都看不到了,我们通过特定的输入,判断后台执行的时间,从而确定注入点,比如用 sleep() 函数
在皮卡丘平台一,无论输入什么,前端都是显示 “I don't care who you are!”
首先我们点击F12打开控制台,选到网络

然后我们输入下面的 payload 进行测试
kobe' and sleep(5)#(sleep是让5秒才会返回执行结果)
如果存在注入点,后端就会 sleep 5秒才会返回执行结果

看到上图这说明这里存在SQL漏洞。
接下来我们先构造一个payload
kobe' and if((substr(database(), 1, 1))='p', sleep(5), null)#
这个payload的意思是,如果当前数据库如果第一个字母是p就5秒才会返回执行结果,否则立即返回。
当然我们也可以像真假注入是一样的了,替换 database()
(select table_name from information_schema.tables where table_schema=database() limit 0,1)
表(列)名的暴力破解
我们之前都是通过 information_schema 去获取的信息,很多时候我们没有权限去读取里面内容,也可能是别的数据库,没有 information_schema
常用的方法就是用暴力破解的方式去获得表名和列名
kobe' and exists(select * from aa)#
上面的 payload,遍历我们字典中的表名,把拦截的数据包发到 BurpSuite 中的Intruder中暴力破解 表名即可

表名不存在时,会提示 doesn't exist,我们匹配这句话


这时候就爆破出一个表名了——users

然后同样的思路爆破列名
kobe' and exists(select aa from users)#
后面的操作都是大同小异。
宽字节注入
当我们输入有单引号时被转义为\’,无法构造 SQL 语句的时候,可以尝试宽字节注入。
GBK编码中,反斜杠的编码是 “%5c”,而 “%df%5c” 是繁体字 “連”。
在皮卡丘平台中,将利用 BurpSuite 截获数据包,发送到 Repeater 中,在里面写入 payload
当我们用通常的测试 payload时,是无法执行成功的,下面的payload会报错
kobe' or 1=1#

因为在后台单引号会被转义,在数据库中执行时多了个反斜杠。我们可以用下面的payload,在单引号前面加上 %df,让单引号成功逃逸
kobe%df' or 1=1#

当然这里还有转义函数比如escape。。。
SQL注入防范措施
代码层面
对输入进行严格的转义和过滤
使用预处理和参数化(Parameterized)
网路层面
通过WAF启用防范SQL Inject
云端防护(360网站卫士,阿里云盾)

posted @ 2020-07-11 16:52  renletao  阅读(282)  评论(0编辑  收藏  举报