STOP Insecure Deserialization with C#
… and Newtonsoft.Json, one of the most common libraries used by C# developers.
Serialization and Deserialization are usual operations in many applications, mostly in web apps that receive data from the world and need to understand users requests.
Serialization is the process of translating data structures or object state into a format that can be stored.
or
Serialization is the process of saving an object’s state as a sequence of bytes.
As far as I know, it is difficult to explore an exploit of serialization and be in control of a system. Otherwise, explore vulnerabilities of deserialization can be an easy business if you use the wrong configurations and tools.
Deserialization is the process of restore the serialized data.
Newtonsoft.Json vulnerability
Newtonsoft.Json uses reflection to construct objects and deserialize a JSON document to a memory object. Reflection processes are able to examine, introspect, and modify its own structure at runtime. Newtonsoft.Json takes advantage of the default parameter-less constructor to create a new object and populate the fields and properties.
As you might know, developers usually avoid repeated code. Instead, we follow patterns and conventions and try to create helpers to be used in cross-application, as you can see below.
In fact, it seems all right, right?…
No! 😕
So, where is the problem??? The problem is the TypeNameHandling.All
configuration. It will deserialize objects where the $type
attribute of the JSON source document will indicate the data type. What do you think that will happen when you deserialize an System.Diagnostics.Process
? 🤓
Of course this is a particular situation, but believe me, it is possible to steal sensible information with a small security issue. And you know it 😉.
How to mitigate the problem
RULE: You must always use specific types! Do not use generic types such as object
or dynamic
. NEVER EVER!!
Additionally, change the TypeNameHandling
configuration to TypeNameHandling.None
. Therefore, Newtonsoft.Json will not use the JSON source document to indicate the object type. Instead, it will use the type obtained from the DeserializeObject
method (DeserializeObject<T>
).
Thus, an System.Diagnostics.Process
object can’t be casted to a generic T
type, such as UserModel
, SubmitResponse
, ContactModel
, and so on, and so on…
❗ IMPORTANT: Sometimes you can’t deserialize a JSON document without the TypeNameHandling.All
configuration. How to solve it? → Add custom validations to your objects, values, properties, and their types. It is the only way you can trust the external data.
Conclusion
Never ever trust external data!
For your security always validate all the inputs and pay attention to the dynamics types. Trust your work but be careful too, because there is always something that can pass your eyes. I advise you to always read the third-parties documentation that you regularly use and trust; most of them will warn you about known vulnerabilities. And if possible use additional audit software to your source code, the cherry on top of the cake!