【报错注入】极客大挑战 2019 HardSQL WriteUp
本文最后更新于:2021年8月18日下午1点46分
报错注入原理:
updatexml()函数
介绍:
updatexml()
是一个使用不同的xml标记匹配和替换xml块的函数。作用:改变文档中符合条件的节点的值
语法:
updatexml(XML_document,XPath_string,new_value)
第一个参数:是string
格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径
,Xpath格式的字符串例如//title【@lang】 第三个参数:string
格式,替换查找到的符合条件的数据原理:
updatexml
使用时,当xpath_string
格式出现错误,mysql
则会爆出xpath语法错误(xpath syntax
)例如:
select * from test where ide = 1 and (updatexml(1,0x7e,3));
由于0x7e
是~
,不属于xpath语法格式,因此报出xpath语法错误。以下代码摘自微笑师傅:(便于理解)链接在这!
1
2
3UpdateXml报错注入
mysql> select updatexml(0,concat(0x7e,(select database())),0);
ERROR 1105 (HY000): XPATH syntax error: '~security'
extractvalue()函数
介绍:此函数从目标XML中返回包含所查询值的字符串
语法:
extractvalue(XML_document,xpath_string)
第一个参数:string
格式,为XML文档对象的名称,第二个参数:xpath_string
(xpath格式的字符串)select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
作用:
extractvalue
使用时当xpath_string
格式出现错误,mysql则会爆出xpath语法错误(xpath syntax
)例如:
select user,password from users where user_id=1 and (extractvalue(1,0x7e));
原理:由于
0x7e
就是~
不属于xpath语法格式,因此报出xpath语法错误。以下代码摘自微笑师傅:(便于理解):
1
2
3extractvalue报错注入
mysql> select extractvalue(1,concat(0x5c,(select database())));
ERROR 1105 (HY000): XPATH syntax error: '\security'
floor()报错注入
floor()报错注入原理(个人理解):
为什么要使用floor和rand:
1 |
|
1 |
|
此时,新建一个table1
的表,该表中一共有4个数据,执行以下sql语句
1 |
|
返回结果如下:
多次执行该sql语句SELECT rand(0) FROM table1;
,返回的结果都如上图所示。
而此时,将rand(0)
改造为floor(rand(0)*2)
时,sql语句修改如下
1 |
|
此时返回的结果为一个固定的序列,0 1 1 0
而又因为 rand 函数的特殊性(如果使用rand()的话,该值会被计算多次)。
在这里的意思就是,group by 进行分组时,floor(rand(0)*2)
执行一次(查看分组是否存在),如果虚拟表中不存在该分组,那么在插入新分组的时候 floor(rand(0)*2)
就又计算了一次。(其实在上述 rand(0) 产生多个数据的时候,也能观察出来。只要 rand(0) 被调用,一定会产生新值)。
报错:
当 group by 对其进行分组的时候,首先遇到第一个值 0 ,发现 0 不存在,于是需要插入分组,就在这时,floor(rand(0)\*2)
再次被触发,生成第二个值 1 ,因此最终插入虚拟表的也就是第二个值 1 ;然后遇到第三个值 1 ,因为已经存在分组 1 了,就直接计数加1(这时1的计数变为2);遇到第四个值 0 的时候,发现 0 不存在,于是又需要插入新分组,然后floor(rand(0)*2)
又被触发,生成第五个值 1 ,因此这时还是往虚拟表里插入分组 1 ,但是,分组 1 已经存在了!所以报错!
以下代码摘自微笑师傅:(便于理解):
1 |
|
WriteUp:
打开题目,是一个登录框页面
随手输入一个admin
,admin
可以看到,用get
传参username
以及password
利用单引号'
闭合username
参数
1 |
|
可以看到有报错,尝试使用updatexml()
报错注入
1 |
|
可以看到,被waf拦截了,经过检查以后,waf将空格space
进行了拦截,将payload进行修正
1 |
|
得到当前的数据库为geek
然后用相同的方法爆出当前的数据表
1 |
|
经过检查以后,发现等号=
被waf拦截了,因此使用like
命令
将payload
修改为:
1 |
|
爆出当前的数据表为H4rDsq1
在利用相同方法爆出当前数据表下的字段,payload为:
1 |
|
得到当前的数据表下有三个字段,分别为id
,username
,password
再爆出这三个字段中的内容
先爆id
1 |
|
再爆username
1 |
|
最后爆password
1 |
|
得到一部分flag:flag{c6f71b98-07e8-489f-8d4c-09
由于updatexml()
函数只能爆出32位,因此,用right
函数,截取password
后半段,将payload
修改为
1 |
|
后半段的flag为:f-8d4c-094e32440be8}
拼接而成,得到flag
:flag{c6f71b98-07e8-489f-8d4c-094e32440be8}
参考文章:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!