Deserializace
- Serializace = proces převedení objektu do datového formátu (např. aby bylo možné objekt uložit do úložiště; javascript objekt do XML)
- Deserializace = obrácený proces serializace
- Mnoho jazyků nabízí nativní možnost serializace včetně přizpůsobení tohoto procesu
- Při práci s nedůvěryhodnými daty mohou být tyto mechanismy zneužity
- Útoky na deserializátory způsobují DoS, remote code execution nebo řízení přístupu
Bezpečná deserializace
PHP
- Zkontrolujte použití funkce
[unserialize()](https://www.php.net/manual/en/function.unserialize.php) - Zkontrolujte, jak jsou přijímány externí parametry
- Použijte bezpečný formát pro výměnu dat (JSON -
json_decode(),json_encode()) v případě předávání serializovaných dat uživateli
Python
- Pokud data obsahují na konci tečku
.je pravděpodobné, že byla odeslána v serializaci - Následující kód je zranitelný (serialization attack)
import pickle
data = """ cos.system(S'dir')tR. """
pickle.loads(data)
import yaml
document = "!!python/object/apply:os.system ['ipconfig']"
print(yaml.load(document))
Java
- Přepište
ObjectInputStream#resolveClass()metodu, abyste zabránili deserializaci libovolných tříd (knihovna SerialKiller) - Použijte bezpečnou náhradu
readObject()metody - Dávejte pozor na použití
XMLdecoders parametry definovanými uživatelemXStreammetodyfromXML(verzev1.4.6je zranitelná vůči serializaci)ObjectInputStreamreadObjectareadUnsharedreadObject,readObjectNodData,readResolve,readExternalSerializable
- Pokud data obsahují tyto vzorce, může to znamenat, že byla odeslána v Java serialization streamu
- Hex
AC ED 00 05 - Base64
eO0 Content-typehlavička odpovědi nastavená naapplication/x-java-serialized-object
- Hex
Zabraňte úniku dat
- Deklarujte datové objekty jako
transient, pokud by je koncoví uživatelé neměli kontrolovat během deserializace nebo vystavovat při serializaci - Deklarujte proměnnou s citlivými informacemi jako
private transientu třídySerializable
public class myAccount implements Serializable
{
private transient double profit; // Declared transient
private transient double margin; // Declared transient
....
Zabraňte deserializaci doménových objektů
- Některé objekty mohou implementovat
Serializablekvůli své hirarchii
- Deklarujte
readObjectmetodu, čímž zaručíte, že objekty nemohou být deserializovány
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Zpřísněte java.io.ObjectInputStream
- Přepište
ObjectInputStream.html#resolveClass(), čímž se omezí třídy, které se smějí deserializovat - K volání dochází před
readObject()→ můžete si být jisti, že nedojde k žádné deserializační aktivitě
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Zpřísněte použití java.io.ObjectInputStream
- Použijte agenta, pokud třídu nelze přetížit
- Agenta můžete v JVM povolit takto:
-javaagent:name-of-agent.jar[rO0od Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
- Podobně můžete ručně opravit a spustit
ObjectInputStreamv JVM (méně škálovatelné)
.Net C#
- Vyhledejte v kódu
TypeNameHandling,JavaScriptTypeResolver - Vyhledejte všechny serializery, kde je typ nastaven uživatelem
- Vyhledejte obsah v base64:
AAEAAAD///// - Vyhledejte obsah s textem
TypeObject,$type: - Nepoužívejte
BinaryFormattertyp, protože není možné zabezpečení - Nedovolte data streamu definovat typ objektu, na který bude deserializován
- Použijte
DataContractSerializerneboXmlSerialier, pokud je to možné
- Použijte
- Nastavte
TypeNameHandlingnaNonetam, kde se používáJSON.NetTypeNameHandling = TypeNameHandling.None
- Nepoužívejte
JavaScriptTypeResolversJavaScriptSerializer - Omezte typy, které je potřeba deserializovat, pokud musíte deserializovat datové streamy, které definují svůj vlastní typ
- Stále je to riskantní
- Mnoho nativních typů je potenciálně nebezpečných (např.
System.IO.FileInfo)
- Objekty
FileInfo, mohou při deserializaci změnit vlastnosti souborů, což může vést k DoS
- Nezapomeňte, že některé typy mají rizikové vlastnosti
- Např.
System.ComponentModel.DataAnnotations.ValidationExceptionpropertyValue(Object) - Útočník může nastavit hodnotu na libovolný typ objektu
- Např.
- Zabraňte útočníkům v řízení typu, který bude instancován (pak lze podvrhnout i
DataContractSerializerneboXmlSerializer)
// Action below is dangerous if the attacker can change the data in the database
var typename = GetTransactionTypeFromDatabase();
var serializer = new DataContractJsonSerializer(Type.GetType(typename));
var obj = serializer.ReadObject(ms);
- Vytvoření ovládacího prvku níže je neúčinné
var suspectObject = myBinaryFormatter.Deserialize(untrustedData);
// Check below is too late! Execution may have already occurred.
if (suspectObject is SomeDangerousObjectType)
{
// Generate warnings and dispose of suspectObject
}
- Vytvořte bezpečnější formu kontroly (allow-list) pomocí vlastního
SerializationBinderproJSON.Net - Sledujte aktuální informace o známých a nebezpečných deserializačních gadgetech
- Oddělte kód, který vytváří gadgety od kódu, který má připojení k internetu
- Např.
System.Windows.Data.ObjectDataProviderje riskantní použít v REST projektu, který deserializuje nedůvěryhodná data
- Např.
Známé gadgety
System.Configuration.Install.AssemblyInstallerSystem.Activities.Presentation.WorkflowDesignerSystem.Windows.ResourceDictionarySystem.Windows.Data.ObjectDataProviderSystem.Windows.Forms.BindingSourceMicrosoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProviderSystem.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocumentSystem.Management.Automation.PSObject
Metody pro bezpečnou serializaci
Použijte alternativní datové formáty
- Vyhněte se nativním (de)serializačním formátům
- Přejděte na čistý datový formát (JSON, XML)
Deserializujte pouze podepsaná data
- Pokud aplikace před deserializací ví, které zprávy bude zpracovávat, může je podepsat v rámci serializace
- Aplikace pak může deserializovat pouze zprávy s ověřeným podpisem