cd ~/blog

~/vulns/unsafe-yaml-deserialization.md

Unsafe YAML Deserialization

rceautor: Jordy Pérez Osorio aviso legal
YAMLdeserializationRCE

~2 min de lectura


1. Descripción técnica

Unsafe YAML Deserialization ocurre cuando una aplicación procesa YAML no confiable con un cargador capaz de construir objetos del lenguaje, invocar funciones o resolver etiquetas con efectos laterales. YAML sólo describe datos en sus usos seguros, pero algunas implementaciones incorporan extensiones que reconstruyen objetos y ejecutan constructores durante la carga.

En PyYAML, una etiqueta como !!python/object/apply puede indicar que el cargador invoque un callable con los argumentos incluidos en el documento. Si la aplicación usa un loader inseguro sobre contenido controlado por el usuario, el análisis del archivo deja de ser una operación pasiva y puede transformarse en ejecución de código.

// renderizando diagrama…

2. Impacto

El impacto puede incluir ejecución de comandos, lectura o modificación de archivos y acceso a secretos del proceso. Depende de los constructores disponibles, de la biblioteca y de los privilegios de la aplicación. La presencia de YAML no basta para confirmar la vulnerabilidad: debe demostrarse que el loader admite tipos peligrosos y que el atacante controla el documento procesado.

3. Condiciones necesarias

  1. La aplicación acepta YAML controlado total o parcialmente por un usuario no confiable.
  2. Utiliza un loader que permite construir objetos o ejecutar callables.
  3. Las etiquetas peligrosas no son rechazadas ni reducidas a tipos escalares y colecciones simples.
  4. El proceso posee permisos suficientes para producir un impacto útil.

4. Validación y detección

La revisión debe identificar el punto exacto de carga y la variante de API utilizada. En PyYAML se debe buscar yaml.load() con loaders inseguros, UnsafeLoader o equivalentes, y distinguirlos de safe_load() y SafeLoader. Una prueba segura puede usar una operación sin efectos destructivos y confirmar que el constructor se invoca durante el parseo.

También conviene revisar tipos personalizados, hooks de construcción y conversiones intermedias. Cambiar la extensión del archivo o comprobar su sintaxis no elimina el riesgo si el mismo contenido termina en un deserializador capaz de crear objetos.

5. Explotación documentada en los writeups

5.1. 112-cve1

La aplicación acepta un documento YAML que llega a un cargador compatible con etiquetas de Python. El payload usa una etiqueta que construye subprocess.Popen; al deserializarlo, el servidor invoca el proceso y ejecuta la orden con la identidad de la aplicación.

6. Mitigación

  • Procesar entradas no confiables con safe_load() o un esquema que sólo admita tipos necesarios.
  • Rechazar etiquetas específicas del lenguaje y constructores arbitrarios.
  • Mantener la biblioteca actualizada y revisar los cambios de comportamiento entre loaders.
  • Ejecutar el parser con el mínimo de privilegios y sin acceso innecesario a secretos.
  • Preferir formatos y validadores cuyo modelo de datos no incluya construcción de objetos ejecutables.

7. Clasificación

8. Referencias y conexiones

// relacionados