文章总结: 本文作者分享了其作为漏洞赏金猎人的经历,讲述如何通过分析网页源代码和JavaScript文件,发现一个大型网站的在线客服聊天机器人存在严重漏洞。作者在Drupal设置JSON中找到聊天APIURL,进而在公开的env_app.js配置文件中获取到MQTT连接用户名、密码及URL等敏感信息。利用这些信息,作者通过Node.js脚本成功以admin身份登录,并使用通配符订阅主题,从而实时读取所有客户的支持聊天记录,导致用户个人数据泄露。最终,作者向HackerOne提交报告并获得四位数赏金。 综合评分: 90 文章分类: 渗透测试,WEB安全,实战经验,SRC活动,解决方案
0173.我是如何黑掉一个在线聊天机器人并赚到我的第一笔(四位数)赏金的
原创
Mahbubur Mahbubur
Rsec
2026年6月10日 11:28 贵州
在小说阅读器读本章
去阅读
本文章仅用网络安全研究学习,请勿使用相关技术进行违法犯罪活动。
声明:本文搬运自互联网,如你是原作者,请联系我们!
类型:聊天机器人
阿萨拉姆阿莱库姆。我是来自孟加拉国的兼职漏洞赏金猎人马赫布尔·拉赫曼·索拉夫 。
这是我的第一篇博文。我将分享我是如何在 HackerOne 上找到我的第一个四位数赏金的 。
本文讲述了我如何在一个大型网站的在线客服聊天机器人中发现一个严重漏洞,并获得漏洞赏金的故事。我将一步步详细介绍整个过程,分享我是如何发现、分析并负责任地报告这个漏洞的。
目标以及我的起点
我当时正在 HackerOne 的一个私有项目中进行攻击。主网站 ——https://www.[REDACTED].com——乍一看很正常。角落里有一个熟悉的客服聊天窗口:就是你需要帮助时点击的那个小气泡。
我并没有一开始就使用花哨的扫描器或复杂的漏洞利用链。我做了一件很多网络猎人至今仍然奉为圭臬的简单事:查看首页的源代码。源代码是浏览器在渲染页面之前下载的原始 HTML 和嵌入数据。公司有时会将 API URL、功能标志或后端主机名隐藏在这些数据中。我当时希望能够从中找到一些有用的信息。
确实如此。
页面中隐藏着聊天 API URL
我在页面源代码中发现了一个名为 “Drupal settings JSON” 的模块。Drupal 是一个常见的网站内容管理系统 (CMS),这个模块本质上是一个前端所需配置的集合。首页使用它来配置各种功能,包括角落里的客服聊天窗口小部件。
我在 JSON 文件中搜索了与聊天相关的任何内容。结果发现了一个用于聊天集成的小型对象。其中最重要的字段是 apiUrl 。它指向的是另一个主机上的完整 URL,而不是 www.[REDACTED].com 。
https://chat-backend.[REDACTED]:8081/custom?token=[redacted]
那是我找到的第一个真正线索。主站点告诉浏览器:“当有人打开聊天窗口时,请连接到端口 8081 上的服务器。”主机名 chat-backend.[REDACTED] 才是聊天应用程序实际运行的位置。如果配置出现错误,很可能就在这里——而不仅仅是在营销主页上。
因此,我的下一步行动是跟随该主机,继续执行在主站点上已经奏效的操作: JavaScript 侦察。
在 JS 侦察期间查找 env_app.js
#
Drupal 设置中的 apiUrl 显示聊天功能位于 chat-backend.[REDACTED]:8081 。我没有止步于首页,而是将侦察范围扩展到该服务器,开始收集和读取与聊天相关的 JavaScript 文件——思路与分析主站点上的包相同,只是这次针对的是聊天后端。
#
在进行 JS 代码审查时,我发现了 env_app.js 。我用浏览器打开了它:
https://chat-backend.[REDACTED]:8081/env_app.js
无需登录 , 也无需检查 cookie 。文件直接加载了。
env_app.js不是营销文案。它是聊天应用程序的环境配置文件 ——与实时聊天窗口加载的文件类型相同,以便窗口能够连接到后端。由于它是公开的,因此任何互联网用户都可以阅读它。我在文件中看到了 MQTT 连接的详细信息,包括类似这样的几行:
CWC_CONNECTION_USERNAME: 'cwc_user'CWC_CONNECTION_PASSWORD: '[redacted]'REACT_APP_CWC_MQTT_URL: 'wss://chat-backend.[REDACTED]:8081/mqtt'
所以,这个聊天应用通过 WebSocket ( wss://… ) 使用 MQTT 与服务通信。它甚至还设置了名为 cwc_user 用户的用户名和密码。即使我没有进一步深入研究,在 JS 文件中泄露代理 URL 和凭据本身就是一个危险的信号:它直接告诉攻击者该从哪里入手,以及哪些密钥可能有效。
这时我遇到了很多新手都会遇到的问题:我不知道 MQTT 是什么。 我以前从未在狩猎中使用过它。我只知道聊天感觉像是实时的,而这个配置正是应用程序实现实时性的方法。
MQTT 的真正含义
在展示我运行的命令之前,先用通俗易懂的方式解释一下 MQTT。
想象一下中间有个邮局(代理)。应用程序通常不会直接互相发送消息,而是将数据包发送到代理。每个数据包都会发送到一个主题,这就像收音机上的频道名称。其他应用程序会订阅它们感兴趣的主题。当有人向某个主题发布内容时,每个订阅者都会收到一份副本。
在这个聊天系统中,每个客户会话都有其自身的主题形式:
client/{session-id}/chat_session
所以每次聊天只能关注一个话题。如果经纪商只允许你订阅当前会话的话题,那么这种设计是合理的。
问题在于 MQTT 也支持通配符。”+”符号表示“匹配任意一个层级”。所以这个话题:
client/+/chat_session
这意味着“同时监听所有客户的聊天会话”。如果经纪商允许 admin 等权限较低的用户订阅此服务,那么您监听的就不再是一个聊天会话,而是整个支持队列。
这就是我需要测试的内容。但首先我需要一种登录经纪商的方法。
JavaScript (main.js) 中的线索
env_app.js中的凭据是针对 cwc_user ,而不是 admin 。我想了解应用程序是如何选择用户名的,所以我按照聊天机器人的前端构建过程进行了操作。
我打开了 asset-manifest.json 文件(一个已构建文件的映射表),并用它找到了 main.js—— 主应用程序包。阅读压缩后的 JS 文件很繁琐,但你要从中寻找的是关键信息:硬编码的密钥、调试接口、备用登录方式等等。
我在代码逻辑中找到了一个备用方案:如果未设置环境变量,应用程序将默认使用:
username:"admin"password:"admin"
这是个典型的错误。开发人员有时会在本地测试时设置默认账户,却忘记在服务器上也设置。代码里写的是 admin / admin ,但我测试代理时用的是用户名 admin密码为空——结果却能正常工作。(所以,实际环境中的错误配置甚至比直接使用默认的备用账户字符串还要糟糕。)
这让我得出了一个明确的假设:以 admin 身份连接,然后尝试使用通配符主题。
构建测试(借助人工智能)
我当时仍然不了解 MQTT 客户端的具体命令。我逐步利用人工智能来理解代理、主题、订阅与发布的区别,以及 client/+/chat_session 命令的作用。然后,我使用 mqtt 库,在 Node.js 中实现了一个小型概念验证程序。
首先安装库:
npm install mqtt
然后我运行了一条单行命令(主机名已隐去):
node -e "const c=require('mqtt').connect('wss://chat-backend.[REDACTED]:8081/mqtt',{username:'admin',password:'',rejectUnauthorized:false});c.on('connect',()=>{console.log('CONNECTED');c.subscribe('client/+/chat_session',{qos:0},()=>console.log('SUBSCRIBED'))});c.on('message',(t,m)=>console.log(t+': '+m.toString()));setTimeout(()=>process.exit(),60000)"
该脚本执行四项操作:
- 使用空密码,以 admin 用户身份通过 WebSocket ( wss://… ) 连接到 MQTT 服务器。`rejectUnauthorized rejectUnauthorized: false仅指示 Node 在此测试环境中接受 TLS 证书——关键在于弱登录。
- 连接成功后,订阅 client/+/chat_session 以便代理将来自所有匹配聊天主题的流量发送给我。
- 对于每条消息,将主题名称和 JSON/文本有效负载打印到终端。
- 60 秒后退出,以免测试无限期运行。
我不需要公司账号、VPN 或特殊网络。只需要 Node 和对公共 JS 中已有的代理 URL 的网络访问权限即可。
当它奏效时
我运行了脚本。它连接成功,也订阅成功。然后我的终端(速度很快)就开始出现一行行信息。
这并非测试沙箱。这些是目标网站上正在发生的实时客户支持聊天。每一行都包含一个主题和一个 JSON 数据块:会话元数据、聊天记录,有时还包含 JWT 令牌和会话 ID 。当客户在聊天中输入个人信息(例如电话号码、家庭住址、合同或服务信息)时,这些信息会显示在同一数据流中。有些消息还涉及安全敏感信息(例如 SIM 卡解锁请求),这使得其影响比仅仅读取营销问题更为严重。
我让它运行了大约三分钟,以确认问题真实存在且可以重现。在这短短的时间里,我统计到来自 10 个不同客户会话的88 条消息。这足以证明问题的存在。
然后我就停止了。我不需要囤积数据。报告的目的是展示缺陷的存在,而不是存档人们的对话。
为什么这会破坏信任
当用户发起客服聊天时,他们通常认为只有公司(或许还有客服人员)才能看到聊天内容。他们会输入账户问题、配送疑问、电话号码、地址——这些都是你不会发布到社交媒体上的信息。
这里,两个失败叠加在一起:
- 身份验证:代理接受了简单的 admin 登录(密码为空)。
- 授权:该用户可以订阅通配符主题并接收许多不相关的会话 。
攻击者可以身处世界任何地方,无需注册账号即可实时查看活跃的客服聊天记录。这并非复杂的攻击链,而是一个利用 JavaScript 文件中已公开线索构建的脚本。
报告和结果
2026 年 3 月中旬,我向 HackerOne 提交了调查结果:清晰的重现步骤、Node 命令模式、简短的 PoC 视频、编辑后的示例以及一个简明的影响部分(未经授权访问私人支持对话、个人数据泄露、高度机密风险)。
问题分类并非一条消息就能解决。我不得不反复解释问题的真正原因。最终,系统认定这是一个有效的严重级别问题。对我个人而言,这也意义非凡:这是我第一次获得四位数赏金。
我汇报之后(与分诊员的对话)
初步处理人员的第一条回复很有礼貌,但听起来像是重复之前的报告。他们说,该项目已经审查过类似的发现。之前的结论大致如下:暴露的聊天配置和公共 MQTT 连接可能是故意的,因为聊天窗口本身是公开的,用户身份验证发生在之后——而且根据之前的审查——即使暴露了这些信息,也无法读取或拦截其他人的消息。
我知道我的发现与众不同,所以我冷静地回答,并坚持陈述事实。
公共代理连接或许在设计上是可以接受的。但这并非核心漏洞。核心漏洞在于 MQTT 主题的授权:任何人都可以订阅 client/+/chat_session 并接收来自其他客户的实时聊天会话。我的概念验证视频展示了真实的字段——家庭住址、电话号码、服务 ID——实时流动。我还直接提出了一个问题:之前的报告是否真正展示了跨客户的实时数据,还是仅仅提到了暴露的配置文件和凭据?这两者的严重程度并不相同。
那条信息改变了语气。
分诊员在他们的工程团队重新测试后返回了结果。简而言之,他们证实了我之前所说的:
我们已对此进行测试,并在工程方面确认这是真实的客户数据。之前的报告并未显示任何实时数据泄露。聊天机器人已暂时关闭,直至问题修复。
我向他们表示了感谢。在仍有可能泄露客户个人身份信息的情况下,立即将聊天机器人下线是正确的做法。
几天后,他们要求我重新测试修复方案,并提供 IP 地址和时间戳,以便他们改进日志记录并将我的流量排除在调查之外。我重新测试后确认漏洞已修复—— 我无法再订阅通配符主题。我提供了网络和时间详情。聊天机器人一直处于宕机状态,直到后端恢复安全。
结语
这次搜寻让我意识到,枯燥的侦察最终还是会奏效。页面源代码指向聊天 apiUrl ,聊天主机指向 env_app.js 文件,该文件又指向一个我必须临时学习的协议,而应用程序的 JS 代码则给了我最终的线索,让我知道该尝试哪个账号。人工智能帮助我学习和构建测试,但证据来自互联网上已经公开的信息。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Rsec Mahbubur Mahbubur《0173.我是如何黑掉一个在线聊天机器人并赚到我的第一笔(四位数)赏金的》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论