强网杯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/9/23 4:38:46 阅读更多 →
深度解析Wan2.2-VAE:突破性视频压缩技术的3大创新

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

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

2026/9/23 16:39:38 阅读更多 →
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/9/16 9:44:57 阅读更多 →

最新新闻

基于Python的舆情热点分析平台:从网易新闻爬虫到情感可视化

基于Python的舆情热点分析平台:从网易新闻爬虫到情感可视化

简介:面向Python课程设计与毕业设计的一站式舆情热点分析平台源码,完整覆盖从网易新闻及评论抓取、数据清洗、中文分词、停用词过滤、情感分析、关键词提取到时间序列分析与可视化展示的典型数据科学流程。资源共1403个文件,约23.83MB&#x…

2026/9/24 0:49:52 阅读更多 →
AI Skill 商业化指南:从能力单元到稳定收入的完整路径

AI Skill 商业化指南:从能力单元到稳定收入的完整路径

1. 先搞清楚你手里的 Skill 到底是什么货1.1 Skill 不是“提示词合集”,别把它想小了很多人第一次接触 Skill 这个概念,会下意识觉得“不就是把一段提示词打包一下吗”。这个理解不能说全错,但确实把 Skill 想得太窄了。我见过太多人拿着一个…

2026/9/24 0:49:52 阅读更多 →
YOLO舰船目标检测实战:数据转换、训练调参与部署避坑指南

YOLO舰船目标检测实战:数据转换、训练调参与部署避坑指南

简介:这份资源面向深度学习与计算机视觉方向的学习者和研究者,提供一套基于YOLO算法的舰船目标检测完整实现方案,可用于海上救援、军事侦察、交通控制等场景下的船只自动识别研究。资源包共60个文件,包含55张jpg舰船图像、2个mat数…

2026/9/24 0:49:52 阅读更多 →
C# OnnxRuntime部署DAMO-YOLO人头检测实战指南

C# OnnxRuntime部署DAMO-YOLO人头检测实战指南

简介:本资源是一套面向C#开发者与计算机视觉初学者的DAMO-YOLO人头检测实战部署方案,聚焦安防、人群密度分析等实际场景,解决传统YOLO模型在C#环境难以直接调用的工程落地难题。压缩包共500个文件,含111个运行依赖DLL、4个ONNX模型…

2026/9/24 0:49:52 阅读更多 →
ECG心电信号分类实战:Python与Matlab双版本实现与避坑指南

ECG心电信号分类实战:Python与Matlab双版本实现与避坑指南

简介:这是一份面向医学数据分析、生物医学工程及机器学习初学者的ECG心电信号分类资源包,整合Python与MATLAB两套实现方案,帮助学习者掌握从信号预处理、特征提取到分类建模的完整流程。压缩包共825个文件,约6.25MB,核…

2026/9/24 0:46:51 阅读更多 →
YOLOv7打电话检测实战:双格式数据集与训练部署全解析

YOLOv7打电话检测实战:双格式数据集与训练部署全解析

简介:YOLOv7打电话行为检测项目,面向计算机视觉开发者与边缘设备部署场景,适合需要快速落地手持电话识别功能的工程人员及高校研究者。压缩包提供训练好的权重、完整训练代码以及配套数据集,可直接加载权重进行图片/视频推理&…

2026/9/24 0:46:51 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →