Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

07 - CI-CD e Supply Chain de Software

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

CI-CD e Supply Chain de Software

Nota 07 do capítulo 26 (CTI e Threat Hunting em Ambientes Modernos), cobrindo o supply chain de software e o envenenamento de pipelines de CI-CD como superfície de ataque.
A nota disseca os incidentes paradigmáticos SolarWinds, XZ Utils e 3CX, mapeia as TTPs de pipeline poisoning e entrega telemetria e consultas para caçar abuso de runner e exfiltração de segredos.
Dialoga com a nota 05 deste capítulo em telemetria de cloud, com o DaC do capítulo 18, cuja própria esteira de detecções é um alvo, e com os controles PRT.4 e SIM do capítulo 15.

1. Contexto e Posicionamento na Biblioteca

A esteira de CI-CD é o único lugar da infraestrutura onde a organização executa, com credenciais de produção e segredos de cloud, código que acabou de chegar de fora: dependências de registries públicos, patches de terceiros, contribuições anônimas e ações de marketplace. O adversário percebeu que comprometer um elo dessa cadeia entrega escala industrial, porque um único merge malicioso se propaga por push automático para milhares de consumidores, assinado digitalmente e sem qualquer comportamento anômalo no endpoint. Esta nota estrutura a defesa dessa superfície em quatro frentes: anatomia da cadeia, lições dos incidentes que definiram o tema, TTPs de pipeline poisoning e caça sobre a telemetria da esteira.

O posicionamento na biblioteca é duplo. Como superfície de ataque, a nota pertence ao bloco de ambientes modernos do capítulo 26, ao lado da telemetria de cloud da nota 05 e do runtime de containers da nota 06. Como vítima em potencial, a própria biblioteca opera detecção como código pelo capítulo 18, e o repositório de regras Sigma e os pipelines de deploy do capítulo 18 herdam diretamente os controles e caças que aqui são apresentados, incluindo a nota 04 do bloco de DaC sobre testes automatizados e CI-CD para detecções.

2. Anatomia da Supply Chain de Software

A cadeia que entrega software à produção se compõe de quatro estoques de confiança, e cada um deles é uma fronteira onde o controle de segurança costuma ser mais fraco que o valor protegido. A lista abaixo descreve cada elo e o porquê do seu apelo ao adversário.

  • Dependências: bibliotecas open source dos registries npm, PyPI e Maven entram no build por resolução automática, e ataques de typosquatting, dependency confusion e version tag maliciosa exploram justamente a automação que ninguém revisa. O caso do pacote event-stream e os surtos recorrentes de pacotes maliciosos em npm e PyPI mostram que o elo mais fraco é a confiança transativa.
  • Pessoas e contas de mantenedor: a reputação de quem mantém o projeto é parte da cadeia de confiança, e o sequestro de conta de mantenedor vale tanto quanto o comprometimento de servidor. Token de mantenedor exposto em repositório público ou sessão sequestrada transforma a publicação de release em vetor de distribuição.
  • Runners: as máquinas que executam os jobs de build têm acesso a segredos, a redes internas e, no caso de runners self-hosted, ao cache de execuções anteriores. Workflows disparados por pull request em runners self-hosted combinam código não confiável com credencial confiável na mesma shell, que é a definição de incidente latente.
  • Segredos: tokens de deploy, credenciais de cloud e chaves de assinatura ficam injetados como variáveis de ambiente no runtime do job, visíveis para qualquer etapa que resolva imprimi-las ou enviá-las para fora. Um único step com echo mal colocado, ou com curl apontando para domínio do atacante, esvazia o cofre inteiro.
  • Artefatos: o binário ou a imagem que sai do build é a materialização final da cadeia, protegida por assinatura digital que confere autenticidade de origem, e não integridade de conteúdo. Quando o próprio build está comprometido, a assinatura legítima lava o artefato malicioso, como SolarWinds e 3CX demonstraram em escala.

O princípio de defesa que organiza esses quatro elos é a segmentação de confiança: código de origem externa nunca roda com segredo de produção acessível, runner de PR é efêmero e sem rede interna, segredo de job tem escopo mínimo e curto prazo, e artefato carrega proveniência verificável, como attestations no padrão SLSA e assinatura com sigstore. A ausência de qualquer um desses quatro pilares define exatamente onde a caça da seção 6 precisa começar.

3. Incidentes Paradigmáticos e Lições

SolarWinds (2020) permanece o caso de referência de comprometimento de build: o adversário habitou o ambiente de compilação da empresa, injetou o backdoor SUNBURST no processo de build do produto Orion e fez a própria vítima assinar e distribuir o malware como atualização oficial para cerca de dezoito mil organizações. A lição estrutural é que o controle de fronteira não enxerga esse ataque, porque o compromisso está dentro do processo legítimo, e a defesa real é telemetria do build, controle rigoroso do ambiente de compilação e validação comportamental do artefato entregue.

XZ Utils (2024) é a lição oposta, de comprometimento social e de empacotamento: o operador manteve o projeto por anos construindo reputação, implantou o backdoor CVE-2024-3094 em artefatos de distribuição via camadas de teste ofuscadas que só se ativavam no build de pacote, e o alvo era o sshd de sistemas que ligavam liblzma ao systemd. A detecção não veio de ferramenta de segurança, e sim de engenharia observante que notou latência anômala no sshd, o que valida o princípio do capítulo 15 de que baseline de comportamento, inclusive de performance, é superfície de detecção.

3CX (2023) demonstra o efeito cascata: atacantes afiliados a operação norte-coreana comprometeram a infraestrutura da própria empresa e injetaram carga no instalador assinado do desktop app, atingindo organizações que já haviam sido vítimas do software de trading comprometido no elo anterior. A cadeia de confiança quebrada em dois níveis mostra que o hunting de supply chain precisa olhar para o supplier do supplier, e que a resposta a incidente de terceiro deve reavaliar todos os artefatos assinados pelo fornecedor comprometido, e não apenas o produto afetado.

Casos complementares fecham o quadro: o Codecov (2021) vazou credenciais de CI através de script de upload comprometido, e a proliferação de ações de marketplace comprometidas, como o caso amplamente explorado em 2025 com a ação tj-actions/changed-files entregando segredos de runner para logs públicos, mostra que o vetor preferido do momento é a dependência de pipeline, e não mais a dependência de biblioteca.

A comparação estruturada desses casos evidencia que cada incidente quebrou um elo diferente, o que reforça a necessidade de telemetria em toda a cadeia em vez de controle único. A tabela abaixo resume o elo comprometido e o controle que mais teria reduzido o impacto em cada caso.

Caso Elo comprometido Vetor de entrada Controle decisivo
SolarWinds Ambiente de build do fornecedor intrusão prolongada no build system telemetria de build e proveniência do artefato
XZ Utils Empacotamento upstream engenharia social do mantenedor baseline comportamental do serviço em produção
3CX Instalador assinado de terceiro comprometimento interno do fornecedor reavaliação de artefatos assinados pós-incidente
Codecov Script de upload do CI modificação do uploader rotação de segredos expostos a runners
tj-actions (2025) Ação de pipeline de terceiros tag movida para commit malicioso pin de ação por hash de commit

4. TTPs de Pipeline Poisoning

O envenenamento de pipeline tem um repertório técnico próprio, com ATT&CK mapeável e assinaturas distintas da exploração de endpoint. A tabela abaixo consolida as seis famílias operacionais que o hunter deve dominar.

TTP ATT&CK Assinatura típica
Dependência comprometida T1195.001 egress do runner para domínio novo durante install, release fora do padrão do maintainer
Comprometimento de build e artefato T1195.002 build executado por identidade ou runner fora do padrão, alteração de script de build
Abuso de runner self-hosted T1078, T1059 job de fork PR rodando em runner com acesso à rede interna
Exfiltração de segredo T1552, T1041, T1567.002 segredos em log, POST para webhook ou domínio não aprovado na janela do job
Tag tampering e release manipulada T1565.001 movimentação ou recriação de tag, force push em branch de release
Persistência em workflow T1053.003, T1078 workflow com schedule criado fora de PR revisado

O padrão transversal dessas famílias é o abuso do mecanismo legítimo de entrega, e é por isso que a detecção por assinatura de payload falha sistematicamente nesse domínio. O que distingue o uso legítimo do malicioso não é o comando, e sim o contexto: quem disparou, de qual runner, para qual destino de rede, em qual momento do ciclo de release e com qual aprovação. Toda consulta da seção 6 é construída sobre esse princípio de contexto.

Vale registrar que essas famílias não são mutuamente exclusivas e se combinam em campanhas reais com economia de esforço: o comprometimento de uma ação de marketplace (T1195.001) entrega imediatamente o acesso a runner (T1078), que expõe segredos (T1552), que financiam ou viabilizam o comprometimento de artefato (T1195.002). O hunting que trata cada família isoladamente enxerga o sintoma; o que encadeia eventos por identidade e por janela temporal enxerga a operação.

5. Telemetria e Hunting na Esteira de CI-CD

A telemetria de supply chain se organiza em quatro planos que precisam convergir no mesmo SIEM, porque a correlação entre eles é o que distingue incidente de ruído. O plano de auditoria do forge entrega o GitHub Audit Log (com streaming nativo para SIEM nas edições empresariais) e o GitLab com audit events, cobrindo ações como git.clone e git.push, mudanças de permissão em repositório, criação e alteração de workflows, solicitação de personal access token e resolução de alertas de secret scanning. O plano de execução entrega os logs de runner, com nome do job, workflow, step, duração e identidade disparadora. O plano de rede entrega o egress do pool de runners via proxy, que é a única fonte confiável de destino de conexão. O plano de integridade entrega o registro de artefatos com hash, assinatura e attestations.

Plano Fonte principal Pergunta de caça
Auditoria do forge GitHub Audit Log, GitLab audit events Quem alterou workflow, permissão ou tag, e fora de qual esteira
Execução Logs de runner Qual step executou, com qual segredo acessível e disparada por quem
Rede Proxy do pool de runners Para onde o job se conectou e se o destino está no baseline
Integridade Registry, sigstore, attestations SLSA O artefato em produção corresponde ao build aprovado

A heurística de alto valor nasce do cruzamento de planos, e não de qualquer plano isolado. Job cujo autor é conta externa, executado em runner com acesso interno, conectando-se a domínio fora do baseline na janela do build é uma sentença, ainda que nenhum dos quatro sinais isolados passe o limiar de alerta. A nota 04 do capítulo 02 fornece a disciplina de avaliação de fonte, e a consulta da seção 6 implementa o cruzamento.

6. Exemplo de Caça: Exfiltração de Segredos em Pipeline

A caça de exfiltração de segredo começa pelo plano de rede, porque o segredo só interessa ao adversário quando sai da esteira. A consulta abaixo, em SPL, cruza o egress do pool de runners com o inventário de jobs e destaca destinos fora do baseline na janela de execução.

index=proxy src_subnet="10.42.0.0/16"
| lookup runners_cidr.csv src AS src OUTPUT job_id, workflow, repositorio
| lookup dominios_aprovados.csv dest_domain OUTPUT aprovado
| where isnull(aprovado) AND job_id != ""
| stats sum(bytes_out) AS bytes_enviados, dc(dest_domain) AS dominios,
        values(dest_domain) AS destinos
  BY job_id, workflow, repositorio, src
| where bytes_enviados > 10000 OR dominios >= 1
| sort - bytes_enviados

A segunda etapa desce ao plano de execução e ao próprio repositório, com duas verificações complementares. A varredura de workflows que combinam o gatilho de pull request com execução em runner privilegiado localiza o padrão de abuso de runner, e a inspeção dos steps que referenciam segredos junto de comandos de rede localiza o padrão de escoamento direto, como no exemplo abaixo, que é a assinatura textual do incidente antes dele acontecer.

# Workflows com gatilho de PR que rodam código do fork
grep -rlE 'pull_request_target|github\.event\.pull_request\.head' \
  .github/workflows/ | sort

# Steps que combinam segredo com chamada de rede no mesmo bloco
grep -rnE '(curl|wget|Invoke-WebRequest).*(secrets\.|TOKEN|KEY|PASSWORD)' \
  .github/workflows/ | grep -v 'actions/' | sort

A varredura textual do repositório encontra o padrão, e a detecção permanente do mesmo padrão em runtime fica com uma regra Sigma que observa a criação de processos nos runners. A regra abaixo cruza o binário de rede com a presença de nomes de segredo na linha de comando, e é um exemplo direto de caça promovida a detecção.

title: Post de segredos de CI para destino externo
id: 7f3c1a2b-9e21-4d10-9c6e-5a1b2c3d4e5f
status: experimental
description: Step de pipeline referencia variavel de segredo em comando de rede
logsource:
  category: process_creation
  product: linux
detection:
  selection_cmd:
    Image|endswith: /curl
  selection_secret:
    CommandLine|contains:
      - AWS_SECRET_ACCESS_KEY
      - GITHUB_TOKEN
      - SLACK_WEBHOOK
  condition: selection_cmd and selection_secret
tags:
  - attack.t1552
  - attack.t1041

O terceiro plano da mesma caça é o histórico de auditoria do forge, buscando alterações em workflows e tags fora da janela de release aprovada. Alterações de workflow por identidade fora da lista de mantenedores, criação de tag de release sem PR associado e force push em branch protegida com bypass são os três eventos que, combinados com o egress anômalo da primeira consulta, convertem a suspeita em caso investigativo com linha do tempo completa. A verificação de hipótese segue o padrão do capítulo 07: para cada candidato, confirmar a identidade disparadora no audit log, o segredo acessível no job e a natureza do destino de rede antes de classificar.

A consulta abaixo exemplifica a varredura no SPL sobre o audit log do GitHub, com a ressalva de que o nome exato das ações varia por edição e versão da plataforma, cabendo ao time mapear as strings do seu ambiente.

sourcetype="github:audit" (action="workflow*" OR action="protected_branch*" OR action="repo.access")
| eval hora = strftime(_time, "%H")
| stats values(action) AS acoes, dc(repo.name) AS repositorios,
        earliest(_time) AS primeiro, latest(_time) AS ultimo
  BY actor, hora
| where repositorios >= 3 OR match(acoes, "protected_branch")
| sort - repositorios

O cruzamento final confronta cada candidata com a lista de mantenedores autorizados, com a janela de release aprovada e com o histórico de atividade da mesma identidade. Falsos positivos previsíveis vêm dos bots legítimos de manutenção, como dependabot e renovate, e por isso a exclusão por identidade de automação documentada é parte da caça, e não um improviso. Encontrada a alteração suspeita, o caminho de resposta segue a ordem inversa da cadeia: revogar o segredo acessado, invalidar o artefato publicado no período, auditar os builds da mesma runner e só então remover a modificação do repositório, porque a ordem contrária alerta o adversário.

7. Erros Comuns e Pontos de Atenção

  • Tratar CI como ambiente de confiança: a esteira tem as credenciais mais valiosas da organização e executa código de fora, e a ausência de telemetria de runner no SIEM é o equivalente a não logar o controlador de domínio.
  • Confiar na assinatura do artefato como prova de integridade: assinatura valida origem do build, e o incidente SolarWinds é precisamente o caso de assinatura legítima sobre build comprometido; a integridade exige proveniência de build, com attestations SLSA.
  • Caçar apenas no código e ignorar o runtime: revisão de PR e scan estático são necessários, mas insuficientes; o egress de runner e o audit log capturam o que passou pela revisão disfarçado de código benigno.
  • Compartilhar runners entre confianças: runner self-hosted reaproveitado entre repositórios públicos e internos permite a contaminação por cache e por workspace, e a segmentação por nível de confiança é pré-requisito de qualquer caça sensata.
  • Encerrar a resposta no ponto errado: o incidente de supply chain termina em rotação de segredos acessados pelo job comprometido e revogação de artefatos, e não apenas em deletar o workflow malicioso; o raio de explosão é calculado pelo inventário de segredos do runner.
  • Subestimar ações de terceiros no marketplace: ações de pipeline são dependências executáveis com update automático, e pinar versão por hash de commit é o controle mínimo que a telemetria assume como baseline.
  • Assumir que segredos de organização estão isolados: segredos herdados por todos os repositórios de uma organização transformam um repositório experimental em cofre acessível, e a revisão periódica de escopo é controle ativo, e não documentação.
  • Ignorar o egress das ações de terceiros: ações executam no runner com a mesma rede do build, e a ausência de telemetria de proxy cobrindo o pool de runners é ponto cego institucionalizado que nenhuma revisão de código compensa.

O ponto de atenção final é o efeito espelho do problema: a biblioteca inteira opera detecção como código, e o repositório de regras Sigma ou as pipelines de deploy do capítulo 18 são exatamente o ativo que esta nota ensina a proteger. Um hunter que aplica esta caça ao próprio pipeline de detecção está executando contra-inteligência no sentido do capítulo 13, porque o adversário que domina o pipeline de detecção apaga a visão de todo o ambiente.

8. Integração com o Restante da Biblioteca

Dentro do capítulo 26, esta nota fecha o ciclo da aplicação cloud-native: a nota 05 fornece a telemetria de cloud onde os runners rodam e para onde os segredos apontam, a nota 06 cobre o runtime dos containers produzidos pela esteira, e a nota 08 completa o quadro com o SaaS, incluindo o próprio GitHub e o Slack por onde a evidência e o alerta transitam. O capítulo 21 contribui na vertente de monitoramento de superfície de terceiros, essencial para o supplier do supplier.

No plano transversal, o capítulo 18 é a vítima e o beneficiário simultâneo, porque sua esteira de detecção como código deve aplicar os controles aqui descritos, e a ponte hunting-para-deteção do capítulo 18 (ADS framework e hunting-to-detection bridge) é o destino natural das consultas desta nota que se mostrarem estáveis. Os controles SIM do capítulo 15 usam os incidentes da seção 3 como material de emulação em purple team, validando as detecções antes que o incidente real chegue, e o controle INT.3 conecta o tema ao compartilhamento de inteligência, já que indicadores de campanhas de supply chain circulam rápido entre ISACs.