强网杯SQL注入实战:绕过SELECT过滤的HANDLER与预编译技巧
1. 项目概述一次经典的SQL注入实战复盘最近在带新人做CTFCapture The Flag题目训练翻到了这道来自“强网杯 2019”的经典题目——“随便注”。这名字起得挺有意思听起来很随意但实际考察的却是SQL注入中非常核心且基础的知识点。对于刚接触Web安全的新手来说这道题是一个绝佳的“磨刀石”它能帮你把SQL注入的整个攻击链条从信息探测到最终利用完整地走一遍。很多朋友可能觉得SQL注入是老生常谈但真正能把每一步的原理、绕过技巧和利用手法都讲清楚、练扎实的并不多。今天我就以这道题为例带大家从头到尾拆解一遍不仅告诉你“怎么做”更重点剖析“为什么这么做”以及在实际渗透测试中你可能会遇到哪些变种和更复杂的防御手段。这道题的环境是一个典型的、存在SQL注入漏洞的Web查询接口。我们的目标就是利用这个漏洞获取数据库中的敏感信息也就是所谓的“Flag”。题目之所以经典在于它没有设置过于花哨的WAFWeb应用防火墙或过滤规则而是聚焦于最基础的联合查询注入、堆叠注入以及MySQL数据库特性利用。通过它我们可以清晰地理解如何手动构造Payload、如何判断注入点类型、如何一步步获取数据库结构并最终读取数据。下面我们就进入正题。2. 初探靶场与注入点判断2.1 目标界面与功能分析通常这类题目的前端是一个简单的输入框比如一个搜索框或查询框允许用户提交参数。我们假设目标URL是http://靶场地址/?inject参数的形式。第一步永远是信息收集。我们打开页面可能会看到一个提交查询的输入框。作为测试我们先输入一个数字1查看返回结果。页面返回了对应的数据记录这很正常。关键的第一步是探测这里是否存在SQL注入漏洞。最经典的方法是使用单引号‘来闭合SQL语句中的字符串。我们在输入框提交1‘。如果页面返回了与正常查询比如1不同的结果比如报错信息、空白页或者查询逻辑异常那么这里就可能存在注入点。在这道题中提交1‘后页面很可能会返回一个详细的SQL语法错误信息例如You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘1’’ at line 1这个报错信息是黄金线索。它明确告诉我们两件事第一后端数据库是MySQL第二我们的输入被直接拼接到了SQL语句中并且单引号破坏了语句结构导致了语法错误。这初步确认了存在字符型注入漏洞。2.2 确认注入类型与闭合方式知道有注入点后我们需要确定注入的类型和原SQL语句的闭合方式。常见的闭合方式有单引号‘、双引号“有时还会包含括号()。从上面的报错信息near ‘‘1’’可以看出我们输入的1‘在数据库中被处理成了‘1‘‘。这说明原语句大概是SELECT ... FROM ... WHERE id‘用户输入‘这样的结构。我们输入1‘后语句变成了SELECT ... FROM ... WHERE id‘1‘‘最后一个单引号成了多余的单引号导致语法错误。为了修复这个语法错误并让语句正确执行同时又能插入我们自己的SQL代码我们需要“注释掉”原语句后面的部分。在MySQL中注释符有两种#URL中需编码为%23和--注意后面有个空格。我们尝试构造Payload1‘ --。这个Payload的意思是1‘用于闭合前面的单引号--空格很重要用于注释掉后面所有的原始SQL代码。提交这个Payload后如果页面正常返回了id1的数据那么就证明我们成功控制了SQL语句并且确认了闭合方式是单引号注入类型为字符型注入。注意在浏览器URL中或表单提交时空格可能会被处理。--后面的空格有时会被忽略为了确保万无一失通常直接使用--来代替。在URL中表示空格。所以更常见的Payload是1‘ --。3. 信息获取与联合查询注入尝试3.1 确定字段数量在可以进行联合查询UNION SELECT的情况下第一步是确定当前查询语句返回的字段列数。我们使用ORDER BY子句来探测。ORDER BY用于根据指定的列索引对结果进行排序。如果索引超过了实际列数数据库就会报错。我们依次提交Payload1‘ order by 1 --(页面正常)1‘ order by 2 --(页面正常)1‘ order by 3 --(页面报错)当order by 3报错时说明当前查询结果只有2列。这是一个非常关键的结论意味着我们后续使用UNION SELECT时必须拼接两个字段。3.2 尝试联合查询并遭遇过滤知道了字段数接下来自然是想通过联合查询来获取数据。我们构造Payload-1‘ union select 1,2 --。这里将id设为-1一个不存在的值是为了让原查询结果为空从而确保页面显示的是我们union select出来的1和2。这两个数字是占位符用于测试哪个字段的内容会回显在页面上。然而提交这个Payload后页面返回了关键信息return preg_match(/select|update|delete|drop|insert|where|\./i,$inject);。这行代码是题目的核心过滤规则。它使用preg_match函数以不区分大小写的方式/i检测我们的输入中是否包含以下关键词select,update,delete,drop,insert,where以及点号.。这意味着我们想直接使用UNION SELECT来查询数据的常规路径被堵死了。select和union都被禁用了。同时禁止了点号也限制了我们使用database.table这样的形式进行跨库查询。这是一道典型的“代码层过滤”题目需要我们思考绕过方法。4. 堆叠注入与架构探秘4.1 什么是堆叠注入当常规的联合查询被禁用后我们就要考虑其他注入技术。这里题目留下了一个重要的“后门”堆叠查询注入。堆叠注入是指通过分号;将多条SQL语句分隔开并一次性提交执行。并非所有数据库或连接驱动都支持堆叠查询但MySQL在特定配置下是支持的。幸运的是这道题的环境支持堆叠注入。我们可以构造Payload1‘; show databases; --。这个Payload的执行逻辑是先执行原查询SELECT ... FROM ... WHERE id‘1‘然后分号开启一个新语句执行SHOW DATABASES;用于列出所有数据库名。提交后页面除了显示id1的查询结果很可能还会将数据库列表也显示出来。通过这一步我们验证了堆叠注入是可行的并且看到了系统中有哪些数据库比如information_schema,mysql,ctftraining, 以及一个可能存放flag的数据库。4.2 深入数据库与表结构既然show databases成功了我们就可以利用MySQL的SHOW命令来绕过对SELECT关键词的过滤一步步探查数据结构。查看当前数据库1‘; show tables; --这条命令会列出当前数据库中的所有表。假设我们看到的返回结果中有两个表1919810931114514和words。这里注意第一个表名是一串纯数字这很不寻常很可能就是存放flag的表。查看表结构接下来需要知道每个表里有哪些列。由于DESC 表名或SHOW COLUMNS FROM 表名内部可能也使用了SELECT在某些版本或解释中我们采用更直接的SHOW CREATE TABLE命令。这个命令会返回创建该表的完整SQL语句里面就包含了列定义。Payload forwords表1‘; show create table words; --Payload for 数字表1‘; show create table1919810931114514; --(注意纯数字的表名需要用反引号包裹否则会被解释为数字而语法错误)假设返回信息显示words表结构CREATE TABLE words (id int(10) NOT NULL, data varchar(20) NOT NULL)1919810931114514表结构CREATE TABLE 1919810931114514 (flag varchar(100) NOT NULL)至此我们完全摸清了数据库结构当前数据库下有两个表。words表有id和data两列这很可能就是前端查询默认操作的表。而1919810931114514这个表只有一列flag毫无疑问目标flag就存放在这里。5. 核心挑战绕过SELECT过滤读取数据现在我们面临核心难题我们知道flag在1919810931114514表的flag列里但过滤规则禁止使用SELECT来读取它。我们必须找到一种不使用SELECT关键词却能获取数据的方法。这里就需要一些MySQL的“骚操作”了。5.1 思路一使用HANDLER语句本题可用方案MySQL提供了一个相对冷门但很有用的命令HANDLER。它可以用于直接访问表的存储引擎接口实现类似游标的方式逐行读取数据而且语法中不包含SELECT。使用HANDLER的基本步骤如下打开表HANDLER 表名 OPEN;读取第一行HANDLER 表名 READ FIRST;读取下一行HANDLER 表名 READ NEXT;可重复执行以遍历数据关闭句柄HANDLER 表名 CLOSE;我们可以构造堆叠注入Payload来执行1‘; HANDLER1919810931114514OPEN; HANDLER1919810931114514READ FIRST; --执行后HANDLER ... READ FIRST语句会返回目标表的第一行数据也就是我们梦寐以求的flag。页面会将其内容显示出来。这是解决此题最直接、最优雅的方法之一。5.2 思路二预编译语句配合字符串拼接另一种强大绕过如果题目连HANDLER也过滤了虽然本题没有我们还可以祭出更高级的技巧预编译语句。其核心思想是将我们想要执行的SELECT语句拆分成字符串利用PREPARE准备和EXECUTE执行来动态执行SQL从而绕过对完整SELECT关键词的静态匹配。整个流程如下设置变量将查询语句的字符串形式存入一个变量。由于过滤了select我们可以用十六进制编码或concat函数来拼接。set sql concat(sel,ect flag from1919810931114514);这里用concat(sel,ect ...)巧妙地绕过了对完整单词select的匹配。预编译语句prepare stmt from sql;这条命令将变量sql中的字符串准备成一个可执行的SQL语句命名为stmt。执行语句execute stmt;执行预编译好的语句效果就等同于执行了SELECT flag FROM 1919810931114514。释放资源deallocate prepare stmt;我们可以将其组合成一个堆叠注入Payload1‘; set sqlconcat(sel,ect flag from1919810931114514); prepare stmt from sql; execute stmt; --这个方法非常强大因为它可以将被禁用的关键词拆解、编码或隐藏在变量中是绕过WAF和简单正则过滤的利器。5.3 思路三修改表结构“偷梁换柱”本题预期解还有一种非常巧妙的思路它不直接去读flag表而是改变前端查询的逻辑。我们回顾一下前端查询大概率是SELECT * FROM words WHERE id ‘用户输入‘。words表有id和data两列。1919810931114514表只有flag一列。如果我们能把1919810931114514这个表的名字改成words同时把它唯一的flag列改名为id或data那么当前端程序执行它固有的SELECT * FROM words ...查询时实际上查的就是我们改名后的、存放flag的表了具体操作步骤如下通过堆叠注入执行重命名原words表先把默认的words表改个名腾出位置。rename table words to any_other_name;重命名flag表为wordsrename table1919810931114514to words;修改新words表的结构现在名为words的表是原来的flag表它只有一列flag。我们需要给它增加列或者修改列名。但ALTER TABLE命令可能被过滤虽然本题没提且操作稍复杂。一个更简单的想法是我们不需要修改它只需要让前端查询能“碰到”flag就行。如果前端查询是SELECT id, data FROM words那么因为新表没有这些列会报错。但如果前端查询是SELECT * FROM words且flag列的类型是字符串那么查询1‘ or 11 --可能会把所有的flag行都显示出来。 实际上更精准的做法是修改列名。但MySQL中修改列名 (CHANGE COLUMN) 需要知道原列名和数据类型。我们已知原列名为flag。可以尝试alter table words change flag id varchar(100);这会把flag列改名为id。但这里有个问题原words表有两列现在新words表只有一列改名后的id查询SELECT *可能还是会出错。更常见的预期解是为flag表添加一个与words表结构一致的列。但考虑到步骤繁琐且题目环境可能不支持多次执行这种“偷梁换柱”的方法思路巧妙但在实际操作中可能不如HANDLER或预编译语句直接。不过它体现了在SQL注入中利用数据库本身的操作DML和DDL来改变应用程序上下文的高级思维。6. 实操过程与最终Payload构造综合以上分析最稳妥、最快捷的解法是使用HANDLER语句。下面我们模拟完整的攻击链探测与确认访问目标输入1‘看到MySQL报错确认字符型注入。输入1‘ --页面正常确认闭合方式与注释有效。绕过联合查询输入1‘ union select 1,2 --页面返回过滤规则得知select等关键词被禁。利用堆叠注入探查输入1‘; show databases; --查看所有数据库确认当前库。输入1‘; show tables; --发现words和1919810931114514两个表。输入1‘; show create table 1919810931114514; --确认该表存在flag列。最终读取数据构造最终Payload1‘; HANDLER 1919810931114514 OPEN; HANDLER 1919810931114514 READ FIRST; --提交Payload页面成功显示flag{th1s_1s_a_simp1e_f1ag}或类似内容。至此Flag获取成功。整个过程中我们绕过了对SELECT关键词的过滤通过堆叠注入执行SHOW和HANDLER命令完成了信息收集和数据读取。7. 总结与实战经验延伸这道“随便注”题目虽然基础但涵盖的知识点非常全面注入点判断、闭合方式确认、字段数探测、联合查询尝试、关键词过滤识别、堆叠注入利用、MySQL特有命令SHOW,HANDLER以及预编译语句的绕过思路。它完美地展示了当一条路UNION SELECT被堵死时一名渗透测试人员应该如何灵活运用已有的知识库寻找新的突破口。在实际的渗透测试或CTF比赛中以下几点经验尤为重要信息收集是基石不要一上来就想着用自动化工具梭哈。手动测试仔细阅读每一次的页面回显和报错信息。像本题中MySQL的详细报错就是最宝贵的线索。理解过滤逻辑看到过滤规则如preg_match不要慌仔细分析它过滤了哪些关键词、字符。思考这些过滤是否可以绕过是大小写绕过、双写绕过、编码绕过还是像本题一样寻找功能等效但关键词不同的替代命令如用SHOW代替部分SELECT功能用HANDLER代替SELECT读取数据善用数据库特性不同的数据库MySQL、PostgreSQL、SQL Server、Oracle有大量特有的系统表、内置函数和命令。熟练掌握这些特性往往能在关键时刻出奇制胜。比如MySQL的information_schema库、SHOW命令、HANDLER命令、PREPARE/EXECUTE语句等。堆叠注入的利用条件堆叠注入并非万能它取决于Web应用使用的数据库连接驱动如PHP中的mysqli_multi_query函数支持而mysqli_query或PDO::query默认不支持。在实战中如果发现分号;后提交的语句被执行了就要立刻想到堆叠注入的可能性。工具与手工结合Sqlmap等自动化工具很强大但在面对复杂过滤或非常规注入点时手工测试和构造Payload的能力不可或缺。这道题就是典型的手工优于自动化工具的场景因为工具可能无法自动识别并利用HANDLER这种非标准的注入方式。最后这道题也提醒我们开发人员防御SQL注入绝不能仅仅依赖简单的关键词黑名单。参数化查询预编译语句才是从根本上解决注入问题的黄金标准。同时要遵循最小权限原则数据库用户不应拥有执行DROP,RENAME,HANDLER等高危命令的权限。安全是一个攻防对抗、不断演进的过程只有深入理解攻击者的思路才能更好地构筑我们的防线。

相关新闻

基于3D高斯溅射的机器人仿真场景重建:从手机视频到数字孪生

基于3D高斯溅射的机器人仿真场景重建:从手机视频到数字孪生

摘要 本文记录一次工程实践:如何把一段普通手机拍摄的视频,在 30 到 60 分钟内自动转换为可直接用于机器人仿真训练的数字孪生场景。方案整合了运动恢复结构(SfM)、3D Gaussian Splatting 神经渲染与语义分割物体提取&#xff0c…

2026/10/16 15:24:28 阅读更多 →
深度解析Wan2.2-VAE:突破性视频压缩技术的3大创新

深度解析Wan2.2-VAE:突破性视频压缩技术的3大创新

深度解析Wan2.2-VAE:突破性视频压缩技术的3大创新 【免费下载链接】Wan2.2-TI2V-5B Wan2.2-TI2V-5B是一款开源的先进视频生成模型,基于创新的混合专家架构(MoE)设计,显著提升了视频生成的质量与效率。该模型支持文本生…

2026/10/20 17:03:14 阅读更多 →
3分钟掌握:Blender 3MF插件终极指南

3分钟掌握:Blender 3MF插件终极指南

3分钟掌握:Blender 3MF插件终极指南 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 还在为Blender无法直接处理3D打印文件而烦恼吗?Blender3mfFor…

2026/10/17 17:57:11 阅读更多 →

最新新闻

Function Calling 422 排查:tool 消息 content 为 null 的修复全记录

Function Calling 422 排查:tool 消息 content 为 null 的修复全记录

上周我把一个 Function Calling 任务切到 deepseek-v4.1-flash,本地跑得好好的,一上远端就开始 422。第一反应是参数写错了,翻来覆去检查代码没看出问题,直到把底层 HTTP 请求体完整 dump 出来,才发现 tool 角色的 con…

2026/10/21 0:36:01 阅读更多 →
Vidu Q4 Preview深度评测:AI视频生成迈向生产力工具的关键一步

Vidu Q4 Preview深度评测:AI视频生成迈向生产力工具的关键一步

最近几个创作群里讨论最多的,绕不开Vidu Q4 Preview。做AI视频的同仁应该都有感觉,这个赛道现在卷到什么程度:几乎每隔几天就有新版本、新模型冒出来,但大多是“看起来厉害、一上手就露馅”。Vidu Q4 Preview这次放出的内容&#…

2026/10/21 0:33:56 阅读更多 →
AI在芯片设计中的黑盒困局:一次IR压降事故带来的反思

AI在芯片设计中的黑盒困局:一次IR压降事故带来的反思

芯片世界里,有一句话最近被工程师们重复得越来越多:AI赢了棋局,却讲不出思路。就在上个月,我拿着一个AI辅助完成的block级floorplan给物理设计团队,线长比上一版少了12%,拥塞图也干净得不像话。结果等IR压降…

2026/10/21 0:33:56 阅读更多 →
计算智能体入门:从状态机到Q-learning的决策实现

计算智能体入门:从状态机到Q-learning的决策实现

1. 从零理解计算智能体的核心骨架计算智能体这个概念,听起来像是学术论文里的术语,但把它拆开来看,其实就是一个能感知环境、做出决策、执行动作的软件实体。你可以把它想象成一个在迷宫里找路的小机器人,它能看到周围哪里有墙、哪…

2026/10/21 0:33:55 阅读更多 →
MoE混合专家模型:稀疏激活如何破解大模型容量与成本困局

MoE混合专家模型:稀疏激活如何破解大模型容量与成本困局

从Transformer诞生起,前馈网络(FFN)就是"又笨重又绕不开"的角色:它占了模型近三分之二的参数量,但每个token都得老老实实把所有参数过一遍。你扩大模型容量,推理成本就跟着线性往上涨&#xff0c…

2026/10/21 0:33:55 阅读更多 →
开源30B模型硬刚闭源旗舰:科研场景实测与本地部署指南

开源30B模型硬刚闭源旗舰:科研场景实测与本地部署指南

最近开源圈又热闹起来了,一个主打科研场景的30B级别开源模型,直接放话要跟两家头部闭源大模型掰手腕。我当时第一反应是“又来一个刷榜的”,但仔细看完技术报告和社区实测数据之后,觉得这波还真不是营销话术,确实有货。…

2026/10/21 0:33:55 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →