FlawOpen

flawopen.com/Ruby YAML/Ruby YAML

Ist YAML.load bei nicht vertrauenswürdigen Eingaben sicher?

CWE-502: Deserialization of Untrusted DataReferenzseite
Kurz erklärt

Prüfen Sie die tatsächlich geladene Psych-Version: Psych 4, mit Ruby 3.1 ausgeliefert, stellte YAML.load standardmäßig auf sichere Deserialisierung um. Frühere Psych-Versionen konstruierten beliebige Objekte; Psych kann unabhängig von Ruby aktualisiert werden. YAML.unsafe_load und Marshal.load deserialisieren Ruby-Objekte und dürfen niemals nicht vertrauenswürdige Eingaben erhalten.

VULNERABLE
# Psych < 4: YAML.load used unsafe
# object construction by default.
YAML.load(params[:config])

# Every Psych version: explicitly unsafe.
YAML.unsafe_load(user_input)
Psych.unsafe_load(user_input)

# Marshal has no restricted safe-load API.
Marshal.load(cookie_value)
FIXED
# Explicit restricted types; keep this list minimal.
require "yaml"
require "date"

data = YAML.safe_load(
  input,
  permitted_classes: [Date],
  permitted_symbols: [],
  aliases: false
)

# For ordinary external data, prefer JSON and
# validate its shape, values, and input size.
data = JSON.parse(input)

Warum YAML gefährlich sein kann

YAML-Tags können von Psych in Ruby-Objekte umgewandelt werden. Bei unsicherem Laden kann ein getaggtes Dokument die Konstruktion einer Klasse anfordern und Werte für deren serialisierten Zustand liefern; die Auswirkungen hängen von verfügbaren Klassen und deren Verhalten ab. So entstehen Deserialisierungs-Gadget-Ketten. Laden Sie nicht vertrauenswürdiges YAML sicher und validieren Sie die resultierenden Daten zusätzlich. Das allgemeine Risiko besteht auch bei Python pickle, PHP unserialize und Ruby-Marshal.load.

Rails-Anwendungen und andere Dienste laden oft viele Abhängigkeiten. Dadurch stehen einer unsicheren Deserialisierungskette mehr Klassen und Verhaltensweisen zur Verfügung. Das hängt von der konkreten Bereitstellung ab und gilt nicht pauschal für jede Rails-Anwendung oder YAML-Datei.

Warum die Versionsänderung für Verwirrung sorgte

Psych 4 änderte YAML.load so, dass standardmäßig sicher geladen wird, und führte unsafe_load für das frühere Verhalten mit Objektkonstruktion ein. Ruby 3.1 enthielt Psych 4, Anwendungen können jedoch eine andere Psych-Gem-Version auswählen. Prüfen Sie deshalb die aufgelöste Abhängigkeit und Runtime, nicht nur die Ruby-Version. Da sicheres Laden anwendungsspezifische Klassen oder Aliase ablehnen kann, migrieren Sie mit einer minimalen expliziten Zulassungsliste, statt zu unsafe_load zu wechseln.

Führt ein Upgrade zu unsafe_load, behandeln Sie den Aufruf als Befund, wenn Eingaben außerhalb der vertrauenswürdigen Bereitstellungsgrenze beeinflusst werden können. Verwenden Sie bevorzugt safe_load mit der kleinsten nötigen Liste für permitted_classes; erweitern Sie sie nicht nur, um Kompatibilitätsfehler zu unterdrücken.

FAQ

Häufige Fragen

Ist YAML.safe_load vollständig sicher?

Psych.safe_load beschränkt deserialisierte Klassen auf die erlaubten Typen (standardmäßig einfache Skalare und Sammlungen) und lehnt Aliase ab. Es validiert weder Datenstruktur noch Größe oder Geschäftsregeln der Anwendung. Erlauben Sie nur benötigte Klassen, begrenzen Sie die Eingabegröße und prüfen Sie die zurückgegebenen Daten. In bestimmten YAML-Implementierungen und Abläufen gab es Denial-of-Service durch Alias-Erweiterung; CVE-2024-35221 dokumentiert einen Fall beim Lesen von RubyGems-Metadaten. Daraus folgt nicht, dass jeder Psych.safe_load-Aufruf verwundbar ist.

Was ist mit eigenen Konfigurationsdateien?

Eine Datei in einem vertrauenswürdigen, integritätsgeschützten Anwendungsartefakt hat eine andere Herkunft als ein Upload oder eine von einem Tenant kontrollierte Datei. Verwenden Sie auch für interne Konfiguration bevorzugt safe_load und erlauben Sie nur erforderliche Klassen. Nutzen Sie unsafe_load nur für feste, nachweislich vertrauenswürdige Daten, niemals für durch Nutzer oder Anfragen beeinflussbare Inhalte.

Ist Marshal jemals vertretbar?

Ein separates Ruby-Risiko: Marshal.load

Unabhängig von YAML dokumentiert Ruby, dass Marshal.load nahezu jede im Prozess geladene Klasse wiederherstellen kann und bei nicht vertrauenswürdigen Daten zu Remote-Codeausführung führen kann. Bewahren Sie Marshal-Daten innerhalb einer Vertrauensgrenze auf und deserialisieren Sie niemals vom Benutzer gelieferte oder von Angreifern beeinflusste Bytes.

Quellen

Siehe auch Unsichere Deserialisierung: Risiken und Schutz .NET BinaryFormatter: Risiken und Migration Java ObjectInputStream: Deserialisierung sicher gestalten Newtonsoft.Json TypeNameHandling: sichere Konfiguration? PHP unserialize() und nicht vertrauenswürdige Daten Python pickle.load(): Risiken nicht vertrauenswürdiger Daten