小迪web自用笔记45
知识点↑
二次注入基本原理:
通过添加插入,把一个东西放数据库里,然后数据库把这个东西取出来的时候形成了注入。
讲解:
第1个是重置密码,就是忘记了密码,然后接受验证码修改之类的,第2种是登进去之后修改密码。
前面的代入有安全处理。但是后面取出来的时候却没有安全处理了,所以才会形成二次注入漏洞。
*双重注入(Double Injection)的核心原因是 转义逻辑重复处理导致反斜杠被“二次转义”或“意外保留”,而 addslashes() 在这个过程中扮演了关键角色。要理解这一点,我们需要从 转义机制、SQL 解析逻辑 和 漏洞触发条件 三个维度拆解:
一、双重注入的前提: magic_quotes_gpc 自动转义
在 PHP 早期版本(如 PHP 5.3 及之前), magic_quotes_gpc 是一个全局配置,作用是:
- 自动对 $_POST / $_GET / $_COOKIE 中的数据添加反斜杠(转义单引号 ' 、双引号 " 、反斜杠 \ 、NULL 字符 \0 )。
- 目的是防止 SQL 注入,因为转义后的特殊字符会被数据库视为“字面量”而非语法符号。
例如,输入 O'Neil 会被自动转义为 O\'Neil ,此时存入数据库的字符串就是 O'Neil (反斜杠仅用于 SQL 解析,不会存入数据库)。
二、 addslashes() 的“推波助澜”:手动二次转义
如果开发者在 magic_quotes_gpc 开启的情况下,又手动调用了 addslashes() ,就会触发“双重转义”:
- 第一次: magic_quotes_gpc 自动转义 → O\'Neil 。
- 第二次: addslashes() 再次转义 → O\\'Neil (反斜杠被转义为 \\ ,单引号被转义为 \' )。
此时,若代码直接将 O\\'Neil 拼接进 SQL 语句(如 INSERT INTO users (name) VALUES ('O\\'Neil') ),数据库解析时会发生:
1. SQL 解析器看到 \\ ,会将其视为一个字面反斜杠(因为第一个反斜杠转义了第二个)。
2. 单引号 ' 前的 \ 会被解析为转义符,导致单引号失去“字符串结束符”的语法意义。
最终,数据库会将 O\'Neil 存入字段,而取出时若未正确处理转义(如未用 stripslashes() ),就会保留 O\'Neil 中的反斜杠,形成存储型注入漏洞。
三、为什么必须依赖 addslashes() ?
双重注入的核心矛盾是 “自动转义 + 手动转义”的逻辑冲突,而 addslashes() 是“手动转义”的直接工具。如果没有 addslashes() ,仅靠 magic_quotes_gpc 的自动转义,不会出现双重转义(因为转义逻辑只执行一次)。
换句话说:
- magic_quotes_gpc 是“自动防御”, addslashes() 是“手动防御”。
- 当两者叠加时,防御逻辑变成了“漏洞催化剂”——转义被重复处理,反而绕过了转义保护。
四、现代防御建议:放弃 addslashes() ,拥抱参数化查询
双重注入的本质是 “转义逻辑不可控”,而解决这个问题的根本方法是 用“参数化查询”替代“字符转义”:
1. 参数化查询(如 PDO 预处理语句):
- 将 SQL 语句结构与用户数据完全分离(数据作为参数传递,而非拼接进 SQL)。
- 数据库会自动处理特殊字符,无需手动转义,彻底避免 SQL 注入。
- 示例:
php
$stmt = $pdo->prepare("INSERT INTO users (name) VALUES (?)");
$stmt->execute([$userInput]); // 数据自动安全处理
2. 为什么不再推荐 addslashes() ?:
- 无法防御宽字节注入(如 GBK 编码下的 %df' 绕过)。
- 依赖开发者手动控制转义逻辑,容易出现“双重转义”或“转义缺失”。
- PHP 已在 5.4 版本移除 magic_quotes_gpc ,转义逻辑需完全手动控制,风险更高。
总结
双重注入的核心是 “自动转义 + 手动转义”的逻辑冲突,而 addslashes() 是“手动转义”的直接载体。在现代开发中,应彻底放弃依赖 addslashes() 和 magic_quotes_gpc ,转而使用 参数化查询(如 PDO、MySQLi 预处理)来确保 SQL 安全。
*简单来说就是带入数据库的时候会有\,存入数据库的时候,\又消失了,但有这个东西才能存入。
对单引号进行反斜杠。
*手动转义可能性。
有单引号就会成功执行 ↑
但这个是白盒。
黑盒:
还有限制的问题,前端限制直接F12改就行,除非后端也限制了。
创建等于插入数据,简历管理等于显示数据(这就有回显了)
首先插入→然后显示(二次注入)
白盒:
抓包看信息,然后找到了位置。
找到存储信息UPDATETABLE
蓝色方框里的内容是:
白盒思路:insert后进入select或update的功能的代码块
它的意思是在**代码审计(白盒测试)**时,要重点关注以下逻辑:
1. insert
当程序通过 INSERT 语句将用户输入存入数据库时,通常会有转义或过滤(比如 addslashes() 或 magic_quotes_gpc ),此时数据是“安全”的。
2. 进入select或update的功能
危险点在于:这些被存储的数据之后在其他功能中被取出,并直接用于 SELECT 或 UPDATE 语句的拼接,而没有再次进行转义或过滤。
3. 代码块
需要审计所有从数据库读取数据,并将其用于 SQL 拼接的代码段。
通俗解释
- 假设用户注册时输入: admin' --
- 程序用 addslashes() 转义后存入数据库: admin\' --
- 后续某个功能(如“修改密码”)从数据库取出这个用户名,并直接拼接到 SQL:
sql
SELECT * FROM users WHERE username = 'admin\' --'
- 此时, \' 可能被当作字面量,导致 -- 注释符生效,注入成功。
总结
这条提示的核心是:
二次注入的漏洞往往藏在“数据插入后,又被取出来直接用在其他 SQL 操作”的代码里。
堆叠注入:
在名为NEWS的表中查询ID为1的值,并且创建一个表的名字为x x x。
在数据库中这个语句可以执行,但是注入的时候却注入不了原因,是因为一般开启只能执行一条SQL语句的开关。
并且你数据库也得支持这种语句。
所以说堆叠注入条件非常苛刻。
在 SQL 注入中,分号 ; 后面的单引号会被数据库 当作新语句的一部分处理,但由于后续语句通常不需要字符串闭合,这个单引号会被 忽略 或 导致语法错误(但不影响核心恶意命令的执行)。具体逻辑如下:
一、分号 ; 的核心作用:分割多条语句
在 MySQL 中,分号 ; 是 语句结束符,用于告诉数据库:
- “当前 SQL 语句执行完毕,请准备执行下一条语句”。
- 例如:
sql
SELECT * FROM users; -- 第一条语句
SHOW DATABASES; -- 第二条语句
数据库会先执行 SELECT ,再执行 SHOW DATABASES 。
二、注入 ';' 时的单引号处理
假设后端代码的原始 SQL 是:
php
$sql = "SELECT * FROM table WHERE id = '" . $user_input . "'";
场景:注入内容为 ';SHOW DATABASES;'
注入后,SQL 变为:
sql
SELECT * FROM table WHERE id = '1';SHOW DATABASES;
数据库的执行逻辑:
1. 第一条语句: SELECT * FROM table WHERE id = '1'
- 单引号 ' 正确闭合了字符串,语法合法。
- 分号 ; 表示这条语句结束。
2. 第二条语句: SHOW DATABASES;
- 这是一条 独立的新语句,不需要考虑前面的单引号(因为第一条语句已经结束)。
- 最后的单引号 ' 会被视为第二条语句的一部分,但由于 SHOW DATABASES 是一条独立的命令(不需要字符串闭合),这个单引号会被数据库 忽略 或导致语法错误(但通常不影响 SHOW DATABASES 的执行)。
三、关键结论:分号后的单引号通常会被忽略
- 分号 ; 的作用是 分割语句,而不是“省略单引号”。
- 分号后的单引号会被数据库视为 新语句的普通字符,但由于后续语句(如 SHOW DATABASES 、 DROP TABLE )不需要字符串闭合,这个单引号会被忽略或导致语法错误(但不影响核心恶意命令的执行)。
四、防御建议
- 使用 参数化查询(如 PDO 预处理语句),彻底分离 SQL 结构和用户数据,避免注入。
- 示例:
php
$stmt = $pdo->prepare("SELECT * FROM table WHERE id = ?");
$stmt->execute([$user_input]); // 自动处理特殊字符
最后面的set@a是封装,然后用ascll绕过过滤。
set必须是一个单独的语句才能执行。
带外:(主动把数据交出来)
第35个是控制安全文件配置的东西,所以有些时候Root并且支持load file也没用。
你要有高权限并且支持读取才行,而且没有安全配置文件。