
PyYAMLにおけるCVE-2020-14343の制御された脆弱性研究および再現ラボ
このプロジェクトは、制御された隔離された Docker 環境で CVE-2020-14343 を実演します。
このラボには 2 つの環境が含まれています:
yaml.safe_load() を使用した修正済み環境このラボでは、脆弱性のライフサイクル全体を実演します:
このラボで使用される再現ペイロードは意図的に無害であり、テストマーカーを出力するだけです。
| プロパティ | 詳細 |
|---|
| CVE | CVE-2020-14343 |
| 製品 | PyYAML |
| 影響を受けるバージョン | 5.4 より前のバージョン |
| 修正済みバージョン | 5.4 |
| 脆弱性の種類 | 不適切な入力検証 (CWE-20) |
| 深刻度 | 重大 |
| 攻撃対象領域 | 脆弱な読み込み機能を使用して処理される YAML 入力 |
この脆弱性は、信頼できない YAML 入力が脆弱な PyYAML 読み込み機能を使用して処理される場合に発生します。
5.4 より前の PyYAML バージョンでは、以下のような Python 固有のタグを含む、特別に細工された YAML タグが許可されていました:
!!python/object/new
FullLoader が使用された場合、オブジェクト構築機能に到達する可能性がありました。
したがって、悪意のある YAML ドキュメントは意図しない Python コード実行を引き起こす可能性があります。
この問題は、以前の PyYAML 脆弱性に対する不完全な修正に関連していました。
PyYAML 5.4 は、任意の Python タグを UnsafeLoader に移動することで CVE-2020-14343 を修正しました。
信頼できない YAML を処理するアプリケーション向けに、このラボでは安全な読み込みアプローチとして yaml.safe_load() も使用しています。
このラボには 2 つの隔離された Docker サービスが含まれています:
Host Machine
|
+------------+------------+
| |
v v
Vulnerable App Patched App
localhost:5000 localhost:5001
| |
PyYAML 5.3.1 PyYAML 5.4
FullLoader SafeLoader
| |
v v
Payload executes Payload rejected
| サービス | ホストポート | コンテナポート | PyYAML | 目的 |
|---|---|---|---|---|
| vulnerable | 5000 | 5000 | 5.3.1 | 脆弱な環境 |
| patched | 5001 | 5000 | 5.4 | 修正済み環境 |
cve-2020-14343-lab/
│
├── vulnerable/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── patched/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── exploit/
│ └── reproduce.py
│
├── detection/
│ └── detect.py
│
├── docker-compose.yml
└── README.md
| ファイル/ディレクトリ | 目的 |
|---|---|
vulnerable/app.py | 脆弱な YAML 読み込みを使用する Flask アプリケーション |
vulnerable/Dockerfile | 脆弱な Docker イメージをビルドします |
vulnerable/requirements.txt | PyYAML を 5.3.1 に固定します |
patched/app.py | 安全な YAML 読み込みを使用する Flask アプリケーション |
patched/Dockerfile | 修正済み Docker イメージをビルドします |
patched/requirements.txt | PyYAML を 5.4 に固定します |
exploit/reproduce.py | 制御されたペイロードを使用して脆弱性を再現します |
detection/detect.py | Docker コンテナ内の PyYAML バージョンを確認します |
docker-compose.yml | 両方の環境をビルドして実行します |
以下のソフトウェアが必要です:
ラボを開始する前に Docker Desktop が実行されている必要があります。
脆弱なアプリケーションは、Docker ポートマッピングを通じてローカルマシン上でのみ意図的に公開されています。
プロジェクトのルートディレクトリから、以下を実行します:
docker compose up --build -d
以下を実行します:
docker compose ps
両方のサービスが Up と表示されるはずです。
以下を開きます:
http://127.0.0.1:5000
期待される応答:
{
"message": "CVE-2020-14343 vulnerable YAML parser"
}
以下を開きます:
http://127.0.0.1:5001
期待される応答:
{
"message": "CVE-2020-14343 patched YAML parser"
}
docker compose up -d
docker compose down
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
脆弱なアプリケーションは、YAML 入力を受け付ける /parse エンドポイントを公開しています。
脆弱な環境では以下を使用しています:
yaml.FullLoader再現スクリプトは以下にあります:
exploit/reproduce.py
脆弱なアプリケーションは以下で利用可能です:
http://127.0.0.1:5000/parse
以下を実行します:
python exploit/reproduce.py
このスクリプトは、Python 固有の YAML タグを含む制御された YAML ペイロードを送信します。
脆弱な環境では、ペイロードが受け入れられ、アプリケーションは HTTP 200 応答を返します。
制御されたテストマーカー:
CVE-2020-14343-TEST
が脆弱なアプリケーションコンテナ内で実行されます。
実行は以下を使用して確認できます:
docker logs cve-vulnerable
期待されるログ出力には以下が含まれます:
CVE-2020-14343-TEST
これは、脆弱な YAML 読み込み動作を通じたコード実行を実証しています。
再現ペイロードは意図的に無害です。テストマーカーを出力するだけで、ホストシステムの変更、認証情報へのアクセス、機密データへのアクセス、外部システムとの対話、破壊的な操作は行いません。
検出スクリプトは以下にあります:
detection/detect.py
このスクリプトは、指定された Docker コンテナ内にインストールされている PyYAML バージョンを確認します。
修正済みバージョンは以下です:
5.4
以下を実行します:
python detection/detect.py cve-vulnerable
期待される結果:
PyYAML installed version: 5.3.1
Fixed version: 5.4
STATUS: VULNERABLE
Reason: PyYAML version is older than 5.4.
以下を実行します:
python detection/detect.py cve-patched
期待される結果:
PyYAML installed version: 5.4
Fixed version: 5.4
STATUS: PATCHED
Reason: PyYAML version is 5.4 or newer.
Docker Container
|
v
docker exec
|
v
Import PyYAML
|
v
Read yaml.__version__
|
v
Compare with 5.4
|
+----------------------+
| |
< 5.4 >= 5.4
| |
v v
VULNERABLE PATCHED
このスクリプトは、対象コンテナからインストールされている PyYAML バージョンを照会します。
脆弱な環境では以下を使用しています:
PyYAML==5.3.1
修正済み環境では以下を使用しています:
PyYAML==5.4
修正済みアプリケーションでは、以下も使用しています:
yaml.safe_load(yaml_input)
以下ではなく:
yaml.load(yaml_input, Loader=yaml.FullLoader)
yaml.safe_load() を使用します。同じエクスプロイトペイロードを修正済みアプリケーションに対してテストします。
修正済みアプリケーションは以下で実行されています:
http://127.0.0.1:5001/parse
以下を実行します:
python exploit/reproduce.py http://127.0.0.1:5001/parse
このラボで観察された結果:
HTTP Status: 400
Server Response:
{"message":"could not determine a constructor for the tag 'tag:yaml.org,2002:python/object/new:tuple' ...","status":"error"}
Python 固有の YAML タグは修正済みアプリケーションによって拒否されます。
制御されたテストマーカーは修正済みアプリケーションでは実行されません。
| テスト | 脆弱な環境 | 修正済み環境 |
|---|---|---|
| PyYAML バージョン | 5.3.1 | 5.4 |
| 検出 | VULNERABLE | PATCHED |
| エクスプロイト要求 | HTTP 200 | HTTP 400 |
| Python 固有の YAML タグ | 受け入れられる | 拒否される |
| テストマーカーの実行 | コンテナログで観察される | 実行されない |
Docker Desktop が実行されていることを確認し、以下を検証します:
docker version
以下を確認します:
docker ps -a
必要に応じて古いコンテナを削除します:
docker rm cve-vulnerable cve-patched
次に:
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
docker compose up --build -d
クリーンな再ビルドの場合:
docker compose build --no-cache
docker compose up -d
このプロジェクトは制御された概念実証ラボであり、本番環境のデプロイを表すものではありません。
制限事項には以下が含まれます:
プロジェクト提出のために以下の証拠を取得する必要があります:
STATUS: VULNERABLE を示す脆弱なバージョンの検出。CVE-2020-14343-TEST マーカー。STATUS: PATCHED を示す修正済みバージョンの検出。スクリーンショットは以下に保存できます:
screenshots/
このリポジトリ内のすべての再現コードとドキュメントは、このラボのために特別に開発されました。
このラボでは、特定から修正までの CVE-2020-14343 を実演します。
脆弱な環境では PyYAML 5.3.1 を使用し、細工された YAML ペイロードを通じた制御されたコード実行を実演します。
検出スクリプトは脆弱な依存関係バージョンを特定します。
修正済み環境では PyYAML を 5.4 にアップグレードし、信頼できない YAML を処理するために yaml.safe_load() を使用します。
同じ再現ペイロードは修正済みアプリケーションによって拒否され、修正の前後の証拠を提供します。
環境全体は Docker Compose を使用して再現できます。