I know this is really, really late in the game, but yes, there is a specific vulnerability that pertains directly to deserialisation of untrusted data. It works in the same way that so-called "PHP Object Injection" attacks do - by abusing classes that perform actions in their finalisation and disposal stages.
Consider the following class:
[Serializable]
class TempFile : IDisposable
{
private readonly string _fileName;
public TempFile()
{
_fileName = Path.GetTempFileName();
}
~TempFile()
{
Dispose();
}
public FileStream GetStream()
{
return new FileStream(_fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
}
public void Dispose()
{
try
{
if (File.Exists(_fileName))
File.Delete(_fileName);
} catch {}
}
}
Now, imagine there's a really boring serialisable class called Message
that just contains some strings. Nothing really interesting at all. You're using this class to pass messages around over the network, like so:
public void ProcessNetworkMessage(byte[] message)
{
var bf = new BinaryFormatter();
Message msg = null;
try
{
using (var ms = new MemoryStream(message))
{
msg = (Message) bf.Deserialise(ms);
}
}
catch (Exception ex)
{
AppLog.WriteLine("Exception: " + ex.Message);
}
if (msg != null)
{
ProcessMessage(msg);
}
}
Seems innocuous, no? But what happens if an attacker passes a binary serialised version of a TempFile
object over the network, rather than the expected Message
object?
Four things happen:
- The data is deserialised into an object instance by the BinaryFormatter.
- The returned object is unsuccessfully cast to a Message object, throwing a cast exception.
- The method exits without using the returned object, leaving the internal representation with zero references in the GC tree.
- The garbage collector disposes of the object.
Why is this exploitable? Well, when the finalisation logic is called by the GC, the destructor calls TempFile.Dispose()
and deletes the file specified by the _fileName
field. Since that field's value is set within the binary serialised blob, the attacker can control it. Put it all together and you've got an arbitrary file deletion bug.
This seems a bit of a stretch, but often you'll find SQL queries and all sorts of other goodies in Dispose()
or destructors of serialisable classes.
Edit: I did a quick search of the reference source, and it turns out that System.CodeDo
m.Compiler.TempFileCollection
contains exactly the issue I showed above - you can fill it with a list of files and upon destruction it deletes them all.