Přeskočit na hlavní obsah

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

  1. Zkontrolujte použití funkce [unserialize()](https://www.php.net/manual/en/function.unserialize.php)
  2. Zkontrolujte, jak jsou přijímány externí parametry
  3. 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

  1. Přepište ObjectInputStream#resolveClass() metodu, abyste zabránili deserializaci libovolných tříd (knihovna SerialKiller)
  2. Použijte bezpečnou náhradu readObject() metody
  3. Dávejte pozor na použití
    • XMLdecoder s parametry definovanými uživatelem
    • XStream metody fromXML (verze v1.4.6 je zranitelná vůči serializaci)
    • ObjectInputStream readObject a readUnshared
    • readObject, readObjectNodData, readResolve, readExternal
    • Serializable
  • 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-type hlavička odpovědi nastavená na application/x-java-serialized-object

Zabraňte úniku dat

  1. Deklarujte datové objekty jako transient, pokud by je koncoví uživatelé neměli kontrolovat během deserializace nebo vystavovat při serializaci
  2. Deklarujte proměnnou s citlivými informacemi jako private transient u třídy Serializable
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 Serializable kvůli své hirarchii
  1. Deklarujte readObject metodu, čí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

  1. Přepište ObjectInputStream.html#resolveClass(), čímž se omezí třídy, které se smějí deserializovat
  2. 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

  1. Použijte agenta, pokud třídu nelze přetížit

.Net C#

  1. Vyhledejte v kódu TypeNameHandling, JavaScriptTypeResolver
  2. Vyhledejte všechny serializery, kde je typ nastaven uživatelem
  3. Vyhledejte obsah v base64: AAEAAAD/////
  4. Vyhledejte obsah s textem TypeObject, $type:
  5. Nepoužívejte BinaryFormatter typ, protože není možné zabezpečení
  6. Nedovolte data streamu definovat typ objektu, na který bude deserializován
    1. Použijte DataContractSerializer nebo XmlSerialier, pokud je to možné
  7. Nastavte TypeNameHandling na None tam, kde se používá JSON.Net
    • TypeNameHandling = TypeNameHandling.None
  8. Nepoužívejte JavaScriptTypeResolver s JavaScriptSerializer
  9. 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
  1. Nezapomeňte, že některé typy mají rizikové vlastnosti
    • Např. System.ComponentModel.DataAnnotations.ValidationException property Value (Object)
    • Útočník může nastavit hodnotu na libovolný typ objektu
  2. Zabraňte útočníkům v řízení typu, který bude instancován (pak lze podvrhnout i DataContractSerializer nebo XmlSerializer)
// 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
}
  1. Vytvořte bezpečnější formu kontroly (allow-list) pomocí vlastního SerializationBinder pro JSON.Net
  2. Sledujte aktuální informace o známých a nebezpečných deserializačních gadgetech
  3. Oddělte kód, který vytváří gadgety od kódu, který má připojení k internetu
    • Např. System.Windows.Data.ObjectDataProvider je riskantní použít v REST projektu, který deserializuje nedůvěryhodná data

Známé gadgety

  • System.Configuration.Install.AssemblyInstaller
  • System.Activities.Presentation.WorkflowDesigner
  • System.Windows.ResourceDictionary
  • System.Windows.Data.ObjectDataProvider
  • System.Windows.Forms.BindingSource
  • Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider
  • System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument
  • System.Management.Automation.PSObject

Metody pro bezpečnou serializaci

Použijte alternativní datové formáty

  1. Vyhněte se nativním (de)serializačním formátům
  2. 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

Kam dál