Hydra: 可変インスタンス化ポリシーセットにより、ターゲットブロックリストを回避できる
## 概要
Hydraの従来の`instantiate()`ターゲットブロックリストおよび関連する実行ポリシー
コレクションは、変更可能なモジュールレベルの状態に保存されています。 `_locate()`が
インポートされたオブジェクトの属性を解決できるため、設定ファイルが`.discard()`
のような変更メソッドを呼び出し、アクティブなポリシーを変更し、それによって
通常はブロックされるターゲットをインスタンス化することができます。
## 影響
複数の関連する`_target_`エントリを制御する設定ファイルは、まずターゲット
ブロックリストからエントリを削除し、その後、削除されたターゲットを呼び出す
可能性があります。 関連するノードは挿入順序で処理され、同じ変更可能な
モジュールレベルのポリシーを参照します。
これは、実行ホワイトリストのない従来の/デフォルトのパスに影響を与えます。
1.3のブロックリストは、完全なセキュリティ境界ではなく、多層防御の手段です。
アプリケーションは、信頼できない設定ファイルを安全にインスタンス化したり、
Pythonのロギング設定に使用したりしてはなりません。
`hydra-core`のバージョン1.3.4から1.3.6、および1.4.0.dev4から1.4.0.dev9
が影響を受けます。 修正されたバージョンは1.3.7と1.4.0.dev10です。
報告された直接的な変更パスは、意図されたアプリケーションのターゲットに
限定され、信頼できるPythonコードによって提供される実行ホワイトリストを
回避しません。 修正の過程で、Hydraは、名前のみによる認証を損なう可能性
のある、一般的な検出、ディスパッチ、イントロスペクション、エイリアス、
呼び出し可能結果、および遅延呼び出しパスを強化しました。
## 技術的な詳細
`hydra-core`のバージョン1.3.4および1.3.5では、変更可能なブロックリストは
以下のパスでアクセス可能です。
`hydra._internal.instantiate._instantiate2.DEFAULT_BLOCKLISTED_MODULES`
`hydra-core`のバージョン1.3.6では、拡張されたポリシーには、変更可能な
コレクションが含まれています。
`hydra._internal.target_policy`
例:
`hydra._internal.target_policy.UNCONTROLLED_EXECUTION_TARGETS.discard`
これは、`set.discard`メソッドに解決されます。レガシーのパスでは、変更対象自体がブロックされません。一度エントリが削除されると、その後の認証チェックでは、変更されたセットが参照されます。
他のランタイムポリシーコレクションも、許可されていないエントリを削除したり、例外セットにエントリを追加したりすることで、同様に攻撃される可能性があります。これらのコレクションはモジュールレベルの状態であるため、変更が成功すると、明示的に元に戻さない限り、Pythonプロセスの存続期間中、その状態は維持されます。
## 安全な再現
`hydra-core` 1.3.6におけるこの動作は、シェルコマンドを実行しなくても再現できます。`finally`ブロックは、変更されたプロセス全体のの状態を復元します。
```python
from omegaconf import OmegaConf
from hydra._internal.target_policy import UNCONTROLLED_EXECUTION_TARGETS
from hydra.utils import instantiate
target = "builtins.eval"
assert target in UNCONTROLLED_EXECUTION_TARGETS
try:
result = instantiate(
OmegaConf.create(
{
"disarm": {
"_target_": (
"hydra._internal.target_policy."
"UNCONTROLLED_EXECUTION_TARGETS.discard"
),
"_args_": [target],
},
"proof": {
"_target_": target,
"_args_": ["40 + 2"],
},
}
)
)
assert result["proof"] == 42
assert target not in UNCONTROLLED_EXECUTION_TARGETS
finally:
UNCONTROLLED_EXECUTION_TARGETS.add(target)
```
## 修正
この修正により、ランタイムポリシーの状態が不変になり、整合性がチェックされるようになります。また、宣言的な設定がHydraの内部や保護されたPythonの実装状態にアクセスしたり、変更したりすることを防ぎます。ターゲットの認証は、標準的な解決された識別子、エイリアス、検出結果、呼び出し可能なオブジェクトの結果、遅延呼び出し可能なオブジェクト、およびランタイム引数などをカバーするようになりました。
この修正は、設定ファイルに依存するコード、ポリシー、プロセス、および環境の変更を拒否します。また、保護された実行時の機能を公開する可能性のある、安全でない内部調査やフォーマットの解析も防ぎます。
Hydra 1.3.7では、これらの保護を多層防御として採用しています。ただし、信頼できない設定ファイルをサンドボックス化するわけではありません。Hydra 1.4では、宣言的なインスタンス化と、Hydraが制御するPythonのログ設定のための、信頼できる、範囲を限定した実行許可リストを、セキュリティ境界として使用しています。
ユーザーは、安定版では`hydra-core` 1.3.7、開発版では1.4.0.dev10にアップグレードしてください。
## 対策
信頼できないソースから、`instantiate()`関数やHydraが制御するPythonのログ設定に設定ファイルを渡さないでください。1.3のリリース版には、実行許可リストの機能がありません。そのため、すぐにアップグレードできないユーザーは、設定ファイルの入力を信頼できるソースに限定する必要があります。
影響を受ける1.4の開発版では、アプリケーションから、Pythonコードで信頼できる、範囲を限定した実行許可リストを提供することもできます。ただし、許可リスト自体は、信頼できない設定ファイルから派生してはなりません。
すでに信頼できない設定ファイルを読み込んでいる可能性のある、長時間のプロセスを再起動してください。これは、ポリシーの変更がプロセス全体の状態で保持されるためです。
影響を受けるパッケージ:
- pip (Python) hydra-core: 影響を受けるバージョンは1.3.4以上、1.3.7未満。1.3.7で修正済み。
- pip (Python) hydra-core: 影響を受けるバージョンは1.4.0.dev4以上、1.4.0.dev10未満。1.4.0.dev10で修正済み。