Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-32722 — XSS almacenado de Bloomberg Memray a través de metadatos de línea de comandos sin escapar | Kitploit
Herramientas/GitHubGitHub/0xmrma/cve-2026-32722
Análisis Estático de Código (SAST)Análisis de VulnerabilidadesExplotación de Aplicaciones WebPruebas de PenetraciónPapers e InvestigaciónAprendizaje y Educación
GitHub0xmrma/cve-2026-32722

CVE-2026-32722

XSS almacenado de Bloomberg Memray a través de metadatos de línea de comandos sin escapar

Ver Repositorio
124hace 6 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-32722

XSS almacenado en Bloomberg Memray mediante metadatos de línea de comandos sin escapar

Introducción

Encontré este problema al revisar Memray, el perfilador de memoria de Python de Bloomberg, con una pregunta simple en mente:

¿Pueden los metadatos de tiempo de ejecución controlados por el atacante cruzar de forma insegura hacia la salida del informe renderizada en el navegador?

En este caso, la respuesta fue sí.

El error estaba en la ruta de generación de informes HTML de Memray, donde los metadatos de la línea de comandos se renderizaban en un informe abierto en el navegador sin escapar. Eso convirtió un campo operativo en un sumidero HTML ejecutable y, finalmente, se convirtió en CVE-2026-32722.

Proyecto: Memray en GitHub
Aviso: GHSA-r5pr-887v-m2w9 / CVE-2026-32722

photo0

Cadena de ataque

argv controlado por el atacante → metadata.command_line → sumidero de plantilla HTML sin escapar → marcado sin procesar en el informe generado → ejecución de JavaScript en el navegador


Qué hace Memray

Memray es un perfilador de memoria de Python.

Instrumenta un proceso de Python, registra el comportamiento de asignación y produce informes que ayudan a los desarrolladores a comprender:

  • dónde se asigna la memoria
  • qué rutas de llamada son responsables
  • cómo es el uso máximo de memoria
  • cómo cambia la memoria con el tiempo

Algunos de esos informes se emiten como HTML y se abren en un navegador.

Eso hace que la generación de informes sea un límite de seguridad real.

La pregunta relevante no es si Memray es una "herramienta local".
La pregunta relevante es si los datos controlados por el atacante pueden cruzar de forma insegura hacia la salida renderizada en el navegador.

En este caso, podían.


Por qué valía la pena investigar este error

Mucha gente subestima las herramientas para desarrolladores.

Eso es un error.

Una vez que una herramienta:

  • registra metadatos de tiempo de ejecución,
  • almacena valores influenciados por el atacante,
  • y luego los renderiza en HTML,

hereda los mismos riesgos de codificación de salida que una aplicación web.

Ese fue el problema central aquí.

Este error no estaba en la lógica de perfilado. No estaba en el seguimiento de asignaciones. No estaba en el manejo nativo de memoria.

Era una clásica falla de límite de confianza:

  • metadatos no confiables entraron al sistema,
  • cruzaron hacia un sumidero HTML,
  • y se renderizaron sin escapar.

Eso es suficiente para crear una vulnerabilidad real.


El límite en el que me centré

No abordé Memray fuzzeando opciones aleatorias de CLI ni persiguiendo caídas del sistema.

El enfoque más sólido era identificar primero la superficie de seguridad de mayor probabilidad.

Para Memray, esa era la generación de informes HTML.

¿Por qué?

Porque la salida HTML introduce un sumidero en el navegador, y los sumideros del navegador convierten errores comunes de metadatos en problemas de seguridad si:

  • la entrada está influenciada por el atacante,
  • la salida no está escapada,
  • y el navegador interpreta el resultado como marcado en lugar de texto.

Eso es exactamente lo que sucedió aquí.


Causa raíz

El error se reduce a dos líneas.

En:

def get_render_environment() -> jinja2.Environment:
    loader = jinja2.PackageLoader("memray.reporters")
    env = jinja2.Environment(loader=loader)

el entorno Jinja se crea sin autoescape.

Luego en:

Command line: <code>{{ metadata.command_line }}</code><br>

metadata.command_line se renderiza directamente en HTML.

Esa es toda la vulnerabilidad.

Por qué esto es explotable

Porque metadata.command_line está influenciado por el atacante.

Memray registra la línea de comandos utilizada para ejecutar el programa perfilado. Eso significa que los valores controlados por el usuario de argv se conservan como metadatos y luego se insertan en el informe.

Entonces la cadena de explotación es sencilla:

  • el atacante controla el contenido de la línea de comandos
  • Memray lo almacena en metadata.command_line
  • la plantilla lo emite en HTML
  • el entorno no lo escapa automáticamente
  • el navegador lo parsea como marcado vivo

Eso convierte los metadatos en contenido ejecutable en el navegador.


Qué convierte esto en un problema de seguridad, no solo en un renderizado deficiente

La distinción importante es la ejecución.

Muchos errores producen HTML malformado. Eso por sí solo no es suficiente.

Aquí, el contenido controlado por el atacante no solo era visible en el código fuente de la página. El navegador lo interpretaba como HTML activo y lo ejecutaba como JavaScript.

Esa es la diferencia entre:

  • corrupción del formato
  • y un sumidero XSS real

Entonces la pregunta no era:

"¿Puede aparecer HTML en el informe?"

La pregunta real era:

"¿Puede el HTML controlado por el atacante volverse ejecutable cuando se abre el informe?"

La respuesta fue sí.


PoC

Mi reproducción inicial usaba un script explícito más un argumento controlado por el atacante:

cat > victim.py <<'PY'
x = [b"A" * 1024 for _ in range(1000)]
print("done")
PY

python -m memray run -o poc.bin victim.py ''
python -m memray flamegraph -o poc.html poc.bin

El HTML generado contenía marcado sin procesar controlado por el atacante:

Command line: <code>~/memray/src/memray/__main__.py run -o poc.bin victim.py </code><br>

Abrir o actualizar el informe generado provocaba la ejecución de JavaScript.

Eso estableció la afirmación central:

  • el valor no estaba escapado,
  • el navegador lo parseaba como marcado,
  • y el sumidero era ejecutable.

Más tarde, durante la divulgación coordinada, el mantenedor simplificó aún más la reproducción:

python -m memray run -o poc.bin -c '# '

Esa versión es mejor porque aísla el límite vulnerable de forma más directa:

  • sin archivo adicional
  • sin lógica de aplicación adicional
  • solo contenido de línea de comandos controlado por el atacante entrando en la canalización del informe

Por qué se eligió el payload

El payload fue intencionalmente simple:

Esto no se trata de payloads llamativos.

Es una sonda de ejecución limpia porque:

  • no requiere infraestructura externa
  • es obvio en el HTML renderizado
  • demuestra la interpretación HTML de inmediato
  • demuestra la ejecución en el navegador sin depender de contenido remoto

Para esta clase de errores, eso es suficiente.


Validación del alcance

Un solo tipo de informe ya habría sido suficiente para justificar el problema.

Pero quería saber si esto estaba aislado o era estructural.

Confirmé el mismo comportamiento en:

  • informes flamegraph
  • informes de tabla
  • informes flamegraph generados con --no-web

Eso importaba por dos razones.

Primera

Mostró que el sumidero vulnerable se reutilizaba en múltiples salidas HTML.

Segunda

Demostró que el error no dependía de recursos externos alojados en CDN.

--no-web seguía reproduciendo el problema, lo que significa que el fallo estaba en el HTML generado por el propio Memray y en el manejo de plantillas, no en el comportamiento de JS remoto. Eso hizo que el caso fuera mucho más sólido.


Por qué se clasificó como severidad baja

La principal preocupación del mantenedor era el control práctico del atacante.

Eso es justo.

Este no es el tipo de problema donde un atacante remoto no autenticado golpea un endpoint HTTP expuesto y obtiene impacto inmediato.

Descargar herramienta