SQL二次注入

本文深入解析二次SQL注入的原理及特点,对比其与普通注入的区别,通过实例展示二次注入的实施过程,强调其隐蔽性和危害性。

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

(一)是什么?

 ——何为二次注入?

 ——为了预防SQL注入攻击,而将输入到应用程序中的某些数据进行了“转义(escape)”,但是这些数据却又在“未被转义(Unescaped)”的查询窗体中重复使用。

简单地说,二次注入和普通注入一样是一个程序漏洞,它发生在用户提交的值被存储在数据库中,然后这个值被应用程序中的某些其他功能使用而不转义或者过滤数据。


(二)区别

参考网上的总结,二次注入和普通注入的区别主要有:

普通注入:(1)在http后面构造语句,是立即直接生效;

                  (2)普通注入很容易被扫描工具扫描到。

二次注入:(1)先构造语句(此语句含有被转义字符的语句);

                  (2)将我们构造的恶意语句存入数据库;

                  (3)第二次构造语句(结合前面已被存入数据库的语句构造。因为系统没有对已存入的数据做检查,成功注入);

                  (4)二次注入更加难以被发现。

 

(三)二次注入示例

用模拟登陆和修改密码进行操作:

首先,假设我们注册了两个用户:用户①名字为“csdner”,密码是“csdner123456”;

                                                     用户②名字为“csndner'--” ,密码是“csdner1111”。

           请注意,此处的用户②的名字就是sql注入有效负载,它没有被转义或者截断,而是按照原样保存在了数据库中。

 

然后,我们登陆用户②,并修改它的密码为“csdn222”。注意此时登陆的是用户②。因此,我们为此用户名构造密码更改查询

UPDATE users
SET password='csdn222'
WHERE username='csdner'--' and password='csdn1111'

 记住此时被查询的是用户②。但是,因为在SQL中,--是开启注释的标志,这样子的话,不知不觉中被更改密码的成了用

户①(实际上,上面的代码已经自动被优快云当做注释处理了,恰好成了注入的样子)

也就是说,现在的查询语句长下面这个样子:

UPDATE users
SET password='csdn222'
WHERE username='csdner'

查询导致更新用户“csdner”的密码,而不是“csdner'- - ” 因此成功执行二阶sql注入。

 

(四)小结

参考了网上的资料,总结一下二次注入的精髓就是,第一次构造的语句只是为了第二次构造做的铺垫,第二次才是真正的攻击。

当然,二阶SQL注入也适用于其他场景,其中数据库中的数据是要被检索的。

### SQL 二次注入的原理 SQL 二次注入是一种特殊的 SQL 注入攻击形式,其核心在于恶意数据被存储在数据库中,并在后续操作中未经过充分验证或过滤而被执行。具体来说,这种攻击发生的原因可能是应用系统在初次接收到用户输入时已经对其进行了安全性处理,但当这些已存储的数据再次参与动态 SQL 查询构建时,未能重新对其进行防护[^2]。 #### 攻击过程描述 1. **初始输入阶段**:攻击者向目标系统提交含有恶意 SQL 片段的内容。此时,该内容可能会经历初步的安全检测(如转义特殊字符),随后存入数据库。 2. **后续利用阶段**:当程序从数据库提取之前保存的恶意数据并将其嵌套至新的 SQL 查询语句中时,如果缺乏必要的清理机制,则可能导致原始恶意代码得以执行,从而实现对系统的非法访问或者破坏行为[^3]。 --- ### 防御方法 针对上述提到的 SQL 二次注入风险,可以从以下几个方面着手加强防范: #### 数据校验与清洗 - 对于任何来源于外部环境的信息,在写入持久化层前都应实施严格的格式校验以及敏感符号替换工作; - 即使某些字段看似无害也需要谨慎对待,因为它们有可能在未来某个时刻成为潜在威胁源的一部分[^1]。 #### 参数化查询技术的应用 采用预编译好的参数占位符方式来代替传统的字符串拼接法构造SQL指令是非常有效的手段之一 。这种方法能够确保即使存在危险成分也不会影响最终形成的合法命令结构 ,因为它会自动把所有传进去 的变量当作纯文本看待而不是可解析语法单元 : ```java PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM users WHERE username=? AND password=?"); pstmt.setString(1, userInputName); pstmt.setString(2, userInputPassword); ResultSet rs = pstmt.executeQuery(); ``` 以上例子展示了如何通过 Java 中 PreparedStatement 类型对象来进行安全可靠的数据库交互操作 。 #### 输出编码控制 除了重视前端收集来的资料之外 , 还要特别留意那些由内部生成却又要反馈给用户的项目 . 如果有必要的话 可考虑运用 HTML 实体转换等功能 来阻止可能出现跨站点脚本 (XSS) 或其他类型的漏洞传播路径 同样适用于防止二次 sql injection 发生的情况 下面给出 python flask 框架下的简单示范 : ```python from markupsafe import escape @app.route('/search') def search(): query = request.args.get('q', '') safe_query = escape(query) # Escape potentially harmful characters. results = db.execute(f"SELECT * FROM entries WHERE title LIKE '%{safe_query}%'").fetchall() return render_template('results.html', results=results) ``` 这里借助 `markupsafe` 库里的 `escape()` 函数实现了基本层面的文字序列保护作用 . #### 定期审计日志审查制度建立 最后一点建议便是养成良好习惯定期查看服务器端产生的各类记录文件寻找异常模式迹象以便及时发现隐患所在 并采取相应补救措施减少损失扩大可能性的同时提高整体网络安全水平 [^3]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值