In Part 1, we explored the basics of insecure deserialization in .NET, demonstrated an example using Newtonsoft.Json TypeNameHandling feature in a vulnerable ASP.NET testing lab, and ysoserial tool which is used such attacks. You can see Part 1.

In this part, we focus on something every security researcher or .NET developer must recognize:

Dangerous serializers.
Safer serializers.

Some .NET formatters allow type metadata to be reconstructed during deserialization, which can enable attackers to trigger gadget chains leading to Remote Code Execution (RCE).

Understanding which serializers are dangerous is essential for both offensive security testing and defensive development.


An example of what ObjectDataProvider Gadget does:

1
2
3
ObjectDataProvider provider = new ObjectDataProvider();
provider.MethodName = "Start";
provider.ObjectInstance = new Process();

During the deserialization provider.Invoke() which will execute Process.start(), the attacker can set the payload as cmd /c whoami this will result an RCE.

Which gadgets exist in loaded assemblies?

  • HTTP body
  • cookie
  • viewstate
  • file upload
1
2
3
4
SerializedObject
├─ AssemblyName
├─ TypeName
├─ FieldValues

Dangerous .NET Deserializers

Several legacy .NET serializers are considered unsafe by design when used with untrusted input.

Formatter Format Notes
BinaryFormatter Binary Allows arbitrary object graph reconstruction
LosFormatter SOAP XML Frequently abused in ASP.NET ViewState attacks
ObjectStateFormatter ASP.NET ViewState binary format Used internally by ASP.NET for ViewState;
Vulnerable when ViewState MAC is disabled or bypassed
NetDataContractSerializer ASP.NET ViewState format Includes full type information
SoapFormatter XML with type metadata Deprecated and insecure

These serializers allow attackers to control types being instantiated, which makes them ideal targets for gadget-based exploitation.

ysoserial.net tool generates payloads that exploit such as these formatters.


Why They Are Dangerous

The core problem is type metadata handling.

Many vulnerable serializers allow payloads containing something like:

1
$type: System.SomeDangerousClass

During deserialization, the runtime may:

  1. Instantiate attacker-controlled types
  2. Trigger constructors
  3. Execute property setters
  4. Invoke dangerous gadget chains

This process can ultimately lead to:

  • Remote Code Execution
  • File operations
  • Process spawning
  • Network calls

Security Model

System.Text.Json was designed with secure defaults:

  • No automatic polymorphic type loading
  • No $type metadata support by default
  • Stronger restrictions around type resolution

Because of this, System.Text.Json is significantly safer against deserialization attacks out of the box.

Safer Serialization Options

Serializer Security Comparison

Modern .NET applications should prefer safe serializers that do not allow arbitrary type reconstruction.

Serializer Safety Notes
System.Text.Json 🟢 Safe No polymorphic type loading by default
Newtonsoft.Json 🟡 Generally Safe Unsafe if TypeNameHandling is enabled

Secure Configuration (Remediation)

When using Newtonsoft.Json, apply the following security practices:

① Disable Type Name Handling

Ensure that type metadata is not processed, This prevent attackers from injecting arbitrary .NET types.

1
TypeNameHandling = TypeNameHandling.None

② Use a Strict Serialization Binder

Implement a whitelist of allowed types, This will prevent attackers from injecting arbitrary .NET classes during deserialization.

1
SerializationBinder = new KnownTypesBinder()

BinaryFormatter

-> This category of attack cannot be mitigated with a SerializationBinder or any other BinaryFormatter configuration switch.
-> When application does something like BinaryFormatter.Deserialize(stream);
It reconstructs objects.
If attacker controls that stream:

  • They control which object is reconstructed
  • They may choose a gadget chain class
  • That class may lead to a sink

That’s how .NET deserialization RCE happens.

Why is BinaryFormatter dangerous?

  • Because it allows full type deserialization and if attacker controls the input, they can instantiate arbitrary classes available in the application domain, which may trigger dangerous methods during object reconstruction.

BinaryFormatter is obsolete and insecure in modern .NET. Microsoft recommends alternatives like:

  • System.Text.Json
  • XmlSerializer
  • DataContractSerializer
Namespace System.Runtime.Serialization.Formatters.Binary

Usage:

1
2
BinaryFormatter formatter = new BinaryFormatter();
object obj = formatter.Deserialize(stream);

What BinaryFormatter Does:

  1. Reads type metadata from serialized data
  2. Instantiates any class available in the application
  3. Executes special methods automatically

Example:

1
2
Serialized data → contains type info → .NET loads that class 
constructor / callbacks execute

Example attack flow

1
2
3
4
5
6
7
8
9
Attacker sends malicious serialized payload

BinaryFormatter.Deserialize()

.NET creates dangerous object

Gadget executes Process.Start()

Remote Code Execution

Example vulnerable code:

1
2
3
4
5
public IActionResult Upload(IFormFile file)
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Deserialize(file.OpenReadStream());
}

If attacker uploads serialized payloadRCE.

→Never use BinaryFormatter with untrusted data.

SoapFormatter

LosFormatter

NetDataContractSerializer

Test our vulnerable app with YSoSerial.net

Example payload generation:

1
ysoserial.net -f BinaryFormatter -g TypeConfuseDelegate -c "calc.exe"
1
2
3
4
5
6
7
```




Why TypeConfuseDelegate and other gadgets fail

ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -o base64 -c ‘calc.exe’


was designed for .NET framework (4.x)
Not .NET core / .NET 5+
version above 5 will not work
Many internal gadgets are gone and changed
.NET core removed and rewrote a lot of gangerous internals 
delegetes, serialization behavior, and reflection paths differ
most ysoserial gadgets rely on ... : ... which they dont exist in .NET Core / .NET >= 5.0
- System.Windows.Data.ObjectDataProvider
- System.Configuration.Install
- System.Web
Modern runtime/.NET Core: removed many dangerous serialization paths, and blocks common gadgets chains
-> no execution chain = no RCE