Description
We've known for a long while that BinaryFormatter
is a dangerous type and that it's responsible for many of the security vulnerabilities real-world .NET applications have seen in recent years. In .NET Core 1.x, the type was removed from the product entirely, and it was brought back in .NET Core 2.0 under the guise of "app compat".
Though as of the time of this writing there are no known types in .NET Core which can be leveraged by BinaryFormatter
to achieve RCE, it is impractical to make this guarantee going forward. As new types are introduced (or existing types from the full Framework are re-introduced) I have no doubt that one of them will contain such a vector that we weren't able to catch during development due to the complexity of this system.
Some applications use a custom SerializationBinder
to mitigate attacks both on .NET Core and in full Framework. The engineering team's current understanding is that a properly-written SerializationBinder
is sufficient to block RCE attacks. However, this is not a guarantee, and even so, a custom SerializationBinder
cannot mitigate other attacks like DoS within the BinaryFormatter
infrastructure itself.
All of this said, the conclusion is that BinaryFormatter
is not an appropriate serialization format for application developers to be using in a cloud-connected world. It was a mistake for us to bring it back in .NET Core 2.0, as us re-introducing it into the shared framework gives the type an undeserved air of respectability, like we're nodding and implicitly approving its usage by modern applications.
To address this, and to eventually migrate applications off of BinaryFormatter
, I propose the following steps. These steps will only affect customers who target .NET 5 or above for their applications.
Remove
BinaryFormatter
from the shared framework and into its own standalone package that must be manually retrieved and installed into the application.Mark the
BinaryFormatter
type itself with[Obsolete]
, or include in the package a code analyzer which warns on the type's usage. Force developers to explicitly acknowledge that they're calling an extremely dangerous API and that they must be certain the data is coming from a trusted location.Document the
BinaryFormatter
code base as legacy only. Clearly communicate that Microsoft is making no further investments in this code base, and all bug reports or feature requests will be immediately closed.Create a separate "safe" (type-limiting, bounds-checking, etc.) serializer whose payload format is
BinaryFormatter
-compatible and which can be used to deserialize existing payloads in a safe fashion, even if those payloads originate from an untrusted source. The API surface will look different than the traditionalBinaryFormatter.Deserialze
call due to needing to configure the serializer on a per-call basis, but at minimum it gives applications a way to read existing payloads. This allows them to migrate their data without leaving them hanging. This serializer could be in the same package thatBinaryFormatter
is in.
These steps would serve to modernize the runtime and SDK by eliminating a type which has no place in today's development cycle, it serves as a forcing function to get application developers to fix potential vulnerabilities in their code, and it provides on an opt-in basis a way for applications to continue to work if they really must continue using the type going forward.