Two critical vulnerabilities have been exposed in JetBrains TeamCity On-Premises versions up to 2023.11.3. Identified by Rapid7’s vulnerability research team in February 2024, CVE-2024-27198 and CVE-2024-27199 pose a significant threat, enabling unauthenticated attackers to potentially gain administrative control or execute code remotely on affected TeamCity servers.
CVE-2024-27198, categorized under CWE-288, highlights an authentication bypass vulnerability with a critical severity score of 9.8, while CVE-2024-27199, associated with CWE-23, outlines a src traversal issue scored at 7.3. These vulnerabilities not only compromise server integrity but also open the door to more extensive supply chain attacks.
In light of these discoveries, JetBrains has swiftly released version 2023.11.4 to mitigate these threats.
In response to these vulnerabilities, the Splunk Threat Research Team has swiftly developed security analytics and hunting queries to support defenders. Below, we'll review what we know so far about how this exploit operates, the security analytics and hunting queries developed by the Splunk Threat Research Team, and additional tips around capturing TeamCity logs.
In the following sections, we’ll break down the Nuclei templates that have been found scanning the Internet.
Contributors to Nuclei swiftly submitted templates to identify potentially vulnerable TeamCity servers on the Internet: https://github.com/projectdiscovery/nuclei-templates/pull/9279 and https://github.com/projectdiscovery/nuclei-templates/pull/9280.
To exploit this in JetBrains TeamCity servers, adversaries can follow a surprisingly straightforward method to bypass authentication. It all starts with them sending a request to the server for a page that doesn’t exist, usually resulting in an error. However, by tweaking the URL with a special query (?jsp=/app/rest/server;.jsp), they trick the server into serving up sensitive information like its version, all without needing to log in.
Taking it further, adversaries can leverage this vulnerability in a few clever ways to gain control over the TeamCity server, along with all its projects, builds, agents, and artifacts. One common tactic involves creating a new admin user under their control. They do this by sending a request to the server’s user management API, packed with their desired username and password:
<teamcitysite>/hax?jsp=/app/rest/users;.jsp
But why stop there? Another route adversaries may take is generating an admin access token for themselves, further cementing their access:
<teamcitysite>/hax?jsp=/app/rest/users/id:1/tokens/TokenName;.jsp
This effectively hands over the keys to the kingdom, granting the attacker unfettered access to manipulate the server as they see fit.
Back to the Nuclei template, an example GET request from the template will look something like:
GET <teamcitysite>/hax?jsp=/app/rest/server;.jsp HTTP/1.1
A response from the server, if vulnerable, will respond with what Rapid7 shared in their blog:
C:\Users\sfewer>curl -ik http://172.29.228.65:8111/hax?jsp=/app/rest/server;.jsp HTTP/1.1 200 TeamCity-Node-Id: MAIN_SERVER Cache-Control: no-store Content-Type: application/xml;charset=ISO-8859-1 Content-Language: en-IE Content-Length: 794 Date: Wed, 14 Feb 2024 17:24:59 GMT <?xml version="1.0" encoding="UTF-8" standalone="yes"?><server version="2023.11.3 (build 147512)" versionMajor="2023" versionMinor="11" startTime="20240212T021131-0800" currentTime="20240214T092459-0800" buildNumber="147512" buildDate="20240129T000000-0800" internalId="cfb27466-d6d6-4bc8-a398-8b777182d653" role="main_node" webUrl="http://localhost:8111" artifactsUrl=""><projects href="/app/rest/projects"/><vcsRoots href="/app/rest/vcs-roots"/><builds href="/app/rest/builds"/><users href="/app/rest/users"/><userGroups href="/app/rest/userGroups"/><agents href="/app/rest/agents"/><buildQueue href="/app/rest/buildQueue"/><agentPools href="/app/rest/agentPools"/><investigations href="/app/rest/investigations"/><mutes href="/app/rest/mutes"/><nodes href="/app/rest/server/nodes"/></server>
Based on this response, we know the server is vulnerable.
CVE-2024-27199 is a vulnerability in the web part of TeamCity, caused by a path traversal issue (CWE-22) that lets someone skip past login checks. It has the potential to sneak out information from the server without needing to authenticate.
The paths identified as vulnerable include:
Exploitation involves utilizing directory traversal tactics (../) to navigate towards sensitive endpoints. These maneuvers allow adversaries not only to gather information but also to alter system settings through unauthenticated access to several critical JSP pages and servlet endpoints. Key endpoints impacted by this vulnerability are:
The Nuclei template will perform a GET request to the following URI’s, and will stop based on the first match.
To test proof of concept (POC) scripts or the Nuclei templates, we can easily setup a Docker container and test it out.
Download the prior vulnerable version:
docker pull jetbrains/teamcity-server:2023.11.3
Start the container:
docker run -it -d --name teamcity -u root -p 8111:8111 jetbrains/teamcity-server:2023.11.3
Simply enough, head to http://localhost:8111 and perform the basic setup of TeamCity.
Login page to Docker Container running TeamCity, Splunk 2024
Once the defaults are selected, login with your admin account and verify that in our lab on the users tab (http://localhost:8111/admin/admin.html?item=users), only the newly created account is there.
TeamCity users in Docker Container, Splunk 2024
Now let’s use the POC here and add a new user.
python3 CVE-2024-27198.py -t http://localhost:8111 -u bobadminhere -p P@ssword1
TeamCity POC testing, Splunk 2024
And now back in the users page we see our new account:
TeamCity users list after POC in Docker Container, Splunk 2024
MetaSploit also released their module. The module was in a PR here, so we added it to our Metasploit-Framework and gave it a spin.
First, we ran a search for jetbrains and then set to use the new module:
MetaSploit Module Testing, Splunk 2024
Once we set our RHOSTS (localhost, or remote IP), we ran the exploit.
MetaSploit Module running, Splunk 2024
First, we will dig into some of the JetBrains TeamCity logs. Then, we’ll share hunting queries and newly released content to help defenders pinpoint exploitation.
Using either POC we shared above, artifacts are generated in the TeamCity logs. Let’s dive into a few variations of these to see how we can use Splunk to find suspicious behavior.
Audit Logs
First, when looking in the UI of TeamCity we see in the audit logs suspicious activity with modules being uploaded or new users being added.
http://localhost:8111/admin/admin.html?item=audit
TeamCity in Docker Container Plugins, Splunk 2024
In addition, we can download the logs from TeamCity, or utilize the Splunk Universal Forwarder to ingest the logs.
Within the TeamCity UI, we can download them here: http://localhost:8111/admin/admin.html?item=diagnostics&tab=logs
TeamCity Diagnostics in Docker Container, Splunk 2024
On the filesystem, in the Docker container in this instance, the TeamCity logs are under /opt/teamcity/logs:
TeamCity Diagnostics on disk within Docker Container, Splunk 2024
With this view into the teamcity-activities.log file, we see the new user being created; a plugin being uploaded, disabled and deleted; and a new token being deleted.
TeamCity Activities log in Docker Container, Splunk 2024
And in the teamcity-server.log:
TeamCity Server Log in Docker Container, Splunk 2024
For the server log, we see similar activity with the plugin and token.
With the teamcity-javaLogging*.log file we see the requests, similar to what Rapid7 described.
TeamCity Java Logging in Docker Container, Splunk 2024
With that, we can ingest these three logs and use the following queries to assist with identifying these behaviors.
New User
The following direct source query identifies a new user being created based on the teamcity-actiities.log file.
source="teamcity-activities.log" host="teamcity" index="jetbrains" "user_create" | rex "user_create: (?User \"user with id=\d+\" was created by \"user with id=\d+\")" | table _time, new_user_event, host, source
TeamCity New User Added, Splunk 2024
New Token
Utilizing the teamcity-server.log, we can extract when a new token is deleted.
index=jetbrains "delete_token_for_user:" | rex "delete_token_for_user: Deleted token \"(?[^\"]+)\" for user \"user with id=(?\d+)\"" | table _time, token_id, user_id, host
TeamCity New Token, Splunk 2024
New Plugin
Similarly, we can identify when a new plugin is added or initialized.
index=jetbrains ("plugin_deleted:" OR "Plugins initialization completed") |rex "plugin_(?deleted): Plugin \"(?[^\"]+)\"" | rex "Plugins initialization completed \((?\d+) plugins loaded\): \[(?\S+) \(ver:(?\S+)\)\]"| eval action=if(isnull(action), "added", action) | table _time, action, plugin_id, plugin_version, host
(TeamCity New Plugin, Splunk 2024)
We are releasing three analytics covering the Web data model and Suricata. These may be modified as needed for any log source.
JetBrains TeamCity Authentication Bypass Suricata CVE-2024-27198
This analytic detects exploitation attempts against CVE-2024-27198 in JetBrains TeamCity servers, where attackers bypass authentication to gain unauthorized access. It monitors for specific POST requests to /app/rest/users and token generation endpoints, indicative of attempts to create admin users or tokens without authentication. The search, tailored for Suricata logs, identifies malicious traffic patterns, logging source, destination, user agent, and request details, crucial for incident response.
sourcetype=suricata ((http.url="*?jsp=*" AND http.url="*;.jsp*") http.status=200 http_method=POST) OR (http.url IN ("*jsp=/app/rest/users;.jsp","*?jsp=/app/rest/users;.jsp","*?jsp=.*/app/rest/users/id:*/tokens;*") http.status=200 http_method=POST ) | stats count min(_time) as firstTime max(_time) as lastTime by src, dest, http.http_user_agent, http.url, http.status,http_method | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
TeamCity Auth Bypass using Suricata, Splunk 2024
Similar query but now using the Web datamodel:
| tstats count min(_time) as firstTime max(_time) as lastTime from datamodel=Web where ((Web.url="*?jsp=*" AND Web.url="*;.jsp*") Web.status=200 Web.http_method=POST) OR (Web.url IN ("*jsp=/app/rest/users;.jsp","*?jsp=/app/rest/users;.jsp","*?jsp=.*/app/rest/users/id:*/tokens;*") Web.status=200 Web.http_method=POST ) by Web.src, Web.dest, Web.http_user_agent, Web.url, Web.status, Web.http_method, sourcetype, source | `drop_dm_object_name("Web")` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
TeamCity Auth Bypass using Web Datamodel, Splunk 2024
JetBrains TeamCity Limited Auth Bypass Suricata CVE-2024-27199
This analytic targets CVE-2024-27199, a critical vulnerability in JetBrains TeamCity, allowing unauthenticated path traversal attacks. It focuses on detecting unauthorized GET requests to specific endpoints like /admin/diagnostic.jsp and /app/https/settings/uploadCertificate, which could indicate attempts to access or alter server settings or upload malicious certificates. By monitoring for abnormal access patterns to these endpoints, the detection helps in identifying and responding to potential authentication bypass attempts, safeguarding against unauthorized information disclosure or system modification.
sourcetype=suricata http.url IN ("*../admin/diagnostic.jsp*", "*../app/https/settings/*", "*../app/pipeline*", "*../app/oauth/space/createBuild.html*", "*../res/*", "*../update/*", "*../.well-known/acme-challenge/*", "*../app/availableRunners*", "*../app/https/settings/setPort*", "*../app/https/settings/certificateInfo*", "*../app/https/settings/defaultHttpsPort*", "*../app/https/settings/fetchFromAcme*", "*../app/https/settings/removeCertificate*", "*../app/https/settings/uploadCertificate*", "*../app/https/settings/termsOfService*", "*../app/https/settings/triggerAcmeChallenge*", "*../app/https/settings/cancelAcmeChallenge*", "*../app/https/settings/getAcmeOrder*", "*../app/https/settings/setRedirectStrategy*") http.status=200 http_method=GET | stats count min(_time) as firstTime max(_time) as lastTime by src, dest, http_user_agent, http.url, http.status, http_method | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
TeamCity Path Traversal, Splunk 2024
Modify this query as needed, including reducing the risk score, removing certain endpoints or modifying it to your log source.
Internet-exposed JetBrains TeamCity servers face a severe security risk with the discovery of two critical vulnerabilities, CVE-2024-27198 and CVE-2024-27199, which were promptly identified by Rapid7's research team. These vulnerabilities could allow unauthorized users to execute code remotely or gain administrative control of the servers. CVE-2024-27198 has a CVSS score of 9.8 and permits authentication bypass, while CVE-2024-27199 is scored at 7.3 and enables attackers to exploit path traversal weaknesses. The latter could lead to information leakage and unauthorized system modifications. JetBrains has responded quickly by releasing an updated version of TeamCity to address these vulnerabilities.
Exploitation of these vulnerabilities is alarmingly straightforward, requiring only a manipulated URL to access restricted server information or to create administrative users without authentication. For example, adversaries could append ?jsp=/app/rest/users;.jsp to the base server URL, granting themselves administrative privileges or generating access tokens, which presents a significant threat to the integrity and security of TeamCity servers. This blog covers our findings on exploit operations, security analytics, and additional tips for logging and defending TeamCity environments against such vulnerabilities.
Visit research.splunk.com to view the Splunk Threat Research Team's complete security content repository. You can implement this content using the Enterprise Security Content Updates app or the Splunk Security Essentials app.
The Splunk platform removes the barriers between data and action, empowering observability, IT and security teams to ensure their organizations are secure, resilient and innovative.
Founded in 2003, Splunk is a global company — with over 7,500 employees, Splunkers have received over 1,020 patents to date and availability in 21 regions around the world — and offers an open, extensible data platform that supports shared data across any environment so that all teams in an organization can get end-to-end visibility, with context, for every interaction and business process. Build a strong data foundation with Splunk.