Einführung¶
Dieser Artikel konzentriert sich auf die Bereitstellung klarer, umsetzbarer Anleitungen zum sicheren Deserialisieren nicht vertrauenswürdiger Daten in Ihren Anwendungen.
Was Deserialisierung ist¶
Serialisierung ist der Prozess, ein Objekt in ein Datenformat umzuwandeln, das später wiederhergestellt werden kann. Personen serialisieren Objekte häufig, um sie im Speicher zu speichern oder als Teil der Kommunikation zu senden.,
Die Deserialisierung ist das Gegenteil dieses Prozesses, indem Daten aus einem bestimmten Format entnommen und in ein Objekt neu erstellt werden. Das beliebteste Datenformat zum Serialisieren von Daten ist heute JSON. Davor war es XML.
Viele Programmiersprachen bieten jedoch eine native Funktion zum Serialisieren von Objekten. Diese nativen Formate bieten normalerweise mehr Funktionen als JSON oder XML, einschließlich der Anpassbarkeit des Serialisierungsprozesses.
Leider können die Funktionen dieser nativen Deserialisierungsmechanismen für böswillige Auswirkungen beim Betrieb mit nicht vertrauenswürdigen Daten wiederverwendet werden., Es wurde festgestellt, dass Angriffe auf Deserialisierer Denial-of-Service -, Zugriffskontroll-und RCE-Angriffe (Remote Code Execution) ermöglichen.
Anleitung zum sicheren Deserialisieren von Objekten¶
Die folgende sprachspezifische Anleitung versucht, sichere Methoden zum Deserialisieren von Daten aufzuzählen, denen nicht vertraut werden kann.
PHP¶
WhiteBox Review¶
Überprüfen Sie die Verwendung der Funktion unserialize() und überprüfen Sie, wie die externen Parameter akzeptiert werden., Verwenden Sie ein sicheres Standarddatenaustauschformat wie JSON (über json_decode()
und json_encode()
), wenn Sie serialisierte Daten an den Benutzer übergeben müssen.
Python¶
BlackBox Review¶
Wenn die Verkehrsdaten am Ende das Symbol dot .
enthalten, ist es sehr wahrscheinlich, dass die Daten in Serialisierung gesendet wurden.
WhiteBox Abgeben¶
Die folgende API in Python wird anfällig für Serialisierung Angriff. Suchcode für das Muster unten.,
- Die Verwendung von
pickle/c_pickle/_pickle
mitload/loads
:
import pickledata = """ cos.system(S'dir')tR. """pickle.loads(data)
- Verwendet von
PyYAML
mitload
:
- Verwendung von
jsonpickle
mitencode
oderstore
Methoden.
Java¶
Die folgenden Techniken sind alle gut für Angriffe gegen Deserialisierung gegen Java serialisierbare Format zu verhindern.,
Implementierungshinweise:
- Überschreiben Sie in Ihrem Code die
ObjectInputStream#resolveClass()
– Methode, um zu verhindern, dass beliebige Klassen deserialisiert werden. Dieses sichere Verhalten kann in eine Bibliothek wie SerialKiller eingeschlossen werden. - Verwenden Sie einen sicheren Ersatz für die generische
readObject()
– Methode, wie hier zu sehen. Beachten Sie, dass dies Angriffe vom Typ „billion laughs“ adressiert, indem die Eingabelänge und die Anzahl der deserialisierten Objekte überprüft werden.
WhiteBox Review¶
Beachten Sie die folgenden Java-API-Anwendungen für potenzielle Serialisierungsanfälligkeit.,
XMLdecoder
with external user defined parameters
XStream
with fromXML
method (xstream version <= v1.46 is vulnerable to the serialization issue)
ObjectInputStream
with readObject
4.,rns kann vorschlagen, dass die Daten in Java-Serialisierungsströmen gesendet wurden
-
AC ED 00 05
in Hex -
rO0
in Base64 -
Content-type
Header einer HTTP-Antwort, die aufapplication/x-java-serialized-object
Verhindern von Datenlecks und Clobbering vertrauenswürdiger Felder¶
Wenn Datenelemente eines Objekts vorhanden sind, die während der Deserialisierung niemals von Endbenutzern kontrolliert oder Benutzern während der Serialisierung ausgesetzt werden sollten, sollten sie als transient
deklariert werden Schlüsselwort (Abschnitt Vertrauliche Informationen schützen).,
Für eine Klasse, die als serialisierbar definiert ist, sollte die Variable sensitive information als deklariert werden.
Beispielsweise wurden die Klasse MyAccount, die Variablen ‚profit‘ und ‚margin‘ als vorübergehend deklariert, um eine Serialisierung zu vermeiden:
public class myAccount implements Serializable{ private transient double profit; // declared transient private transient double margin; // declared transient ....
Verhindern Sie die Deserialisierung von Domänenobjekten¶
Einige Ihrer Anwendungsobjekte müssen aufgrund ihrer Hierarchie möglicherweise serialisierbar implementieren., Um sicherzustellen, dass Ihre Anwendungsobjekte nicht deserialisiert werden können, sollte eine readObject()
– Methode deklariert werden (mit einem final
– Modifikator), die immer eine Ausnahme auslöst:
Verhärten Sie Ihre eigene java.io.ObjectInputStream¶
Die java.io.ObjectInputStream
– Klasse wird zum Deserialisieren von Objekten verwendet. Es ist möglich, sein Verhalten durch Unterklassen zu härten., Dies ist die beste Lösung, wenn:
- Sie können den Code ändern, der die Deserialisierung durchführt
- Sie wissen, welche Klassen Sie erwarten
deserialisieren Die allgemeine Idee besteht darin, ObjectInputStream.html#resolveClass()
zu überschreiben, um einzuschränken, welche Klassen deserialisiert werden dürfen.
Da dieser Aufruf erfolgt, bevor eine readObject()
aufgerufen wird, können Sie sicher sein, dass keine Deserialisierungsaktivität auftritt, es sei denn, der Typ ist einer, den Sie zulassen möchten.,
Ein einfaches Beispiel dafür, das hier gezeigt wird, wobei die LookAheadObjectInputStream
– Klasse garantiert keinen anderen Typ außer der Bicycle
– Klasse deserialisiert:
Vollständigere Implementierungen dieses Ansatzes wurden von verschiedenen Community-Mitgliedern vorgeschlagen:
- NibbleSec-eine Bibliothek, die Whitelisting und Blacklisting von Klassen ermöglicht, die deserialisiert
- IBM-der bahnbrechende Schutz, geschrieben Jahre bevor die verheerendsten Ausbeutungsszenarien in Betracht gezogen wurden.,
- der Apache-Commons-IO-Klassen
Verhärten Alle java.io.ObjectInputStream Verwendung mit einem Agenten¶
Wie bereits erwähnt, die java.io.ObjectInputStream
Klasse zu Deserialisieren von Objekten. Es ist möglich, sein Verhalten durch Unterklassen zu härten. Wenn Sie den Code jedoch nicht besitzen oder nicht auf einen Patch warten können, ist die Verwendung eines Agenten zum Einhärten auf java.io.ObjectInputStream
die beste Lösung.,
Das globale Ändern von ObjectInputStream
ist nur für die Blacklist bekannter bösartiger Typen sicher, da nicht für alle Anwendungen die erwarteten Klassen deserialisiert werden können. Glücklicherweise gibt es in der Blacklist nur sehr wenige Klassen, um heute vor allen bekannten Angriffsvektoren sicher zu sein.
Es ist unvermeidlich, dass mehr „gadget“ – Klassen entdeckt werden, die missbraucht werden können. Es gibt jedoch eine unglaubliche Menge anfälliger Software, die heute verfügbar gemacht wird und eine Korrektur benötigt., In einigen Fällen kann das“ Beheben “ der Sicherheitsanfälligkeit das erneute Entwerfen von Nachrichtensystemen und das Brechen der Abwärtskompatibilität beinhalten, da Entwickler serialisierte Objekte nicht akzeptieren.
Um diese Agenten zu aktivieren, fügen Sie einfach einen neuen JVM-Parameter hinzu:
-javaagent:name-of-agent.jar
Agenten, die diesen Ansatz verfolgen, wurden von verschiedenen Community-Mitgliedern freigegeben:
- rO0 im Gegensatz dazu Sicherheit
Ein ähnlicher, aber weniger skalierbarer Ansatz wäre, den ObjectInputStream Ihrer JVM manuell zu patchen und zu booten. Hinweise zu diesem Ansatz finden Sie hier.
.,Net CSharp¶
WhiteBox Review¶
Suchen Sie im Quellcode nach den folgenden Begriffen:
TypeNameHandling
JavaScriptTypeResolver
Suchen Sie nach Serialisierern, bei denen der Typ von einer benutzergesteuerten Variablen festgelegt wird.,
BlackBox Review¶
Suche nach folgendem base64-kodierten Inhalt, der mit beginnt:
AAEAAAD/////
Suche nach Inhalten mit folgendem Text:
TypeObject
$type:
Allgemeine Vorsichtsmaßnahmen¶
Erlauben Sie dem Datenstrom nicht, den Objekttyp zu definieren, zu dem der Stream deserialisiert wird. Sie können dies verhindern, indem Sie beispielsweise die DataContractSerializer
oder XmlSerializer
verwenden, wenn dies überhaupt möglich ist.,
Wobei JSON.Net
verwendet wird Stellen Sie sicher, dass die TypeNameHandling
nur auf None
gesetzt ist.
TypeNameHandling = TypeNameHandling.None
Wenn JavaScriptSerializer
verwendet werden soll, verwenden Sie es nicht mit einer JavaScriptTypeResolver
.
Wenn Sie Datenströme deserialisieren müssen, die ihren eigenen Typ definieren, dann beschränken Sie die Typen, die deserialisiert werden dürfen. Man sollte sich bewusst sein, dass dies immer noch riskant ist, da viele native.NET-Typen an sich potenziell gefährlich sind. beispielsweise.,
System.IO.FileInfo
FileInfo
Objekte, die tatsächlich auf den Server verweisen, können beim Deserialisieren die Eigenschaften dieser Dateien ändern, z. B. schreibgeschützt, wodurch ein potenzieller Denial-of-Service-Angriff entsteht.
Selbst wenn Sie die Typen begrenzt haben, die deserialisiert werden können, denken Sie daran, dass einige Typen Eigenschaften haben, die riskant sind. System.ComponentModel.DataAnnotations.ValidationException
hat beispielsweise eine Eigenschaft Value
vom Typ Object
., wenn dieser Typ der Typ ist, der für die Deserialisierung zulässig ist,kann ein Angreifer die Eigenschaft Value
auf einen beliebigen Objekttyp festlegen.
Angreifer sollten daran gehindert werden, den Typ zu steuern, der instanziiert wird. Wenn dies möglich ist, kann sogar DataContractSerializer
oder XmlSerializer
unterlaufen werden, z. B.
// Action below is dangerous if the attacker can change the data in the databasevar typename = GetTransactionTypeFromDatabase();var serializer = new DataContractJsonSerializer(Type.GetType(typename));var obj = serializer.ReadObject(ms);
Die Ausführung kann während der Deserialisierung innerhalb bestimmter.NET-Typen erfolgen. Das Erstellen eines Steuerelements wie das unten gezeigte ist unwirksam.,
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}
Für BinaryFormatter
und JSON.Net
ist es möglich, mit einer benutzerdefinierten SerializationBinder
eine sicherere Form des Whitelist-Steuerelements zu erstellen.
Versuchen Sie, über bekannte. Net – unsichere Deserialisierungs-Gadgets auf dem Laufenden zu bleiben, und achten Sie besonders darauf, wo solche Typen von Ihren Deserialisierungsprozessen erstellt werden können. Ein Deserialisierer kann nur Typen instanziieren, die er kennt.
Versuchen Sie, jeden Code, der potenzielle Gadgets erstellen könnte, von jedem Code mit Internetverbindung getrennt zu halten., Als Beispiel ist System.Windows.Data.ObjectDataProvider
, das in WPF-Anwendungen verwendet wird, ein bekanntes Gadget, das einen beliebigen Methodenaufruf ermöglicht. Es wäre riskant, wenn dies ein Verweis auf diese Assembly in einem REST-Service-Projekt wäre, das nicht vertrauenswürdige Daten deserialisiert.
Bekannt .,NET RCE Gadgets¶
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
Language-Agnostic Methods for Deserializing Safely¶
Using Alternative Data Formats¶
A great reduction of risk is achieved by avoiding native (de)serialization formats., Durch den Wechsel zu einem reinen Datenformat wie JSON oder XML verringern Sie die Wahrscheinlichkeit, dass benutzerdefinierte Deserialisierungslogik für böswillige Zwecke wiederverwendet wird.
Viele Anwendungen verlassen sich auf ein Datenübertragungsobjektmuster, bei dem eine separate Objektdomäne für den expliziten Zweck der Datenübertragung erstellt wird. Natürlich ist es immer noch möglich, dass die Anwendung Sicherheitsfehler macht, nachdem ein reines Datenobjekt analysiert wurde.,
Nur signierte Daten deserialisieren¶
Wenn die Anwendung vor der Deserialisierung weiß, welche Nachrichten verarbeitet werden müssen, können sie sie als Teil des Serialisierungsprozesses signieren. Die Anwendung konnte dann wählen, keine Nachricht zu deserialisieren, die keine authentifizierte Signatur hatte.,
Mitigation Tools/Bibliotheken¶
- Java secure Deserialisierung Bibliothek
- SWAT (Serial-Whitelist-Anwendung-Trainer)
- NotSoSerial
Erfassung Tools¶
- Java-Deserialisierung cheat Blatt richtet sich an pen Tester
- Ein proof-of-concept-tool für die Generierung von Nutzlasten, die auf die Ausnutzung unsichere Java-Objekt-Deserialisierung.
- Java De-Serialisierung toolkits
- Java de-Serialisierung tool
- .,n
- JavaSerialKiller
- Java-Deserialisierung Scanner
- Rülpsen-ysoserial
- SuperSerial
- SuperSerial-Aktiv
Referenzen¶
- Java-Deserialisierung-Cheat-Sheet
- Deserialisierung nicht vertrauenswürdiger Daten
- Java-Deserialisierung Angriffe – German OWASP Day 2016
- AppSecCali 2015 – Marshalling Pickles
- Fingerhut-Security – Vulnerability-Ankündigung
- Java-Deserialisierung cheat Blatt richtet sich an pen Tester
- Ein proof-of-concept-tool für die Generierung von Nutzlasten, die auf die Ausnutzung unsichere Java-Objekt-Deserialisierung.,
- Java De-Serialisierung toolkits
- Java de-Serialisierung tool
- Burp-Suite-Erweiterung
- Java secure Deserialisierung Bibliothek
- Serianalyzer ist eine statische bytecode-analyzer für die Deserialisierung
- Payload generator
- Android-Java-Deserialisierung Sicherheitsanfälligkeit Tester
- Burp-Suite-Erweiterung
- JavaSerialKiller
- Java-Deserialisierung Scanner
- Rülpsen-ysoserial
- SuperSerial
- SuperSerial-Aktiv
- .Net
- Alvaro Muñoz: .,NET Serialization: Erkennen und Verteidigen anfälliger Endpunkte
- James Forshaw-Black Hat USA 2012-Bist du mein Typ? Brechen .net Sandboxen Durch Serialisierung
- Jonathan Birch BlueHat v17 – Gefährliche Inhalte – Sicherung .Net Deserialisierung
- Alvaro Muñoz & Oleksandr Mirosh – Freitag der 13: der Angriff auf JSON – AppSecUSA 2017