So che questo è davvero, molto tardi nel gioco, ma sì , esiste una vulnerabilità specifica che riguarda direttamente la deserializzazione dei dati non attendibili. Funziona allo stesso modo dei cosiddetti attacchi "PHP Object Injection" - abusando di classi che eseguono azioni nelle fasi di finalizzazione e smaltimento.
Considera la seguente classe:
[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 {}
}
}
Ora, immagina ci sia una classe serializzabile davvero noiosa chiamata Message
che contiene solo alcune stringhe. Niente di veramente interessante. Stai utilizzando questa classe per trasmettere messaggi sulla rete, in questo modo:
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);
}
}
Sembra innocuo, no? Ma cosa succede se un utente malintenzionato passa una versione serializzata binaria di un oggetto TempFile
sulla rete, anziché l'oggetto Message
previsto?
Quattro cose accadono:
- I dati vengono deserializzati in un'istanza dell'oggetto da BinaryFormatter.
- L'oggetto restituito viene lanciato senza successo su un oggetto Message, generando un'eccezione cast.
- Il metodo termina senza utilizzare l'oggetto restituito, lasciando la rappresentazione interna con zero riferimenti nell'albero del GC.
- Il garbage collector dispone dell'oggetto.
Perché è sfruttabile? Bene, quando la logica di finalizzazione viene chiamata dal GC, il distruttore chiama TempFile.Dispose()
ed elimina il file specificato dal campo _fileName
. Poiché il valore di quel campo è impostato all'interno del blob serializzato binario, l'utente malintenzionato può controllarlo. Metti tutto insieme e hai un bug di eliminazione file arbitrario.
Questo sembra un po 'eccessivo, ma spesso troverai query SQL e tutti i tipi di altri extra in Dispose()
o distruttori di classi serializzabili.
Modifica: ho fatto una rapida ricerca dell'origine di riferimento e ho scoperto che System.CodeDo
m.Compiler.TempFileCollection
contiene esattamente il problema che ho mostrato sopra: puoi riempirlo con un elenco di file e dopo la distruzione li cancella tutti.