flawopen.com/Incidents/solarwinds-sunburst-build-compromise-december-2020
SUNBURST : attaque de la chaîne de compilation
SUNSPOT a modifié le code source d’Orion au build et intégré SUNBURST aux mises à jour signées. La signature prouvait l’origine, pas l’intégrité.
Imaginez un serrurier de confiance qui envoie des kits d'entretien scellés et tamponnés à des milliers d'immeubles. Quelqu'un s'introduit dans l'usine où l'on assemble les kits et ajoute une petite pièce à chacun avant la pose du scellé et du tampon. Chaque immeuble reçoit un kit qui vient réellement du serrurier et l'installe. Le scellé n'a jamais été brisé, car la falsification a eu lieu avant.
Concepts Clés et Termes
SUNSPOT- L'implant du serveur de build analysé par CrowdStrike. Il guettait MSBuild.exe compilant Orion et remplaçait un fichier source par la version piégée le temps de la compilation.
SUNBURST- La porte dérobée compilée dans SolarWinds.Orion.Core.BusinessLayer.dll. Elle restait dormante jusqu'à deux semaines, puis contactait l'infrastructure de l'attaquant en HTTP.
Signature de code- Une signature cryptographique montrant qu'un binaire vient du détenteur de la clé. Elle ne dit rien de l'éventuelle falsification du build qui l'a produit.
Build reproductible- Un build qui produit une sortie identique au bit près à partir des mêmes sources, pour que des builders indépendants puissent vérifier les résultats des autres.
CWE-506- Code malveillant intégré. Ici, il a été inséré pendant le build de l'éditeur lui-même, pas dans le dépôt de sources.
Correspondances de référentiels
- Référence CWE pour la faiblesse décrite dans ce guide : CWE-506 CWE-829
- D3-OTF Filtrage du trafic sortant — La restriction du trafic sortant décrite dans ce guide limite les destinations accessibles au service ou à l’hôte.
Chronologie de l'Incident
Les attaquants accèdent à l'environnement de SolarWinds ; le 12 septembre, ils injectent du code de test dans un build d'Orion pour vérifier que la méthode fonctionne.
SUNBURST est compilé dans les builds d'Orion via SUNSPOT.
SolarWinds commence à diffuser des correctifs d'Orion qui contiennent SUNBURST à son insu ; parmi les versions touchées figurent 2019.4 HF5 et 2020.2.
Les attaquants retirent SUNSPOT de l'environnement de build.
FireEye publie son analyse de SUNBURST et la CISA émet l'Emergency Directive 21-01, qui ordonne aux agences fédérales de déconnecter Orion.
Déroulement de l'Attaque Étape par Étape
Le serveur de build est compromis
Les attaquants ont obtenu un accès à l'environnement de build de SolarWinds et installé SUNSPOT sur le serveur qui compilait Orion.
Un fichier source est remplacé en pleine compilation
Quand SUNSPOT voyait MSBuild.exe compiler la solution Orion, il remplaçait InventoryManager.cs par une version piégée, puis restaurait l'original après la compilation.
La vraie clé signe le résultat
Le SolarWinds.Orion.Core.BusinessLayer.dll compilé passait par l'étape de signature habituelle : la DLL piégée portait donc une signature SolarWinds valide.
Les clients installent une mise à jour de confiance
Moins de 18 000 clients ont installé des mises à jour touchées. Les attaquants ont ensuite choisi un groupe de victimes bien plus restreint pour des intrusions ultérieures.
Code Source : Vulnérable vs Sécurisé
C# illustratif, pas la chaîne de SolarWinds. Le job vulnérable fait confiance à un unique serveur de build de longue durée et signe tout ce qu'il produit, précisément ce qu'a exploité SUNSPOT. La barrière durcie exige deux builds du même commit approuvé sur des builders fraîchement provisionnés et administrés séparément, compare leurs empreintes SHA-256 en temps constant et refuse de signer à la moindre différence. Un implant sur un builder produit alors un écart au lieu d'une version signée ; cela n'échoue que si l'attaquant contrôle les deux builders, d'où l'interdiction de partager identifiants ou images.
using System;
using System.Diagnostics;
public static class ReleasePipeline
{
// Les compilations utilisent la copie de travail partagée et modifiable d’un serveur, puis signent
// tout résultat. Toute modification de l’arborescence pendant la compilation est aussi signée.
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
{
// Deux compilateurs isolés compilent le même commit épinglé depuis des checkouts neufs en lecture seule,
// avec /p:Deterministic=true. Le contrôle ne signe que des résultats identiques.
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
}
}Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Protégez les runners de CI comme la production : ils détiennent sources, secrets et clés de signature et produisent ce que les clients exécutent ; ils méritent l'isolement, le contrôle d'accès et la journalisation d'audit d'une base de production.
- ✓Compilez chaque version deux fois, sur des builders fraîchement provisionnés et administrés séparément, en compilation déterministe, et bloquez la publication si les empreintes des artefacts diffèrent.
- ✓Ne prenez pas une signature valide pour une preuve de sûreté ; elle prouve la provenance, qui ne vaut que ce que vaut l'environnement détenant la clé.
- ✓Restreignez le trafic sortant des agents privilégiés. SUNBURST devait joindre ses serveurs de commande et de contrôle : un outil de supervision capable de parler à n'importe quel hôte d'Internet doit être une décision explicite et revue.
- ✓Dimensionnez les privilèges de chaque agent d'éditeur selon ce qu'un attaquant gagnerait en le compromettant entièrement, pas selon la facilité de déploiement.
- ✓Conservez une télémétrie que l'attaquant ne peut pas modifier : des journaux hors hôte, en ajout seul, permettent de reconstituer après coup une intrusion de plusieurs mois.
Sources
- Mandiant (FireEye) — un attaquant très furtif exploite la chaîne d'approvisionnement de SolarWinds pour compromettre de nombreuses victimes avec la porte dérobée SUNBURST
- CrowdStrike — SUNSPOT : un implant dans le processus de build
- CISA — Emergency Directive 21-01 : atténuer la compromission du code de SolarWinds Orion
- La porte dérobée XZ Utils : l'attaque de la chaîne d'approvisionnement qui a pris trois ans
- Shai-Hulud : le ver npm qui se publiait lui-même