flawopen.com/Incidents/solarwinds-sunburst-build-compromise-december-2020
SUNBURST: quando o pipeline de build era a vulnerabilidade
O SUNSPOT alterou o código-fonte do Orion no build e inseriu o SUNBURST em atualizações assinadas. A assinatura provava a origem, não a integridade.
Pense num chaveiro de confiança que envia kits de manutenção lacrados e carimbados para milhares de prédios. Alguém invade a fábrica onde os kits são montados e acrescenta uma pecinha extra em cada um antes de o lacre e o carimbo serem aplicados. Todos os prédios recebem um kit que realmente vem do chaveiro e o instalam. O lacre nunca foi rompido, porque a adulteração aconteceu antes de lacrar.
Conceitos Centrais e Termos
SUNSPOT- O implante no servidor de build analisado pela CrowdStrike. Ele vigiava o MSBuild.exe compilando o Orion e substituía um arquivo-fonte pela versão com backdoor enquanto durava o build.
SUNBURST- O backdoor compilado em SolarWinds.Orion.Core.BusinessLayer.dll. Ficava inativo por até duas semanas e depois contatava a infraestrutura do atacante via HTTP.
Assinatura de código- Uma assinatura criptográfica que mostra que um binário veio de quem detém a chave. Ela não diz nada sobre se o build que o gerou foi adulterado.
Build reproduzível- Um build que gera saída idêntica bit a bit a partir do mesmo código-fonte, para que builders independentes possam conferir os resultados uns dos outros.
CWE-506- Código malicioso embutido. Aqui ele foi inserido durante o próprio build do fornecedor, não no repositório de código-fonte.
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-506 CWE-829
- D3-OTF Filtragem de tráfego de saída — A restrição de rede de saída deste guia limita os destinos que o serviço ou host pode alcançar.
Linha do Tempo do Incidente
Os atacantes acessam o ambiente da SolarWinds; em 12 de setembro injetam código de teste num build do Orion para confirmar que o método funciona.
O SUNBURST é compilado nos builds do Orion por meio do SUNSPOT.
A SolarWinds começa a distribuir hotfixes do Orion que, sem que ela saiba, contêm o SUNBURST; entre as versões afetadas estão 2019.4 HF5 e 2020.2.
Os atacantes removem o SUNSPOT do ambiente de build.
A FireEye publica sua análise do SUNBURST e a CISA emite a Emergency Directive 21-01, mandando os órgãos federais desconectarem o Orion.
Fluxo de Ataque Passo a Paso
O servidor de build é comprometido
Os atacantes obtiveram acesso ao ambiente de build da SolarWinds e instalaram o SUNSPOT no servidor que compilava o Orion.
Um arquivo-fonte é trocado no meio do build
Quando o SUNSPOT via o MSBuild.exe compilando a solução do Orion, substituía InventoryManager.cs por uma versão com backdoor e restaurava o original após a compilação.
A chave legítima assina o resultado
O SolarWinds.Orion.Core.BusinessLayer.dll compilado passava pela etapa normal de assinatura, então a DLL com backdoor tinha uma assinatura válida da SolarWinds.
Os clientes instalam uma atualização confiável
Menos de 18 mil clientes instalaram atualizações afetadas. Depois, os atacantes escolheram um grupo bem menor de vítimas para invasões posteriores.
Código-Fonte: Vulnerável vs. Seguro
C# ilustrativo, não é o pipeline da SolarWinds. O job vulnerável confia num único servidor de build de longa duração e assina tudo o que ele produz, exatamente o que o SUNSPOT explorou. O gate reforçado exige dois builds do mesmo commit aprovado em builders provisionados do zero e administrados separadamente, compara seus digests SHA-256 em tempo constante e se recusa a assinar se houver qualquer diferença. Um implante num builder passa a gerar divergência em vez de uma release assinada; só falha se o atacante controlar os dois builders, por isso eles não podem compartilhar credenciais nem imagens.
using System;
using System.Diagnostics;
public static class ReleasePipeline
{
// As compilações usam a cópia de trabalho compartilhada e gravável em um servidor e assinam
// qualquer resultado. Também assinam alterações feitas na árvore durante a compilação.
public static void BuildAndSign(string project, string outputDll)
{
using var build = Process.Start("msbuild.exe", $"\"{project}\" /p:Configuration=Release");
build!.WaitForExit();
if (build.ExitCode != 0)
throw new InvalidOperationException("build failed");
Signer.Sign(outputDll); // HSM-backed signing service client
}
}using System;
using System.IO;
using System.Security.Cryptography;
public static class ReleaseGate
{
// Dois compiladores isolados compilam o mesmo commit fixado em checkouts novos e somente leitura,
// com /p:Deterministic=true. A etapa assina somente resultados idênticos.
public static void VerifyAndSign(string builderAOutput, string builderBOutput,
string builtCommit, string approvedCommit)
{
if (!string.Equals(builtCommit, approvedCommit, StringComparison.Ordinal))
throw new InvalidOperationException("build is not from the approved commit");
byte[] a = SHA256.HashData(File.ReadAllBytes(builderAOutput));
byte[] b = SHA256.HashData(File.ReadAllBytes(builderBOutput));
if (!CryptographicOperations.FixedTimeEquals(a, b))
throw new InvalidOperationException("independent builds differ; refusing to sign");
Signer.Sign(builderAOutput, Convert.ToHexString(a)); // digest is logged with the signature
}
}Lista de Verificação de Segurança para Engenharia
- ✓Proteja os runners de CI como produção: eles guardam código-fonte, segredos e chaves de assinatura e geram o que os clientes executam, então merecem o isolamento, o controle de acesso e os logs de auditoria de um banco de dados de produção.
- ✓Compile as releases duas vezes, em builders provisionados do zero e administrados separadamente, com compilação determinística, e reprove a release se os digests dos artefatos forem diferentes.
- ✓Não trate uma assinatura válida como prova de segurança; ela prova a origem, e a origem só é tão confiável quanto o ambiente que guardava a chave.
- ✓Restrinja o egress de agentes privilegiados. O SUNBURST precisava alcançar seus servidores de comando e controle, então ferramentas de monitoramento que falam com qualquer host da internet devem ser uma decisão explícita e revisada.
- ✓Dimensione os privilégios de cada agente de fornecedor pelo que um atacante ganharia se ele fosse totalmente comprometido, não pelo que é conveniente implantar.
- ✓Mantenha telemetria que o atacante não consiga editar: logs fora do host e somente de acréscimo é que permitem reconstruir depois uma invasão de meses.
Fontes
- Mandiant (FireEye) — atacante altamente evasivo usa a cadeia de suprimentos da SolarWinds para comprometer várias vítimas no mundo com o backdoor SUNBURST
- CrowdStrike — SUNSPOT: um implante no processo de build
- CISA — Emergency Directive 21-01: mitigar o comprometimento do código do SolarWinds Orion
- O backdoor do XZ Utils: o ataque à cadeia de suprimentos que levou três anos
- Shai-Hulud: o worm do npm que se publicava sozinho