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í
XMLdecoder
s parametry definovanými uživatelemXStream
metodyfromXML
(verzev1.4.6
je zranitelná vůči serializaci)ObjectInputStream
readObject
areadUnshared
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á 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 transient
u 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
Serializable
kvůli své hirarchii
- 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
- 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
[rO0
od Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
- Podobně můžete ručně opravit a spustit
ObjectInputStream
v 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
BinaryFormatter
typ, protože není možné zabezpečení - Nedovolte data streamu definovat typ objektu, na který bude deserializován
- Použijte
DataContractSerializer
neboXmlSerialier
, pokud je to možné
- Použijte
- Nastavte
TypeNameHandling
naNone
tam, kde se používáJSON.Net
TypeNameHandling = TypeNameHandling.None
- Nepoužívejte
JavaScriptTypeResolver
sJavaScriptSerializer
- 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.ValidationException
propertyValue
(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
DataContractSerializer
neboXmlSerializer
)
// 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
SerializationBinder
proJSON.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.ObjectDataProvider
je riskantní použít v REST projektu, který deserializuje nedůvěryhodná data
- Např.
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
- 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