FlawOpen

flawopen.com/Ruby YAML/Ruby YAML

YAML.load est-il sûr avec des entrées non fiables ?

CWE-502: Deserialization of Untrusted DataPage de référence
Réponse courte

Vérifiez la version de Psych réellement chargée par l’application : Psych 4, fourni avec Ruby 3.1, a fait de YAML.load une désérialisation sûre par défaut. Les versions précédentes de Psych construisaient librement des objets ; Psych peut aussi être mis à niveau indépendamment de Ruby. YAML.unsafe_load et Marshal.load désérialisent des objets Ruby et ne doivent jamais recevoir de données non fiables.

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)

Pourquoi YAML peut être dangereux

YAML contient des balises que Psych peut convertir en objets Ruby. Avec un chargement non sécurisé, un document balisé peut demander la construction d’une classe et fournir des valeurs pour son état sérialisé ; l’impact dépend des classes disponibles et de leur comportement. C’est le principe des chaînes de gadgets de désérialisation. Utilisez un chargement sûr pour les YAML non fiables et validez séparément les données obtenues. Le risque général existe aussi avec Python pickle, PHP unserialize et Marshal.load en Ruby.

Rails et d’autres applications peuvent charger de nombreuses dépendances, ce qui élargit l’ensemble des classes et comportements accessibles à une chaîne de désérialisation non sécurisée. Cela dépend du déploiement ; ce n’est pas une propriété de toutes les applications Rails ni de tout document YAML.

Pourquoi le changement de version a créé de la confusion

Psych 4 a modifié YAML.load pour utiliser un chargement sûr par défaut et a introduit unsafe_load pour conserver le comportement antérieur de construction d’objets. Ruby 3.1 incluait Psych 4, mais une application peut choisir une autre version de la gem Psych ; vérifiez la dépendance résolue et le runtime, pas seulement la version de Ruby. Comme le chargement sûr peut refuser des classes propres à l’application ou des alias, migrez avec une liste d’autorisation explicite et minimale au lieu de passer à unsafe_load.

Si une mise à niveau introduit unsafe_load, signalez cet appel lorsque l’entrée peut être contrôlée hors de la frontière de déploiement fiable. Préférez safe_load avec la liste minimale requise de permitted_classes ; ne l’élargissez pas uniquement pour masquer des erreurs de compatibilité.

FAQ

Questions fréquentes

YAML.safe_load est-il totalement sûr ?

Psych.safe_load limite les classes désérialisées à celles autorisées (types scalaires et collections de base par défaut) et refuse les alias. Cela ne valide ni la structure, ni la taille, ni les règles métier de l’application. N’autorisez que les classes nécessaires, limitez la taille et validez les données renvoyées. Certaines implémentations et chaînes de traitement YAML ont connu des DoS par expansion d’alias ; CVE-2024-35221 documente un cas lié aux métadonnées RubyGems. Cela ne signifie pas que chaque appel à Psych.safe_load est vulnérable.

Qu’en est-il de mes propres fichiers de configuration ?

Un fichier inclus dans un artefact applicatif fiable et protégé en intégrité n’a pas la même provenance qu’un téléversement utilisateur ou qu’un fichier contrôlé par un tenant. Même pour une configuration interne, préférez safe_load et n’autorisez que les classes nécessaires. N’utilisez unsafe_load que pour des données fixes dont la fiabilité est démontrée, jamais pour un contenu influencé par l’utilisateur ou la requête.

Marshal peut-il être acceptable ?

Autre risque Ruby : Marshal.load

À la différence de YAML, la documentation Ruby indique que Marshal.load peut reconstruire presque toute classe chargée dans le processus et entraîner une exécution de code à distance si les données ne sont pas fiables. Gardez les données Marshal dans une frontière de confiance ; ne désérialisez jamais des octets fournis par l’utilisateur ou influencés par un attaquant.

Références

À voir aussi Désérialisation non sécurisée : risques et défense .NET BinaryFormatter : risques et migration Sécurité d’ObjectInputStream en Java : désérialisation sûre Newtonsoft.Json TypeNameHandling : configuration sûre ? PHP unserialize() et les données non fiables Python pickle.load() : risques des données non fiables