
CVE-2020-2551 POC(インターネット上で使用)
POCのテスト(外部ネットワークで使用可能)
python CVE-2020-2551.py [HOST] [IP]
codebaseを変更してリモートローディングを試みる(失敗)
python CVE-2020-TEST.py [HOST] [IP]
(初出は安全客、原文リンク)
この脆弱性を学ぶには、CORBAやRMIなどの前提知識が必要です。
簡単にまとめると:
CORBAはOMGが策定した分散アプリケーション向けの技術標準であり、IDLを使用して言語間サポートを実現し、クライアントとサーバー間はIIOPプロトコルで通信します。
RMIはもう一つの分散アプリケーション技術であり、JavaではJNDIを使用して簡単に利用でき、クライアントとサーバーはJRMPプロトコルで通信します。ただし、weblogicではRMIはT3プロトコルを使用しており、これに関しては以前にも多くの脆弱性が報告されています。
RMI-IIOPはRMIとCORBAのそれぞれの利点を組み合わせ、IIOPプロトコルを介してRMIアプリケーションを展開します。
公式ドキュメントにも次のように記載されています:
RMIサーバーオブジェクトはIIOPプロトコルを使用でき、任意の言語で書かれたCORBAクライアントオブジェクトと通信できます。
weblogicのことは一旦おいて、まずRMI-IIOPインスタンスの作成方法に注目します:
クライアントコードは、Java における RMI、JNDI、LDAP、JRMP、JMX、JMS のあれこれ(上)のテストプロジェクトを参照できます。HelloClientとHelloServerを自分でコンパイルしても良いですし、テストプロジェクトでコンパイル済みのものを使用しても構いません。
コマンドラインでネーミングサーバー(Java組み込み)を起動します:
start orbd -ORBInitialPort 1050
コマンドラインでサーバーサイドHelloServerを起動し、リモートデバッグを設定します。IDEAでリモートデバッグを行う方法については、こちらの冒頭で紹介されている方法を参照してください。
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 HelloServer
もちろん、リモートデバッグをせずに結果だけを見ても構いません。直接起動します。
java HelloServer
コマンドラインでクライアントを起動します。
Java HelloClient
この時点で電卓が起動します。リモートデバッグが成功すると、次の呼び出しスタックが表示されます。

EvilMessage.readObejct() でコマンドを実行します。

余談:weblogicのインストールとデバッグに関する記事。
では、weblogic内のRMI-IIOPはどうでしょうか? JavaのRMI-IIOPについてという記事で、weblogic RMI-IIOPの悪用について言及されています。それを基にいくつか調査を行いました。Using WebLogic’s RMI over IIOPでは、weblogicでRMI-IIOPクライアントを使用するいくつかの方法が説明されています。例えば:
最初の2つの方法の違いは、JNDI_FACTORYの設定の違いだけのようです。

以前weblogic T3の逆シリアル化を調査した際、weblogic上にHelloserverアプリケーションをデプロイし、sayhello()メソッドを利用できるようにしました。2種類のJNDI_FACTORYを設定して呼び出してみたところ、2番目のJNDI_FACTORYを使用してsayHello()メソッドの呼び出しに成功しました。
それでは、weblogic T3プロトコルのPOCを修正します。具体的にはRMIをIIOPに変更したところ、jtaTransactionManager利用チェーンが正常に実行され、ローカルのjrmplistenにjrmpリクエストが送信されました。

トラフィックを確認すると、remove()メソッドの呼び出し時にremove__java_lang_Objectリクエストが送信され、トラフィック内に悪意のあるデータが含まれていましたが、acedマジックヘッダーは見つかりませんでした。

サーバー側で特別な解析が行われた後、データが逆シリアル化されると推測されます。呼び出しスタックを見ると、後半部分の実行チェーンは前述のネイティブRMI-IIOPの実行チェーンと非常によく似ています。前半はCDRInputStream.read_value()からトリガーされますが、こちらはweblogicのIIOPInputStream.read_value()からトリガーされます(read_valueという点は、2019年のトピックでも言及されています)。

ここで、リクエストはまずclusterableServerRef.invoke()で処理され、異なるinvokerに応じてthis.invoker.invoke()が呼び出されます。次に、Mejb_dj5nps_HomeImpl_WLSkel.invoke()が呼び出され、"remove"であるため、case 6ブランチに入り、IIOPInputStream.readObject()が呼び出され、read_value()メソッドでIIOPInputStreamデータが解析されて逆シリアル化がトリガーされます。これがremove()メソッドを利用するPOCです。
Lucifaer氏の[分析記事](https://lucifaer.com/2020/02/25/WebLogic WLS核心组件RCE分析(CVE-2020-2551)/?from=timeline&isappinstalled=0#2-2-Weblogic解析流程)では、bind()メソッドを使用した悪用方法が言及されています。これがインターネット上の主流な悪用方法でもあります。呼び出しスタックを追ってみましょう。

前回と同様に、リクエストはまずclusterableServerRef.invoke()で処理され、異なるinvokerに応じてthis.invoker.invoke()が呼び出されます。ここではCobraServerRef.invoke()が呼び出され、その後_NamingContextAnyImplBase._invoke()内で、va1が"bind_any"であるため、case 0ブランチに入り、IIOPInputStream.read_any()メソッドが呼び出されます。その後もIIOPInputStream.read_value()が呼び出されて逆シリアル化がトリガーされます。先ほどトラフィック内でacedマジックヘッダーが見られなかったのは、IIOPInputStream内に解析方式が存在するためです。IIOPInputStreamのhex-value形式は以下の通りで、クラス名とフィールド情報が含まれています。

最終的に悪意のあるクラスのreadObejct()メソッドが呼び出されます。

パッチを確認したところ、2015年のT3逆シリアル化悪用のパッチと同じ場所であることがわかりました。

WebLogic CVE-2020-2551脆弱性分析のテストでは、CVE-2020-2551のフィルタリングクラスの場所もweblogic.iiop.Utilsクラス内にあることが確認されています。

しかし、ローカルテストでは、weblogic10.3.6に2015年のパッチを適用しても、isBlacklisted()関数はトリガーされませんでした(ただし、MsgAbbrevInputStreamとInboundMsgAbbrevの両方でisBlacklisted()が呼び出されてブラックリスト検証が行われているため、奇妙です...)。

今回のCVE-2020-2551のパッチでは、weblogic.iiop.Utils.LoadClass()にフィルタリングのverifyclassermitted()メソッドが追加されました。

ブラックリストは悪意のあるクラスをフィルタリングしており、その中にはJtaTransactionManagerの親クラスであるcom.bea.core.repackaged.springframework.transaction.support.AbstractPlatformTransactionManagerが含まれています。このクラスはweblogicに組み込まれており、非常に危険です。パッチを見ていると、606行目の検証がLoadClass()の後に行われるため、もしclassNameのロード時にクラスがロードされて悪意のある静的コードブロックが実行されれば、防御を回避できるのではないか?という考えが浮かびました。これについては後述します。
JAVAプログラムで書かれたPOCにはネットワーク問題があり、ローカルのweblogicサービスに対しては正常に動作しますが、dockerコンテナや外部ネットワークのマシンに対しては動作しません。この問題を指摘した分析記事:
手把手教你解决Weblogic CVE-2020-2551 POC网络问题
以下、POCのデバッグについて。前述のremoveのものを参考にするか、Y4erのものを参考にしてください。前述の2つの記事では、2つの解決方法が提案されています:
両方を試しました。weblogicを再パッケージ化すると、java.lang.NoSuchMethodError: weblogic.security.subject.SubjectManager.installCESubjectManager というエラーが発生しましたが、解決策は見つかりませんでした。