On our API we need to take in json, deserialize it to an interface, set a field, and ship it off. To achieve this, on both ends I'm setting the jsonConvert to use TypeNameHandling.All. The endpoint in question is supposed to be fairly locked down, but there's always a chance of someone gaining access and setting $type to a system class with a dangerous constructor or garbage collection method.
My question is would clarifying the namespace of the type before attempting to deserialize it be sufficiently safe? or would there still be a risk of having something like a sub-object with a dangerous class type in the json? If there is still a risk or an exploit I've missed, what other steps can I do to mitigate the danger?
Our company name is at the start of every namespace we use, so in the code below we just check that the type set in the json starts with our company name. The {} at the start is just so the compiler knows it doesn't need to keep the JObject in memory after the check.
{ //check the type is valid
var securityType = JsonConvert.DeserializeObject<JObject>(request.requestJson);
JToken type;
if (securityType.TryGetValue("$type", out type))
{
if (!type.ToString().ToLower().StartsWith("foo")) { //'foo' is our company name, all our namespaces start with foo
await logError($"Possible security violation, client tried to instantiate {type}", clientId: ClientId);
throw new Exception($"Request type {type} not supported, please use an IFoo");
}
}
else
{
throw new Exception("set a type...");
}
}
IFoo requestObject = JsonConvert.DeserializeObject<IFoo>(request.requestJson, new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
});