找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4052

积分

0

好友

533

主题
发表于 1 小时前 | 查看: 4| 回复: 0

客户端里的“盲人摸象”?用恶意JavaScript搞定未知应用

应用渗透测试人员在编写定制化的恶意JavaScript时,常常目标明确。他们手握测试账号,熟知应用的业务逻辑,知道要窃取何种“核心数据”——无论是批量下载文档、提升自身权限,还是发起转账操作。编写这样的Payload,如同拿着地图寻宝。

然而,对于红队成员而言,情况截然不同。他们面对的往往是完全陌生的应用:功能未知、逻辑未知,甚至连有没有用户登录都是未知数。更关键的是,除了XSS漏洞,红队还可能有其他向应用注入恶意JavaScript代码的途径。这种情况下,预先定制化的Payload基本失效了,怎么办?

这正是JS-Tap诞生的背景。它是一款专门为红队打造的通用JavaScript武器化工具。它不执着于直接攻击应用服务器,而是将注意力集中在客户端,像一个无声的“观察者”,系统性地提取对攻击者有用的情报。即便你对目标应用一无所知,甚至目标用户都未登录,它也能运作。

JS-Tap能窃取哪些“战利品”?

一旦JS-Tap的有效载荷在目标浏览器中运行,它就会开始悄悄收集以下信息:

  • 客户端指纹:IP地址、操作系统、浏览器版本。
  • 用户输入:文本框中的按键记录(最典型的应用就是窃取登录凭据)。
  • 浏览轨迹:用户访问过的所有URL。
  • 存储数据:未设置HttpOnly标志的Cookie、LocalStorage和SessionStorage。
  • 页面快照:当前页面的HTML源码(可选)和屏幕截图。
  • 网络请求:XHR和Fetch API调用的完整副本(可选,需开启Monkeypatch)。其中包含:
    • 请求端点
    • 请求方法(GET、POST等)
    • 设置的请求头(包括关键的Authorization头)
    • 请求体和响应体

收集到的所有数据,都会实时汇总到一个基于Web的JS-Tap门户中,供攻击者监控和分析。

两种模式,两种玩法:trap vs implant

JS-Tap的Payload提供了两种操作模式,以应对不同的攻击场景。

陷阱模式 (trap)

这是用作XSS Payload时的标准模式。XSS攻击有个痛点:Payload的生命周期很短暂。一旦用户关掉弹窗,或者从当前页面跳转,注入的恶意脚本就会消失。

陷阱模式利用iframe陷阱技术解决了这个问题。Payload一旦执行,会创建一个覆盖全屏的iframe,并将用户重定向到应用的某个合法起始页(比如后台登录页)。用户看似在正常操作,但实际上,他一直被困在我们构建的恶意页面之上,Payload得以持续运行。

在这个过程中,JS-Tap还会巧妙地伪造浏览器地址栏,使其与iframe内的URL保持一致,进一步打消用户的疑虑。

注意:如果目标应用设置了严格的CSP(内容安全策略)或X-Frame-Options标头,这种技术可能会失效。一些基于JavaScript的“框架破坏者”也能阻止iframe陷阱。

植入模式 (implant)

当你已经拿到一台应用服务器或托管JavaScript文件的服务器权限时,植入模式就派上用场了。你可以直接将JS-Tap的Payload注入到一个被广泛引用的JS文件里(比如jQuery.jsmain.js),实现“守株待兔”。

植入模式无需iframe陷阱,任何访问了被感染页面的用户,其浏览器都会加载并运行JS-Tap,悄无声息地成为我们的“目标”。

实战演示:给WordPress下个套

光说不练假把式。我们用JS-Tap来对付一个存在反射型XSS漏洞的WordPress站点,看看具体如何操作。

目标:诱骗管理员登录WP后台、检查插件并为新员工创建一个管理员账户。我们的目标是窃取其登录凭据和新账户的密码。

图中展示了WordPress中可被利用的XSS漏洞点。

浏览器地址栏显示XSS攻击payload和警告弹窗的演示截图。

接下来,启动JS-Tap服务端,获取Web管理后台的登录凭据,并将Payload配置为陷阱模式,起始页设定为WordPress管理员登录页。

终端界面展示启动JS-Tap服务端、生成管理员凭据和运行Flask应用的过程。

我们将漏洞利用的PoC替换为指向jsTapServer的Payload (telemlib.js),用户一旦访问以下URL就会中招:

http://targetapp.localdemo/wp-content/plugins/sketchyPlugin/unauthXSS.php?param=

当目标用户打开此链接时,看到的并非杂乱代码,而是一个“正常”的登录页面。

WordPress登录页面截图,上方地址栏显示为正常的wp-login.php链接。

实际上,这个页面正是我们设置的iframe陷阱。用户能看到地址栏是正常的,便不会起疑。假设我们的钓鱼话术成功,管理员开始登录。

WordPress登录表单,用户名输入admin,密码已填写,即将点击登录按钮。

登录成功,进入仪表盘。注意右上角用户名和看似正常的URL,受害者毫无察觉。

WordPress管理后台仪表盘页面,显示欢迎信息和站点概况。

管理员按指示查看了插件页面,未发现异常。

WordPress插件管理页面,显示已安装的Akismet Anti-Spam插件。

随后,管理员转到用户列表,开始为“新员工”创建账户。

WordPress用户列表页面,仅显示admin一个管理员账户。

管理员进入“添加新用户”页面。他创建了newAdmin账户,但出于安全考虑,并没有手动输入密码,而是使用了WordPress自动生成的强密码(我们假设他会把密码记录下来发给新员工)。这正是我们的机会。

WordPress添加新用户表单,用户名已填newAdmin,密码区域显示自动生成的强密码,角色选择为管理员。

至此,用户的操作告一段落。让我们回到JS-Tap门户,看看都捞到了什么。左侧客户端列表已出现一个新会话。

JS-Tap门户客户端列表,显示一个名为wacky-azure-kangaroo的在线客户端及其系统信息。

点击该客户端,右侧会按时间线列出所有捕获到的事件,如URL访问、Cookie信息、本地存储数据等。

JS-Tap门户的Loot区域,展示了从客户端收集到的URL访问、Cookie和LocalStorage等事件数据。

在持续滚动的事件流中,我们看到了“HTML Scraped”、“URL Visited”和一个至关重要的“Screenshot Captured”事件。

JS-Tap事件流显示HTML抓取、URL访问和屏幕截图捕获记录,截图内容为WordPress登录页面。

点开“View Code”就能查看抓取到的页面HTML源码。

代码查看器弹窗,展示了从WordPress登录页面抓取的完整HTML源码。

继续往下看,激动人心的“User Input”事件出现了!我们成功捕获了管理员输入的账户名admin和密码Password123!

JS-Tap事件流中用红框标出的用户输入记录,清晰地显示了输入框名称和键入的值,即用户名和密码。

第一波战利品到手!赶紧把它们存到客户备注里。

弹出笔记窗口,管理员凭据被粘贴到关于wacky-azure-kangaroo客户端的备注中。

接着,我们看到了WordPress仪表盘的截图,可以确认账户确实是管理员。

JS-Tap捕获的WordPress仪表盘截图,显示了完整的管理功能概览。

在接下来的事件中,我们看到了新用户注册表单的页面截图。

JS-Tap事件流和截图,展示了“添加新用户”的空白表单页面。

紧随其后的就是一系列新的“User Input”事件,记录了为newAdmin用户填入的信息。

一连串用户输入事件,显示正在输入新管理员的用户名newAdmin和电子邮箱等信息。

咦?密码呢?管理员确实没有手动输入密码,而是用了自动生成的功能。我们把那张表单截图放大看看。

放大的“添加新用户”表单截图,红框高亮显示密码区域,可以看到“Generate password”按钮。

果然,密码区域显示的是“Generate password”(生成密码)按钮,说明密码是自动生成的。但既然页面显示了密码,它就肯定藏在HTML源码里!我们立刻回头去下载这个页面的HTML代码。

代码编辑器展示从添加新用户页面抓取到的HTML文件内容,标题为Add New User。

在源码中搜索“Generate password”,我们迅速定位到了关键代码段。一个input标签的data-pw属性,赫然暴露了自动生成的强密码!

代码编辑器高亮显示了HTML源码中密码输入框的data-pw属性,其值为一串复杂的强密码。

大获全胜!所有收获都记录到了客户备注里。

弹出笔记窗口,除了之前的第一个管理员凭据外,现在新增了新管理员newAdmin的用户名和自动生成的密码。

进阶功能:拦截API调用,看穿单页应用

WordPress只是开胃菜。对于现代动态Web应用(尤其是单页应用),页面不刷新,数据都通过API请求异步加载。这时,JS-Tap的另一项绝活——Monkeypatch API——就派上用场了。

JavaScript一个奇妙的特性是“猴子补丁”(Monkeypatching),即在运行时动态修改代码的行为。JS-Tap正是利用这一点,在你不知情的情况下,悄悄修改了浏览器底层的XMLHttpRequest (XHR) 和Fetch API,从而拦截所有网络请求

我们有一个用于测试的演示应用,它通过三种方式(XHR、Fetch、jQuery)发起网络请求以获取“生命奥秘”的答案。

Monkeypatch Lab演示应用界面,包含三个请求按钮和一个注入JS-Tap Payload的按钮。

在注入Payload前,我们要在telemlib.js的配置中,将起始页指向这个应用,并启用API拦截和API调用后截图的功能。

代码编辑器截图,红框高亮显示JS-Tap配置中设置新起始页URL的代码行。

启用 monkeypatch API 原型:

代码编辑器截图,高亮显示设置monkeyPatchAPIs为true的代码行。

设置API调用后截图及其延迟:

代码编辑器截图,高亮显示postApiCallScreenshot和screenshotDelay配置项的代码行。

配置修改完毕,注入Payload。用户点击完三次按钮后,JS-Tap门户里出现了新的客户端。

JS-Tap门户客户端列表,新增了一个名为cuckoo-olive-quokka的客户端。

查看新客户端的事件,我们首先捕获到了一个藏在LocalStorage中的SECRET_API_KEY_FALL_2023!,它是一个鉴权令牌。

JS-Tap事件流,红框高亮显示从LocalStorage中提取的Authorization Key和对应的令牌值。

把它也保存到备注里。

弹出笔记窗口,LocalStorage中的鉴权令牌被保存到cuckoo-olive-quokka客户端备注中。

继续往下滚动事件列表,API调用的细节一览无余。这里展示了一个XHR API调用的完整过程:请求端点/api/xhrAnswer、方法POST、设置的Content-TypeAuthorization头,以及一个“View API Call”按钮。

事件列表详细记录了一次XHR请求的Open, Set Header和Call过程。

点击“View API Call”,请求体和响应体并排展示,请求发送{"request": "answer"},响应返回{"answer": "42 of course!"}

API Call Viewer弹窗,并排显示XHR请求的JSON请求体和响应体。

紧接着,延迟的截图也送到了,页面上果然显示着“Answer: 42 of course!”。

延迟捕获的截图,显示Monkeypatch Lab应用的页面上已经展示了答案42 of course。

Fetch API的调用也被以同样方式拦截。可以看到,响应中的答案是“Definitely vegemite.”。

API Call Viewer弹窗,显示Fetch请求的响应体,答案为Definitely vegemite。

最后,连通过jQuery发出的请求,在底层同样被XHR API拦截并捕获,暴露了其请求端点为/api/jqueryAnswer

事件列表显示被拦截的jQuery API调用,其底层请求被识别为对/api/jqueryAnswer的XHR调用。

任务结束,我们可以把针对所有客户记下的笔记一键导出。

All Client Notes弹窗,汇总展示了所有客户端的笔记信息。

总结

JS-Tap为红队提供了一套极具价值的通用客户端攻击武器库。它不依赖对应用的后验知识,能将大量看似无关的客户端行为,转换成可供攻击者利用的情报。虽然对于渗透测试而言,定制化Payload往往能造成更深层的影响,但JS-Tap在红队行动中“广撒网、盲打击”的场景下,无疑是一个不可或缺的强大工具。

对JS-Tap感兴趣?你可以在其GitHub仓库找到完整的代码库:https://github.com/hoodoer/JS-Tap。如果你有任何问题或改进建议,也欢迎与作者 @hoodoer 直接交流。




上一篇:Claude Fable 5 上线仅三天因出口管制全球下架,Anthropic 安全营销惨遭反噬
下一篇:面试官问“智能客服如何设计”?对话系统架构设计与面试实战指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-6-14 03:40 , Processed in 0.598753 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表