Solarwinds hack : quelles conséquences pour la sécurité de l’access management ?

En décembre 2020, FireEye découvre une attaque sophistiquée de grande envergure impactant le gouvernement américain et de nombreuses entreprises privées. Elle a conduit à la fuite de messages depuis Microsoft 365 (nouveau nom d’Office 365). Début janvier il a été reporté que 3000 boîtes du ministère de la justice américain ont été compromises de cette manière.

L’un des vecteurs de cette attaque remonte au logiciel Orion de la société SolarWinds. Cette référence au soleil dans la raison sociale de la société a donné naissance à de nombreux noms pour l’attaque et ses différents vecteurs : Solorigate, SolarStorm, Sunburst, etc. Afin de ne pas incriminer un éditeur qui a été une victime, on parlera dans cet article d’attaque Sunburst, même si le terme fait référence non à l’attaque dans son ensemble, mais à un de ses vecteurs.

L’attaque est complexe, composée d’une longue chaîne de compromissions menant au final à de l’usurpation d’identité impliquant les solutions de gestion des accès de Microsoft : ADFS et Azure AD.

On peut se poser la question : est-ce un problème circonscrit à Microsoft ou l’usurpation aurait-elle été possible avec d’autres solutions d’authentification ?

Avant de répondre à la question, on commence par expliquer comment les boîtes ont été piratées pour remonter progressivement au début de l’attaque. On précise qu’il s’agit d’une interprétation de notre part en fonction des informations rendues publiques à la date de publication.

L’authentification Microsoft 365

Pour se connecter à la messagerie de leur victime, les attaquants n’avaient pas connaissance de son mot de passe, car ils n’en avaient pas besoin.
Il leur a en effet suffi de créer un jeton d’identité frauduleux contenant l’identité de leur cible et de le présenter à Microsoft 365 qui l’a accepté.
Pour bien comprendre, partons du fonctionnement normal (ici simplifié pour des raisons de clarté).
Pour accéder à M365, un utilisateur est d’abord dirigé vers Azure AD pour authentification. Azure AD génère alors un jeton avec l’identité de l’utilisateur et le signe avec sa clé privée. L’utilisateur est renvoyé vers M365 avec ce jeton (on schématise beaucoup ici – des mécanismes sont en œuvre pour sécuriser ce transfert).
Microsoft 365 contrôle alors la validité du jeton en en vérifiant la signature avec la clé publique d’Azure AD. Il finit par en extraire l’identité de l’utilisateur et lui donne accès au service.

Authentification Microsoft 365

 

Accéder à la messagerie Microsoft 365 d’autrui

Les attaquants ont pu s’insérer en amont de la cinématique d’authentification et faire en sorte qu’Azure AD génère un jeton sans que l’utilisateur soit authentifié. Ce vrai-faux jeton est alors légitiment accepté par Microsoft 365.
Pour cela, deux moyens ont été employés
• Pour les organisations disposant d’un ADFS, une clé privée a été volée sur le réseau local. C’est le scénario cauchemar où l’attaque devient alors imparable et indétectable.
• En l’absence d’un ADFS, les attaquants ont obtenu un accès administrateur à la console Azure AD et ont ajouté une fédération vers un serveur d’authentification à eux. Ça fonctionne tout aussi bien, mais c’est plus voyant puisque les modifications de configuration sont visibles par les administrateurs

Usurper les identités avec la clé privée ADFS

Les organisations déploient un fournisseur d’identité ADFS afin que les utilisateurs accèdent à Microsoft 365 par une authentification de l’Active Directory interne. Azure AD ne réalise plus les authentifications en direct mais est configuré pour rediriger les demandes d’authentification vers ADFS, qui vérifie le mot de passe sur l’AD. Le résultat est ensuite remonté à Azure AD sous forme d’un jeton qui sert de base pour la génération d’un autre jeton qui est finalement transmis à M365.

Authentification M365 auprès de l’AD avec ADFS

Avec Sunburst, l’attaquant a exploité une faiblesse du protocole SAML, dans sa configuration standard en authentification cloud. Cette cinématique indique que le jeton est directement présenté par l’utilisateur, qui y a donc accès et peut le manipuler.
En arrivant à dérober la clé privée d’ADFS, l’attaquant crée facilement de toutes pièces un faux jeton SAML. Il y place en particulier l’identité de la boîte dont il souhaite lire les messages. Il signe ensuite le jeton avec la clé volée et le présente à Azure AD (on schématise évidemment un peu). Azure AD faisant confiance à ADFS, le jeton est accepté. L’attaquant est reconnu comme sa victime. Azure AD génère un jeton final valide, toujours avec l’identité de la victime.
Ce jeton est transmis à Microsoft 365 qui doit commencer par le valider. Et comme il a été signé avec la clé légitime d’Azure AD, le jeton passe tous les contrôles de Microsoft 365 bien qu’il soit falsifié. Il donne donc accès à la boîte de la victime et l’attaquant peut récupérer tranquillement toutes les informations souhaitées.

Accès à M365 après vol de la clé privée ADFS

L’attaque est rendue possible par le vol de la clé privée, qui s’opère en se connectant sur le serveur en tant qu’administrateur. Une fois cet accès obtenu, la procédure est ensuite très simple, car la clé est récupérée par une simple commande d’administration.
La condition, c’est donc d’être sur le réseau local et de disposer d’un accès administrateur.
Avant d’expliquer comment les attaquants ont procédé pour l’obtenir, on décrit la seconde méthode d’accès à une boîte, par courtage d’identité, et pour lequel un accès administrateur a tout aussi été nécessaire.

Passer pour un autre par courtage d’identité (identity brokering)

Le principe de l’identité brokering, c’est le chaînage des serveurs d’identité. En cinématique normale, une application délègue son authentification à un fournisseur d’identité (abrégé en « IdP »). Dans notre cas, Office 365 demande à Azure AD (qui joue le rôle d’IdP) de réaliser l’authentification pour lui. Puis Azure AD demande son mot de passe à l’utilisateur et le vérifie.
On peut constituer une chaîne en configurant Azure AD pour qu’il ne demande pas le mot de passe lui-même, mais qu’il s’adresse à un autre fournisseur d’identité, qui va le faire auprès de son annuaire propre (différent donc d’Azure AD). Comme on l’a vu précédemment, c’est exactement comme ça que cela fonctionne quand Azure AD s’adresse à ADFS.
Comme une relation de confiance a été instaurée entre le fournisseur délégué et Azure AD, ce dernier accepte l’authentification et génère un jeton à destination de Microsoft 365, en se basant sur les informations transmises par le serveur ayant authentifié l’utilisateur.
L’important, c’est évidemment la relation de confiance, qui est matérialisée par des échanges d’informations et vérifiée par des certificats et des secrets.
Si l’attaquant réussi à obtenir des droits d’administrateur Azure AD, il alors tout loisir d’y définir une relation de confiance avec un serveur d’identité qu’il installe pour l’occasion et qu’il contrôle donc entièrement. Il y intègre l’identité de sa victime, avec un mot de passe qu’il définit lui même.
Il lui suffit alors de se connecter à Microsoft 365, qui l’envoie dans un premier temps à Azure AD. Il saisit un login qui déclenche la redirection vers son serveur d’identité. Il s’authentifie avec le mot de passe qu’il a lui même attribué et le serveur génère un jeton contenant l’identité de la victime.
Grâce à la relation de confiance établie, Azure AD accepte le jeton et génère à son tour un jeton d’accès à Microsoft, qui contient l’identité prélevée dans le jeton initial, c’est à dire celle de la victime.
Microsoft 365 reçoit alors un jeton authentique, généré par Azure AD, qui passe donc tous les contrôles, mais qui contient une identité usurpée. On a donc bien un vrai-faux jeton.

Ajout d’une délégation d’authentification frauduleuse

La différence avec le vol de la clé privée, c’est que la configuration mise en place est visible des administrateurs légitimes qui pourront s’apercevoir que leur système a été compromis. Mais comme la mise en place d’une fédération est un événement très rare, il n’est pas étonnant que personne n’ait rien vu.
Pour que cette attaque fonctionne, il faut quand même disposer du mot de passe d’un administrateur Azure AD. Dans le cas Sunburst, il a été récupéré depuis le réseau local, sur lequel l’attaquant s’est introduit.

Obtenir un accès administrateur

Pour les deux types d’attaque observés, un accès administrateur a été indispensable et a été obtenu depuis le réseau local.
Dans le cas du vol de clé privée, l’attaquant s’est connecté au serveur ADFS et a pu avoir un accès privilégié en volant un ticket Kerberos. Dans le cas du courtage d’identité, il a vraisemblablement récupéré un mot de passe administrateur en clair, qui a suffi à se connecter à Azure AD qui n’était pas protégé par MFA (authentification à facteurs multiples).
Le point commun, c’est que l’accès administrateur a été volé depuis le réseau local, une fois que l’accès y a été obtenu. En ayant le contrôle d’une machine Windows sur le réseau local, il existe plusieurs techniques pour récupérer soit le mot de passe en clair, soit un ticket ou un hash directement réutilisables. Elles se basent sur le fait que Windows conserve ces informations en mémoire pour pouvoir les réutiliser.
Ce n’est évidemment pas à la portée de tout le monde, mais les attaquants en question n’étaient pas tout le monde !
Une fois parvenus sur le réseau local, les attaquants ont utilisé des mécanismes de mouvement latéral et d’évasion pour arriver à leurs fins.

S’introduire dans le réseau local

Pour arriver sur le réseau local, les attaquants ont commencé par s’attaquer à SolarWinds, qui édite la plateforme Orion de gestion de système d’information. Ils ont réussi à introduire un malware dans le code du logiciel (par un moyen non encore élucidé à ce jour), qui a ensuite été distribué à tous les clients de la solution lors d’une mise à jour automatique.
Une fois la mise à jour installée, le malware qu’elle intègre s’active et contacte le centre de contrôle et de commande des attaquants (C&C) qui ont pu manœuvrer à distance. Ils ont pour cela simulé des requêtes DNS. Un second malware a ensuite été installé pour mettre en sommeil leur accès initial et le préserver en cas de découverte.

Compromission par contamination des mises à jour logicielles

Des conséquences qui auraient pu être dévastatrices

En ce début janvier 2021, on ne connaît pas encore l’étendue exacte de l’attaque attribuée à des acteurs gouvernementaux russes. Les conséquences apparaissent pour l’instant limitées mais c’est vraisemblablement parce que l’objectif était concentré sur le gouvernement américain.
On estime en effet à 18 000 organisations ayant installé le composant compromis d’Orion. En ces temps de ransomware, si la motivation des attaquants avait été pécuniaire, les dégâts auraient été autrement plus importants. Ils se sont concentrés sur leur objectif final, en se contentant par exemple de dérober des éléments utiles dans ce contexte (outils offensifs de FireEye, code source Microsoft et Cisco), alors qu’ils auraient pu se faire de l’argent en pillant le patrimoine informatique des nombreuses entreprises compromises.

Une bonne nouvelle : Microsoft 365 et Azure AD ont un niveau de sécurité élevé

L’attaque éveille évidemment de nombreuses interrogations sur la vulnérabilité de tous les systèmes d’information, mais on va ici se concentrer sur ce qu’elle nous apprend sur les risques induis dans le domaine de la gestion des accès.
La première constatation que l’on peut faire, c’est l’ampleur des efforts qu’il a fallu déployer pour arriver au final à ouvrir quelques milliers de boîtes aux lettres dans le cloud.
Si l’on suit la chronologie, SolarWinds a été compromis en septembre 2019, les versions modifiées d’Orion datent de mars 2020 et l’attaque a été détectée début décembre 2020 lorsque les acteurs malveillants ont dérobé des outils d’attaque sophistiqués de FireEye en utilisant la même porte d’entrée. On peut évidemment penser que ces outils allaient servir à s’en prendre à des cibles gouvernementales protégées.
On est donc devant une attaque de longue haleine, impliquant de nombreuses étapes pour voler des messages électroniques sans se faire remarquer.
La première chose qu’on peut noter, c’est que les deux méthodes utilisées reposent sur des prérequis
• le vol de la clé privée SAML impose que l’organisation visée délègue l’authentification à un ADFS qui utilise une cinématique où le jeton transite par le navigateur de l’utilisateur
• l’authentification directe à la console d’administration Azure AD aurait été plus compliquée si une authentification à multiples facteurs (MFA) avait été déployée
On remarque ensuite que pour accéder aux boîtes aux lettres, les attaquants n’ont pas utilisé de méthodes plus directes de compromission des crédentiels, comme la force brute ou le password spraying au niveau de la page de login Azure AD.
Il faut aussi dire qu’il est probable que l’objectif des attaquants n’était pas uniquement d’accéder aux boîtes aux lettres, mais bien d’atteindre d’autres ressources plus confidentielles sur les réseaux locaux. Le piratage de la messagerie n’était peut-être qu’opportuniste.
Toutefois, avec les mesures de protection d’Azure AD, les méthodes de type force brute, password spraying ou spear phishing demandent beaucoup d’énergie pour chaque boîte. En les employant, il aurait été difficile d’atteindre les centaines de milliers de boîtes compromises sans être détecté.
Ce genre de méthode reste cependant valide pour des attaques très ciblées. Elles ont d’ailleurs été effectivement employées par les attaquants, afin de pénétrer dans le réseau local de certaines victimes lorsque le vecteur Sunburst n’était pas possible. Ce sont alors des accès à distance (de type remote desktop) qui ont été visés.

L’accès administrateur a donné plus de possibilités sur les serveurs internes que sur Office 365

Le point clé de l’attaque a été d’obtenir des accès administrateur. Les attaquants l’ont eu, en fonction des organisations ciblées, pour les serveurs ADFS internes ou pour l’interface d’administration Azure AD.
La compromission du serveur ADFS interne a permis de falsifier des jetons SAML avec une empreinte réduite. Microsoft indique que le vol de la clé privée ADFS se fait par une requête LDAP sur l’Active Directory (entrée CryptoPolicy de l’OU ADFS). Il faudrait donc surveiller les accès à cette entrée, ce qui n’était pas fait pour les organisations compromises et ce qui n’est fait par quasiment personne.
La probabilité est donc forte que le vol se fasse subrepticement. La suite des opérations (falsification des jetons) est totalement indétectable. Une fois la clé privée acquise, l’attaque devient indécelable.
La surveillance de l’origine des connexions à AzureAD n’aurait rien donné, puisque les attaquants avaient la possibilité d’agir depuis le réseau local.
De son côté, la corruption de la configuration d’Azure AD laisse des traces visibles dans la configuration, qui auraient pu être remarquées par des administrateurs avertis. L’attaque peut donc être découverte à tout moment.

L’access management de Microsoft a été compromis, qu’en aurait-il été pour les autres solutions ?

L’attaque Sunburst a ciblé ADFS et Azure AD, du fait du rôle central que ces systèmes ont pour accéder à Microsoft 365. On peut se poser la question de savoir si les conséquences auraient été différentes si les attaquants étaient tombés sur un IdP (fournisseur d’identité) différent, ou encore si la fédération avec Azure AD avaient été réalisée par OpenID Connect au lieu de SAML.
Trois situations vont ici être étudiées, prises dans un contexte général, sans entrer dans le détail de chaque implémentation :
• La prise de contrôle du serveur hébergeant un IdP
• L’accès administrateur à la console d’administration d’un IdP
• Le vol de la clé privée d’un IdP OpenID Connect/OAuth 2

La prise de contrôle du serveur hébergeant le fournisseur d’identités est catastrophique

Les attaquants ont réussi à prendre le contrôle de l’ADFS interne. Mais les mêmes techniques (ou des techniques similaires) auraient pu être employées pour s’en prendre à un autre fournisseur d’identité, toujours avec des droits d’administrateur sur le serveur.
L’impact en aurait été tout aussi important.
Ils auraient eu accès à la configuration pour la modifier, ce qui est traité dans le chapitre qui suit.
Ils auraient très certainement pu voler toutes les clés privées, avec les mêmes conséquences en SAML et avec des conséquences en OIDC/OAuth 2 que l’on aborde plus bas.
Ils auraient eu un accès à l’annuaire, soit en consultant les logs qui donnent la liste des logins, soit en récupérant les crédentiels de connexion dans l’IdP (par déchiffrement du mot de passe ou par un autre moyen).
Mais ils auraient aussi pu modifier le code source de l’IdP et rendre l’usurpation d’identité difficilement détectable. Il suffit pour cela d’ajouter du code parasite qui fasse que lorsqu’un login inventé est saisi, l’authentification soit inconditionnellement validée et que les jetons soient générés avec une identité usurpée passée par exemple dans le champ de mot de passe.

Altération du code source d’un IdP

La modification du code source est souvent simple à réaliser, à partir du moment où l’on dispose d’un accès en écriture au système de fichiers.
Certaines solutions libres sont développées en Perl. Le code est donc en clair, et les modifications sont prises en compte à la volée, sans même avoir à relancer le service.
La plupart des IdP sont en Java. Il nous est arrivé de récupérer les fichiers .class, de les décompiler, d’altérer le code, puis de les recompiler. Il faut ensuite redéployer la webapp, ce qui se fait aisément. Mais c’est parfois plus simple. Avec Shibboleth, nous avons modifié le comportement de l’IdP et fait de l’emprunt d’identité par un simple ajout de code Java dans les JSP mises à disposition pour personnaliser la page d’authentification.
On pouvait s’y attendre, la compromission de serveur est critique.

Protéger l’accès à la console d’administration de l’IdP

Lorsque l’organisation visée ne disposait pas d’ADFS, les attaquants ont pu utiliser un mot de passe Active Directory récupéré sur le réseau local pour se connecter à l’interface d’administration Azure AD. Cela a été possible car la plupart du temps l’annuaire dans le cloud est synchronisé avec l’AD interne.
Si la solution d’access management est installée localement, l’attaquant a montré qu’il avait les moyens de prendre le contrôle du serveur et de modifier la configuration directement dans les fichiers, voire d’aller plus loin en retouchant le code source pour laisser moins de traces. Il n’a donc pas tellement d’intérêt à se connecter à la console d’administration.
En revanche si l’access management est dans le cloud, disposer du mot de passe permettant l’accès à la console d’administration est le moyen le plus efficace de le compromettre, sous réserve que la MFA ne soit pas déployée (ou qu’elle soit facilement contournable).
Or si l’accès à la console d’administration s’appuie sur Active Directory, l’attaquant pourra appliquer les mêmes méthodes que pour la compromission Sunburst et récupérer un mot de passe administrateur qui fonctionnera pour Azure AD.
L’étape suivante consiste alors comme pour Azure AD en la mise en place d’une délégation vers un IdP pirate.
Il faut ensuite faire en sorte qu’il puisse utiliser cette délégation parasite sans se faire remarquer, c’est-à-dire sans quelle soit visible par les utilisateurs finaux qui doivent continuer à s’authentifier directement.
Les écrans d’authentification ne doivent donc pas être altérés, tout en laissant la possibilité pour l’attaquant de déclencher une dérivation vers son IdP pirate.
En fonction des solutions de gestion des accès et en fonction de la manière dont elles sont utilisées, ce sera plus ou moins facile.
Si l’authentification se fait en deux pages (le login puis le mot de passe), il est probable que personne ne se rendra compte de rien. En saisissant un login dans le domaine de son IdP, le système provoquera par défaut le routage souhaité. Se leur côté, les utilisateurs normaux continuant à s’authentifier dans leur domaine, il leur sera toujours demandé leur mot de passe dans le même second écran.
Si l’authentification se fait dans un unique formulaire (login et mot de passe dans la même page), il sera encore souvent possible d’ajouter dans la page en question un bouton invisible, dont l’emplacement ne sera connu que des attaquants, et qui déclenchera la bascule vers leur IdP.
Il sera donc souvent possible de réaliser des attaques similaires à celles qui ont été observées avec Sunburst, sans éveiller les soupçons.

OpenID Connect et OAuth 2 sont-ils moins vulnérables ?

Il n’est jamais inutile de rappeler les différences entre OpenID Connect et OAuth 2, ce qu’on va faire ici de manière très sommaire.
Les deux protocoles n’ont pas le même champ d’application. L’un est destiné aux applications et l’autre aux API. Ils sont cependant souvent utilisés de manière conjointe, d’abord OpenID Connect pour authentifier les utilisateurs, puis OAuth 2 lorsque l’application a besoin d’accéder aux données des utilisateurs.
OpenID Connect fournit un jeton d’identité pour l’authentification des applications web. OAuth 2 génère un jeton d’accès qui ouvre l’accès aux services web (au travers d’une app web ou d’une app native) et qui peut transmettre l’identité de l’utilisateur final.
Pour schématiser, le jeton d’identité OpenID Connect est utilisé directement par l’application qui l’obtient (souvent exécutée sur un serveur), alors que le jeton d’accès OAuth 2 sert de manière indirecte : il est récupéré par une application qui le présente à une API.
Si un attaquant vole la clé privée de l’IdP, a-t-il les mêmes possibilité en OIDC/OAuth 2 que ce qu’on a vu pour SAML ?
En d’autres termes, est-il possible de générer un jeton d’identité ou un jeton d’accès et de le présenter pour obtenir un accès indu ?

OpenID Connect comble les insuffisances de sécurité de SAML

OpenID Connect et son jeton d’identité n’ont vraiment de sens que pour les applications appelées confidentielles, c’est-à-dire hébergées sur un serveur. L’autre type d’applications est appelé client public, il s’agit essentiellement des SPA (Single Page Application s’exécutant dans un navigateur) et des app mobiles.
Un client public ne peut que difficilement s’appuyer sur les identités pour sa sécurité propre. Une SPA sécurisée est un oxymore, puisqu’elle s’exécute dans un environnement (le navigateur) où la sécurité ne peut être garantie. Ce qu’il faut protéger dans le cadre d’une SPA, c’est l’accès au backend, qui contient les données.
Pour en revenir aux applications confidentielles, avec OpenID Connect, le jeton d’identité est échangé directement entre serveurs, sans jamais passer par le navigateur (du moins si la cinématique obsolète implicit est bien interdite). Un attaquant n’a donc pas de vecteur naturel pour présenter un jeton falsifié.
On remarquera que le risque le plus important couvert par ce dispositif, c’est le vol du jeton dans le navigateur plutôt que la falsification de jeton qui est plus compliquée à réaliser.
OpenID Connect a donc capitalisé sur l’expérience SAML pour offrir une cinématique plus sécurisée. On notera tout de même que SAML a prévu un mode de fonctionnement similaire d’échange de jetons entre serveurs, appelé artifact binding, mais qui n’est pas très répandu.

OpenID Connect protège le jeton

OAuth 2 doit être mis en œuvre correctement dans les cas d’usage où il s’applique

Avec OAuth 2, la situation ressemble parfois à celle qui a permis de présenter des faux jetons SAML.

On rappelle que le protocole réalise l’autorisation à une API (un service web) appelée par une application.

Si l’API est conçue pour n’être appelée que par des applications s’exécutant sur des serveurs (applications confidentielles), les bonnes pratiques conseillent que l’accès à l’API ne soit possible que par les applications dûment autorisées. La connexion à l’API ne doit être possible soit qu’après une authentification de l’application, soit qu’après des protections au niveau du réseau, soit par les deux mesures lorsque c’est possible. Un attaquant devra donc défaire ces dispositifs pour réussir à présenter un jeton falsifié.

Or de plus en plus les API sont publiées sur internet, pour être appelées depuis un navigateur (SPA) ou depuis une app mobile.

Il n’est alors plus possible d’identifier le client qui se connecte et de restreindre efficacement l’accès au service web. Un attaquant a toute latitude pour présenter le jeton qu’il veut.

Le jeton va-t-il être accepté comme c’est le cas avec SAML ? Cela dépend de la manière dont il est validé. La norme OAuth 2 ne donne pas de détails sur les mécanismes à mettre en place, laissant le choix de réaliser une vérification de signature ou une vérification par introspection, qui consiste pour l’API à se connecter au fournisseur d’identités pour présenter lui le jeton et contrôler sa validité.

On comprend tout de suite l’intérêt de cette dernière manière de procéder, puisqu’un jeton falsifié par un attaquant ne sera pas accepté, alors qu’il le sera par une API qui fait une simple vérification de signature.

D’ailleurs les bonnes pratiques OAuth 2 dictent que le jeton doit être de type opaque (illisible donc non signé) avec une validation par introspection.

Si ces recommandations sont suivies, le vol de la clé privée est neutralisé.

On notera que le jeton opaque reste vulnérable au vol et doit toujours être proprement protégé dans l’application. C’est faisable pour les applications mobiles, mais virtuellement impossible pour les SPA.

Quelques réflexions suscitées par l’attaque

L’attaque Sunburst est très inhabituelle de par son ampleur et sa complexité. Elle donne à réfléchir sur ce qu’un acteur gouvernemental est capable d’accomplir, avec tout ce que cela implique en ressources et en persévérance.
Elle pose donc des questions sur des sujets de sécurité dont la probabilité d’occurrence était jusque récemment jugée minime.

La difficulté de protéger les secrets

Une grande partie de la sécurité des systèmes repose sur l’existence et la protection de secrets garantissant l’authentification et la confidentialité des échanges : mots de passe, clés privées, etc.
Ces secrets sont saisis par des opérateurs (authentification d’un visiteur auprès d’un site internet par exemple), comme ils sont aussi utilisé directement par des systèmes : connexion à une base de données, chiffrement des échanges entre modules, etc. Dans ce cas, le secret doit être stocké quelque part et être soigneusement protégé : au mieux conservé dans des coffre-forts (keystores) et au pire chiffré dans des fichiers de configuration.
Mais comme il doit être récupéré de manière automatique, un acteur ayant pris le contrôle du système avec des droits élevés pourra la plupart du temps suivre le chemin utilisé par les applications pour obtenir ou utiliser le secret.
Car ce que l’application peut accomplir, un acteur externe disposant des mêmes droits pourra habituellement le faire aussi. Par exemple le chiffrement des mots de passe dans le fichier de configuration est utile. Mais comme l’application doit avoir accès à la clé pour les déchiffrer, un acteur ayant le contrôle du serveur pourra faire la même chose et déchiffrer les mots de passe.
Il faut considérer qu’un acteur malveillant ayant pris le contrôle d’une machine pourra faire exactement les mêmes choses que ce que les applications qu’elle héberge sont capables de faire : disposer du mot de passe pour se connecter à un système protégé (base de données, annuaire, API, etc.), signer des documents ou chiffrer des fichiers.
Il est cependant toujours possible de protéger les clés privées de signature et de chiffrement et éviter qu’elles ne soient volées comme elles l’ont été avec Sunburst. Les HSM sont des équipements prévus à cet effet : ils stockent les clés, les utilisent pour réaliser eux-mêmes les opérations de cryptogaphie et font en sorte qu’il soit impossible d’en extraire les clés. Mais ce sont des systèmes coûteux. Le budget mensuel d’un HSM AWS à Paris est d’environ 1300€. Ca protège les clés, mais pas les mots de passe. Un mot de passe de base de données chiffré par HSM et stocké dans un fichier de configuration est vulnérable devant un attaquant qui a obtenu assez de droits pour accéder à l’API de l’HSM.
Cela ne veut évidemment pas dire qu’il faille abandonner toute velléité de protéger les secrets. Chiffrer les mots de passe dans un fichier de configuration est toujours nécessaire pour éviter qu’ils ne soient exploités si le fichier devait fuiter (dépôt accidentel dans un repository Git par exemple).

Et l’authentification MFA alors ?

L’authentification forte, c’est le réflexe automatique de l’ingénieur sécurité débutant, qui professe que le mot de passe va mourir dans l’année et préconise que toutes les authentifications se fassent par biométrie, clé sécurisée ou après confirmation sur un téléphone mobile. Le monde sera alors sauvé.
Evidemment la réalité est bien plus contrastée ; la MFA est souvent souhaitable mais sa généralisation est parfois impossible et dans certains cas contre-productive. Elle doit être utilisée à bon escient. Mais ce n’est pas le propos ici de ratiociner sur les moyens de mettre en place une authentification parfaite, équilibre fragile entre la sécurité et la facilité d’utilisation pour tous.
L’attaque Sunburst évoque tout de même quelques réflexions sur l’authentification MFA.
La première, c’est que dans sa variante ADFS, Sunburst met en échec tous les mécanismes de sécurisation de l’authentification. La falsification des jetons SAML contourne complètement la phase même d’authentification qui devient totalement inutile.
A l’inverse, l’authentification forte est réaffirmée dans son rôle de protection des consoles d’administration cloud. Si elle avait été mise en place, la récupération du mot de passe administrateur depuis le réseau local n’aurait pas suffi à se connecter à Azure AD pour en modifier la configuration.
Finalement, on peut se dire que les mêmes techniques qui ont permis de voler les clés privées ADFS peuvent être mises en jeu pour déjouer l’authentification forte, en volant les secrets qui y sont liés. On se souvient que RSA a dû remplacer tous les token SecurID après le vol d’une clé racine au début des années 2010.
D’ailleurs, les attaquants Sunburst s’en sont effectivement pris aux secrets d’une authentification MFA. Des enquêteurs de Volexity ont déterminé que des boîtes aux lettres avaient été accédées par OWA (Outlook Web Access) alors même qu’elles étaient protégées par un dispositif Duo. Les attaquants avaient réussi à voler une clé sur le serveur OWA leur permettant de générer un cookie confirmant faussement une authentification forte inexistante lors de la connexion à la boîte.

Les bonnes pratiques de sécurité sont primordiales

Il est bien sûr trop tôt pour tirer les leçons de cette attaque d’envergure inédite, alors que de nouvelles révélations tombent encore tous les jours.
Elle montre cependant qu’un acteur motivé peut arriver à ses fins dès lors qu’il en a le temps. Les organisations compromises sont réputées pour être bien protégées. Elles ont certainement dû passer avec succès des dizaines de tests d’intrusion. Mais un test d’intrusion ne dure que quelques jours, alors que les acteurs derrière Sunburst ont disposé de nombreux mois pour compromettre des systèmes d’information entiers.
Sunburst a aussi mis en lumière la fragilité des mécanismes d’authentification, lorsque toutes les précautions ne sont pas prises.
On observe par exemple une mode du jeton JWT chez certains développeurs, qui l’utilisent pour sécuriser des applications de type SPA, en conjonction avec OAuth 2 (mais pas toujours).
Or les dernières innovations ne sont pas toujours les plus adaptées. Dans de nombreux cas, l’utilisation d’OAuth 2 pour protéger un backend abaisse le niveau de sécurité. Sunburst montre qu’il est possible (même si c’est difficile) de falsifier un JWT. Ce qui est relativement facile de faire, c’est de voler un jeton existant pour le rejouer. Il est donc important en OAuth 2 de bien appliquer les préconisations de sécurisation.
Il ne faut cependant pas perdre de vue qu’en sécurité, il nous arrive fréquemment de barricader une porte déjà difficilement accessible tout en laissant une fenêtre ouverte. Ainsi dans notre exemple, un jeton d’accès dans une application SPA se fait voler relativement facilement, alors qu’un cookie est bien mieux protégé. On aura donc intérêt – si le contexte le permet – de s’appuyer sur les sessions HTTP, certes anciennes et moins à la mode, mais plus sécurisées, car elles permettent de protéger les jetons OAuth 2 (si on en a besoin) dans un serveur.

Auteur : Marc (Directeur technique)

Leave A Comment

Solarwinds hack : quelles conséquences pour la sécurité de l’access management ?

En décembre 2020, FireEye découvre une attaque sophistiquée de grande envergure impactant le gouvernement américain et de nombreuses entreprises privées. Elle a conduit à la fuite de messages depuis Microsoft 365 (nouveau nom d’Office 365). Début janvier il a été reporté que 3000 boîtes du ministère de la justice américain ont été compromises de cette manière.

L’un des vecteurs de cette attaque remonte au logiciel Orion de la société SolarWinds. Cette référence au soleil dans la raison sociale de la société a donné naissance à de nombreux noms pour l’attaque et ses différents vecteurs : Solorigate, SolarStorm, Sunburst, etc. Afin de ne pas incriminer un éditeur qui a été une victime, on parlera dans cet article d’attaque Sunburst, même si le terme fait référence non à l’attaque dans son ensemble, mais à un de ses vecteurs.

L’attaque est complexe, composée d’une longue chaîne de compromissions menant au final à de l’usurpation d’identité impliquant les solutions de gestion des accès de Microsoft : ADFS et Azure AD.

On peut se poser la question : est-ce un problème circonscrit à Microsoft ou l’usurpation aurait-elle été possible avec d’autres solutions d’authentification ?

Avant de répondre à la question, on commence par expliquer comment les boîtes ont été piratées pour remonter progressivement au début de l’attaque. On précise qu’il s’agit d’une interprétation de notre part en fonction des informations rendues publiques à la date de publication.

L’authentification Microsoft 365

Pour se connecter à la messagerie de leur victime, les attaquants n’avaient pas connaissance de son mot de passe, car ils n’en avaient pas besoin.
Il leur a en effet suffi de créer un jeton d’identité frauduleux contenant l’identité de leur cible et de le présenter à Microsoft 365 qui l’a accepté.
Pour bien comprendre, partons du fonctionnement normal (ici simplifié pour des raisons de clarté).
Pour accéder à M365, un utilisateur est d’abord dirigé vers Azure AD pour authentification. Azure AD génère alors un jeton avec l’identité de l’utilisateur et le signe avec sa clé privée. L’utilisateur est renvoyé vers M365 avec ce jeton (on schématise beaucoup ici – des mécanismes sont en œuvre pour sécuriser ce transfert).
Microsoft 365 contrôle alors la validité du jeton en en vérifiant la signature avec la clé publique d’Azure AD. Il finit par en extraire l’identité de l’utilisateur et lui donne accès au service.

Authentification Microsoft 365

 

Accéder à la messagerie Microsoft 365 d’autrui

Les attaquants ont pu s’insérer en amont de la cinématique d’authentification et faire en sorte qu’Azure AD génère un jeton sans que l’utilisateur soit authentifié. Ce vrai-faux jeton est alors légitiment accepté par Microsoft 365.
Pour cela, deux moyens ont été employés
• Pour les organisations disposant d’un ADFS, une clé privée a été volée sur le réseau local. C’est le scénario cauchemar où l’attaque devient alors imparable et indétectable.
• En l’absence d’un ADFS, les attaquants ont obtenu un accès administrateur à la console Azure AD et ont ajouté une fédération vers un serveur d’authentification à eux. Ça fonctionne tout aussi bien, mais c’est plus voyant puisque les modifications de configuration sont visibles par les administrateurs

Usurper les identités avec la clé privée ADFS

Les organisations déploient un fournisseur d’identité ADFS afin que les utilisateurs accèdent à Microsoft 365 par une authentification de l’Active Directory interne. Azure AD ne réalise plus les authentifications en direct mais est configuré pour rediriger les demandes d’authentification vers ADFS, qui vérifie le mot de passe sur l’AD. Le résultat est ensuite remonté à Azure AD sous forme d’un jeton qui sert de base pour la génération d’un autre jeton qui est finalement transmis à M365.

Authentification M365 auprès de l’AD avec ADFS

Avec Sunburst, l’attaquant a exploité une faiblesse du protocole SAML, dans sa configuration standard en authentification cloud. Cette cinématique indique que le jeton est directement présenté par l’utilisateur, qui y a donc accès et peut le manipuler.
En arrivant à dérober la clé privée d’ADFS, l’attaquant crée facilement de toutes pièces un faux jeton SAML. Il y place en particulier l’identité de la boîte dont il souhaite lire les messages. Il signe ensuite le jeton avec la clé volée et le présente à Azure AD (on schématise évidemment un peu). Azure AD faisant confiance à ADFS, le jeton est accepté. L’attaquant est reconnu comme sa victime. Azure AD génère un jeton final valide, toujours avec l’identité de la victime.
Ce jeton est transmis à Microsoft 365 qui doit commencer par le valider. Et comme il a été signé avec la clé légitime d’Azure AD, le jeton passe tous les contrôles de Microsoft 365 bien qu’il soit falsifié. Il donne donc accès à la boîte de la victime et l’attaquant peut récupérer tranquillement toutes les informations souhaitées.

Accès à M365 après vol de la clé privée ADFS

L’attaque est rendue possible par le vol de la clé privée, qui s’opère en se connectant sur le serveur en tant qu’administrateur. Une fois cet accès obtenu, la procédure est ensuite très simple, car la clé est récupérée par une simple commande d’administration.
La condition, c’est donc d’être sur le réseau local et de disposer d’un accès administrateur.
Avant d’expliquer comment les attaquants ont procédé pour l’obtenir, on décrit la seconde méthode d’accès à une boîte, par courtage d’identité, et pour lequel un accès administrateur a tout aussi été nécessaire.

Passer pour un autre par courtage d’identité (identity brokering)

Le principe de l’identité brokering, c’est le chaînage des serveurs d’identité. En cinématique normale, une application délègue son authentification à un fournisseur d’identité (abrégé en « IdP »). Dans notre cas, Office 365 demande à Azure AD (qui joue le rôle d’IdP) de réaliser l’authentification pour lui. Puis Azure AD demande son mot de passe à l’utilisateur et le vérifie.
On peut constituer une chaîne en configurant Azure AD pour qu’il ne demande pas le mot de passe lui-même, mais qu’il s’adresse à un autre fournisseur d’identité, qui va le faire auprès de son annuaire propre (différent donc d’Azure AD). Comme on l’a vu précédemment, c’est exactement comme ça que cela fonctionne quand Azure AD s’adresse à ADFS.
Comme une relation de confiance a été instaurée entre le fournisseur délégué et Azure AD, ce dernier accepte l’authentification et génère un jeton à destination de Microsoft 365, en se basant sur les informations transmises par le serveur ayant authentifié l’utilisateur.
L’important, c’est évidemment la relation de confiance, qui est matérialisée par des échanges d’informations et vérifiée par des certificats et des secrets.
Si l’attaquant réussi à obtenir des droits d’administrateur Azure AD, il alors tout loisir d’y définir une relation de confiance avec un serveur d’identité qu’il installe pour l’occasion et qu’il contrôle donc entièrement. Il y intègre l’identité de sa victime, avec un mot de passe qu’il définit lui même.
Il lui suffit alors de se connecter à Microsoft 365, qui l’envoie dans un premier temps à Azure AD. Il saisit un login qui déclenche la redirection vers son serveur d’identité. Il s’authentifie avec le mot de passe qu’il a lui même attribué et le serveur génère un jeton contenant l’identité de la victime.
Grâce à la relation de confiance établie, Azure AD accepte le jeton et génère à son tour un jeton d’accès à Microsoft, qui contient l’identité prélevée dans le jeton initial, c’est à dire celle de la victime.
Microsoft 365 reçoit alors un jeton authentique, généré par Azure AD, qui passe donc tous les contrôles, mais qui contient une identité usurpée. On a donc bien un vrai-faux jeton.

Ajout d’une délégation d’authentification frauduleuse

La différence avec le vol de la clé privée, c’est que la configuration mise en place est visible des administrateurs légitimes qui pourront s’apercevoir que leur système a été compromis. Mais comme la mise en place d’une fédération est un événement très rare, il n’est pas étonnant que personne n’ait rien vu.
Pour que cette attaque fonctionne, il faut quand même disposer du mot de passe d’un administrateur Azure AD. Dans le cas Sunburst, il a été récupéré depuis le réseau local, sur lequel l’attaquant s’est introduit.

Obtenir un accès administrateur

Pour les deux types d’attaque observés, un accès administrateur a été indispensable et a été obtenu depuis le réseau local.
Dans le cas du vol de clé privée, l’attaquant s’est connecté au serveur ADFS et a pu avoir un accès privilégié en volant un ticket Kerberos. Dans le cas du courtage d’identité, il a vraisemblablement récupéré un mot de passe administrateur en clair, qui a suffi à se connecter à Azure AD qui n’était pas protégé par MFA (authentification à facteurs multiples).
Le point commun, c’est que l’accès administrateur a été volé depuis le réseau local, une fois que l’accès y a été obtenu. En ayant le contrôle d’une machine Windows sur le réseau local, il existe plusieurs techniques pour récupérer soit le mot de passe en clair, soit un ticket ou un hash directement réutilisables. Elles se basent sur le fait que Windows conserve ces informations en mémoire pour pouvoir les réutiliser.
Ce n’est évidemment pas à la portée de tout le monde, mais les attaquants en question n’étaient pas tout le monde !
Une fois parvenus sur le réseau local, les attaquants ont utilisé des mécanismes de mouvement latéral et d’évasion pour arriver à leurs fins.

S’introduire dans le réseau local

Pour arriver sur le réseau local, les attaquants ont commencé par s’attaquer à SolarWinds, qui édite la plateforme Orion de gestion de système d’information. Ils ont réussi à introduire un malware dans le code du logiciel (par un moyen non encore élucidé à ce jour), qui a ensuite été distribué à tous les clients de la solution lors d’une mise à jour automatique.
Une fois la mise à jour installée, le malware qu’elle intègre s’active et contacte le centre de contrôle et de commande des attaquants (C&C) qui ont pu manœuvrer à distance. Ils ont pour cela simulé des requêtes DNS. Un second malware a ensuite été installé pour mettre en sommeil leur accès initial et le préserver en cas de découverte.

Compromission par contamination des mises à jour logicielles

Des conséquences qui auraient pu être dévastatrices

En ce début janvier 2021, on ne connaît pas encore l’étendue exacte de l’attaque attribuée à des acteurs gouvernementaux russes. Les conséquences apparaissent pour l’instant limitées mais c’est vraisemblablement parce que l’objectif était concentré sur le gouvernement américain.
On estime en effet à 18 000 organisations ayant installé le composant compromis d’Orion. En ces temps de ransomware, si la motivation des attaquants avait été pécuniaire, les dégâts auraient été autrement plus importants. Ils se sont concentrés sur leur objectif final, en se contentant par exemple de dérober des éléments utiles dans ce contexte (outils offensifs de FireEye, code source Microsoft et Cisco), alors qu’ils auraient pu se faire de l’argent en pillant le patrimoine informatique des nombreuses entreprises compromises.

Une bonne nouvelle : Microsoft 365 et Azure AD ont un niveau de sécurité élevé

L’attaque éveille évidemment de nombreuses interrogations sur la vulnérabilité de tous les systèmes d’information, mais on va ici se concentrer sur ce qu’elle nous apprend sur les risques induis dans le domaine de la gestion des accès.
La première constatation que l’on peut faire, c’est l’ampleur des efforts qu’il a fallu déployer pour arriver au final à ouvrir quelques milliers de boîtes aux lettres dans le cloud.
Si l’on suit la chronologie, SolarWinds a été compromis en septembre 2019, les versions modifiées d’Orion datent de mars 2020 et l’attaque a été détectée début décembre 2020 lorsque les acteurs malveillants ont dérobé des outils d’attaque sophistiqués de FireEye en utilisant la même porte d’entrée. On peut évidemment penser que ces outils allaient servir à s’en prendre à des cibles gouvernementales protégées.
On est donc devant une attaque de longue haleine, impliquant de nombreuses étapes pour voler des messages électroniques sans se faire remarquer.
La première chose qu’on peut noter, c’est que les deux méthodes utilisées reposent sur des prérequis
• le vol de la clé privée SAML impose que l’organisation visée délègue l’authentification à un ADFS qui utilise une cinématique où le jeton transite par le navigateur de l’utilisateur
• l’authentification directe à la console d’administration Azure AD aurait été plus compliquée si une authentification à multiples facteurs (MFA) avait été déployée
On remarque ensuite que pour accéder aux boîtes aux lettres, les attaquants n’ont pas utilisé de méthodes plus directes de compromission des crédentiels, comme la force brute ou le password spraying au niveau de la page de login Azure AD.
Il faut aussi dire qu’il est probable que l’objectif des attaquants n’était pas uniquement d’accéder aux boîtes aux lettres, mais bien d’atteindre d’autres ressources plus confidentielles sur les réseaux locaux. Le piratage de la messagerie n’était peut-être qu’opportuniste.
Toutefois, avec les mesures de protection d’Azure AD, les méthodes de type force brute, password spraying ou spear phishing demandent beaucoup d’énergie pour chaque boîte. En les employant, il aurait été difficile d’atteindre les centaines de milliers de boîtes compromises sans être détecté.
Ce genre de méthode reste cependant valide pour des attaques très ciblées. Elles ont d’ailleurs été effectivement employées par les attaquants, afin de pénétrer dans le réseau local de certaines victimes lorsque le vecteur Sunburst n’était pas possible. Ce sont alors des accès à distance (de type remote desktop) qui ont été visés.

L’accès administrateur a donné plus de possibilités sur les serveurs internes que sur Office 365

Le point clé de l’attaque a été d’obtenir des accès administrateur. Les attaquants l’ont eu, en fonction des organisations ciblées, pour les serveurs ADFS internes ou pour l’interface d’administration Azure AD.
La compromission du serveur ADFS interne a permis de falsifier des jetons SAML avec une empreinte réduite. Microsoft indique que le vol de la clé privée ADFS se fait par une requête LDAP sur l’Active Directory (entrée CryptoPolicy de l’OU ADFS). Il faudrait donc surveiller les accès à cette entrée, ce qui n’était pas fait pour les organisations compromises et ce qui n’est fait par quasiment personne.
La probabilité est donc forte que le vol se fasse subrepticement. La suite des opérations (falsification des jetons) est totalement indétectable. Une fois la clé privée acquise, l’attaque devient indécelable.
La surveillance de l’origine des connexions à AzureAD n’aurait rien donné, puisque les attaquants avaient la possibilité d’agir depuis le réseau local.
De son côté, la corruption de la configuration d’Azure AD laisse des traces visibles dans la configuration, qui auraient pu être remarquées par des administrateurs avertis. L’attaque peut donc être découverte à tout moment.

L’access management de Microsoft a été compromis, qu’en aurait-il été pour les autres solutions ?

L’attaque Sunburst a ciblé ADFS et Azure AD, du fait du rôle central que ces systèmes ont pour accéder à Microsoft 365. On peut se poser la question de savoir si les conséquences auraient été différentes si les attaquants étaient tombés sur un IdP (fournisseur d’identité) différent, ou encore si la fédération avec Azure AD avaient été réalisée par OpenID Connect au lieu de SAML.
Trois situations vont ici être étudiées, prises dans un contexte général, sans entrer dans le détail de chaque implémentation :
• La prise de contrôle du serveur hébergeant un IdP
• L’accès administrateur à la console d’administration d’un IdP
• Le vol de la clé privée d’un IdP OpenID Connect/OAuth 2

La prise de contrôle du serveur hébergeant le fournisseur d’identités est catastrophique

Les attaquants ont réussi à prendre le contrôle de l’ADFS interne. Mais les mêmes techniques (ou des techniques similaires) auraient pu être employées pour s’en prendre à un autre fournisseur d’identité, toujours avec des droits d’administrateur sur le serveur.
L’impact en aurait été tout aussi important.
Ils auraient eu accès à la configuration pour la modifier, ce qui est traité dans le chapitre qui suit.
Ils auraient très certainement pu voler toutes les clés privées, avec les mêmes conséquences en SAML et avec des conséquences en OIDC/OAuth 2 que l’on aborde plus bas.
Ils auraient eu un accès à l’annuaire, soit en consultant les logs qui donnent la liste des logins, soit en récupérant les crédentiels de connexion dans l’IdP (par déchiffrement du mot de passe ou par un autre moyen).
Mais ils auraient aussi pu modifier le code source de l’IdP et rendre l’usurpation d’identité difficilement détectable. Il suffit pour cela d’ajouter du code parasite qui fasse que lorsqu’un login inventé est saisi, l’authentification soit inconditionnellement validée et que les jetons soient générés avec une identité usurpée passée par exemple dans le champ de mot de passe.

Altération du code source d’un IdP

La modification du code source est souvent simple à réaliser, à partir du moment où l’on dispose d’un accès en écriture au système de fichiers.
Certaines solutions libres sont développées en Perl. Le code est donc en clair, et les modifications sont prises en compte à la volée, sans même avoir à relancer le service.
La plupart des IdP sont en Java. Il nous est arrivé de récupérer les fichiers .class, de les décompiler, d’altérer le code, puis de les recompiler. Il faut ensuite redéployer la webapp, ce qui se fait aisément. Mais c’est parfois plus simple. Avec Shibboleth, nous avons modifié le comportement de l’IdP et fait de l’emprunt d’identité par un simple ajout de code Java dans les JSP mises à disposition pour personnaliser la page d’authentification.
On pouvait s’y attendre, la compromission de serveur est critique.

Protéger l’accès à la console d’administration de l’IdP

Lorsque l’organisation visée ne disposait pas d’ADFS, les attaquants ont pu utiliser un mot de passe Active Directory récupéré sur le réseau local pour se connecter à l’interface d’administration Azure AD. Cela a été possible car la plupart du temps l’annuaire dans le cloud est synchronisé avec l’AD interne.
Si la solution d’access management est installée localement, l’attaquant a montré qu’il avait les moyens de prendre le contrôle du serveur et de modifier la configuration directement dans les fichiers, voire d’aller plus loin en retouchant le code source pour laisser moins de traces. Il n’a donc pas tellement d’intérêt à se connecter à la console d’administration.
En revanche si l’access management est dans le cloud, disposer du mot de passe permettant l’accès à la console d’administration est le moyen le plus efficace de le compromettre, sous réserve que la MFA ne soit pas déployée (ou qu’elle soit facilement contournable).
Or si l’accès à la console d’administration s’appuie sur Active Directory, l’attaquant pourra appliquer les mêmes méthodes que pour la compromission Sunburst et récupérer un mot de passe administrateur qui fonctionnera pour Azure AD.
L’étape suivante consiste alors comme pour Azure AD en la mise en place d’une délégation vers un IdP pirate.
Il faut ensuite faire en sorte qu’il puisse utiliser cette délégation parasite sans se faire remarquer, c’est-à-dire sans quelle soit visible par les utilisateurs finaux qui doivent continuer à s’authentifier directement.
Les écrans d’authentification ne doivent donc pas être altérés, tout en laissant la possibilité pour l’attaquant de déclencher une dérivation vers son IdP pirate.
En fonction des solutions de gestion des accès et en fonction de la manière dont elles sont utilisées, ce sera plus ou moins facile.
Si l’authentification se fait en deux pages (le login puis le mot de passe), il est probable que personne ne se rendra compte de rien. En saisissant un login dans le domaine de son IdP, le système provoquera par défaut le routage souhaité. Se leur côté, les utilisateurs normaux continuant à s’authentifier dans leur domaine, il leur sera toujours demandé leur mot de passe dans le même second écran.
Si l’authentification se fait dans un unique formulaire (login et mot de passe dans la même page), il sera encore souvent possible d’ajouter dans la page en question un bouton invisible, dont l’emplacement ne sera connu que des attaquants, et qui déclenchera la bascule vers leur IdP.
Il sera donc souvent possible de réaliser des attaques similaires à celles qui ont été observées avec Sunburst, sans éveiller les soupçons.

OpenID Connect et OAuth 2 sont-ils moins vulnérables ?

Il n’est jamais inutile de rappeler les différences entre OpenID Connect et OAuth 2, ce qu’on va faire ici de manière très sommaire.
Les deux protocoles n’ont pas le même champ d’application. L’un est destiné aux applications et l’autre aux API. Ils sont cependant souvent utilisés de manière conjointe, d’abord OpenID Connect pour authentifier les utilisateurs, puis OAuth 2 lorsque l’application a besoin d’accéder aux données des utilisateurs.
OpenID Connect fournit un jeton d’identité pour l’authentification des applications web. OAuth 2 génère un jeton d’accès qui ouvre l’accès aux services web (au travers d’une app web ou d’une app native) et qui peut transmettre l’identité de l’utilisateur final.
Pour schématiser, le jeton d’identité OpenID Connect est utilisé directement par l’application qui l’obtient (souvent exécutée sur un serveur), alors que le jeton d’accès OAuth 2 sert de manière indirecte : il est récupéré par une application qui le présente à une API.
Si un attaquant vole la clé privée de l’IdP, a-t-il les mêmes possibilité en OIDC/OAuth 2 que ce qu’on a vu pour SAML ?
En d’autres termes, est-il possible de générer un jeton d’identité ou un jeton d’accès et de le présenter pour obtenir un accès indu ?

OpenID Connect comble les insuffisances de sécurité de SAML

OpenID Connect et son jeton d’identité n’ont vraiment de sens que pour les applications appelées confidentielles, c’est-à-dire hébergées sur un serveur. L’autre type d’applications est appelé client public, il s’agit essentiellement des SPA (Single Page Application s’exécutant dans un navigateur) et des app mobiles.
Un client public ne peut que difficilement s’appuyer sur les identités pour sa sécurité propre. Une SPA sécurisée est un oxymore, puisqu’elle s’exécute dans un environnement (le navigateur) où la sécurité ne peut être garantie. Ce qu’il faut protéger dans le cadre d’une SPA, c’est l’accès au backend, qui contient les données.
Pour en revenir aux applications confidentielles, avec OpenID Connect, le jeton d’identité est échangé directement entre serveurs, sans jamais passer par le navigateur (du moins si la cinématique obsolète implicit est bien interdite). Un attaquant n’a donc pas de vecteur naturel pour présenter un jeton falsifié.
On remarquera que le risque le plus important couvert par ce dispositif, c’est le vol du jeton dans le navigateur plutôt que la falsification de jeton qui est plus compliquée à réaliser.
OpenID Connect a donc capitalisé sur l’expérience SAML pour offrir une cinématique plus sécurisée. On notera tout de même que SAML a prévu un mode de fonctionnement similaire d’échange de jetons entre serveurs, appelé artifact binding, mais qui n’est pas très répandu.

OpenID Connect protège le jeton

OAuth 2 doit être mis en œuvre correctement dans les cas d’usage où il s’applique

Avec OAuth 2, la situation ressemble parfois à celle qui a permis de présenter des faux jetons SAML.

On rappelle que le protocole réalise l’autorisation à une API (un service web) appelée par une application.

Si l’API est conçue pour n’être appelée que par des applications s’exécutant sur des serveurs (applications confidentielles), les bonnes pratiques conseillent que l’accès à l’API ne soit possible que par les applications dûment autorisées. La connexion à l’API ne doit être possible soit qu’après une authentification de l’application, soit qu’après des protections au niveau du réseau, soit par les deux mesures lorsque c’est possible. Un attaquant devra donc défaire ces dispositifs pour réussir à présenter un jeton falsifié.

Or de plus en plus les API sont publiées sur internet, pour être appelées depuis un navigateur (SPA) ou depuis une app mobile.

Il n’est alors plus possible d’identifier le client qui se connecte et de restreindre efficacement l’accès au service web. Un attaquant a toute latitude pour présenter le jeton qu’il veut.

Le jeton va-t-il être accepté comme c’est le cas avec SAML ? Cela dépend de la manière dont il est validé. La norme OAuth 2 ne donne pas de détails sur les mécanismes à mettre en place, laissant le choix de réaliser une vérification de signature ou une vérification par introspection, qui consiste pour l’API à se connecter au fournisseur d’identités pour présenter lui le jeton et contrôler sa validité.

On comprend tout de suite l’intérêt de cette dernière manière de procéder, puisqu’un jeton falsifié par un attaquant ne sera pas accepté, alors qu’il le sera par une API qui fait une simple vérification de signature.

D’ailleurs les bonnes pratiques OAuth 2 dictent que le jeton doit être de type opaque (illisible donc non signé) avec une validation par introspection.

Si ces recommandations sont suivies, le vol de la clé privée est neutralisé.

On notera que le jeton opaque reste vulnérable au vol et doit toujours être proprement protégé dans l’application. C’est faisable pour les applications mobiles, mais virtuellement impossible pour les SPA.

Quelques réflexions suscitées par l’attaque

L’attaque Sunburst est très inhabituelle de par son ampleur et sa complexité. Elle donne à réfléchir sur ce qu’un acteur gouvernemental est capable d’accomplir, avec tout ce que cela implique en ressources et en persévérance.
Elle pose donc des questions sur des sujets de sécurité dont la probabilité d’occurrence était jusque récemment jugée minime.

La difficulté de protéger les secrets

Une grande partie de la sécurité des systèmes repose sur l’existence et la protection de secrets garantissant l’authentification et la confidentialité des échanges : mots de passe, clés privées, etc.
Ces secrets sont saisis par des opérateurs (authentification d’un visiteur auprès d’un site internet par exemple), comme ils sont aussi utilisé directement par des systèmes : connexion à une base de données, chiffrement des échanges entre modules, etc. Dans ce cas, le secret doit être stocké quelque part et être soigneusement protégé : au mieux conservé dans des coffre-forts (keystores) et au pire chiffré dans des fichiers de configuration.
Mais comme il doit être récupéré de manière automatique, un acteur ayant pris le contrôle du système avec des droits élevés pourra la plupart du temps suivre le chemin utilisé par les applications pour obtenir ou utiliser le secret.
Car ce que l’application peut accomplir, un acteur externe disposant des mêmes droits pourra habituellement le faire aussi. Par exemple le chiffrement des mots de passe dans le fichier de configuration est utile. Mais comme l’application doit avoir accès à la clé pour les déchiffrer, un acteur ayant le contrôle du serveur pourra faire la même chose et déchiffrer les mots de passe.
Il faut considérer qu’un acteur malveillant ayant pris le contrôle d’une machine pourra faire exactement les mêmes choses que ce que les applications qu’elle héberge sont capables de faire : disposer du mot de passe pour se connecter à un système protégé (base de données, annuaire, API, etc.), signer des documents ou chiffrer des fichiers.
Il est cependant toujours possible de protéger les clés privées de signature et de chiffrement et éviter qu’elles ne soient volées comme elles l’ont été avec Sunburst. Les HSM sont des équipements prévus à cet effet : ils stockent les clés, les utilisent pour réaliser eux-mêmes les opérations de cryptogaphie et font en sorte qu’il soit impossible d’en extraire les clés. Mais ce sont des systèmes coûteux. Le budget mensuel d’un HSM AWS à Paris est d’environ 1300€. Ca protège les clés, mais pas les mots de passe. Un mot de passe de base de données chiffré par HSM et stocké dans un fichier de configuration est vulnérable devant un attaquant qui a obtenu assez de droits pour accéder à l’API de l’HSM.
Cela ne veut évidemment pas dire qu’il faille abandonner toute velléité de protéger les secrets. Chiffrer les mots de passe dans un fichier de configuration est toujours nécessaire pour éviter qu’ils ne soient exploités si le fichier devait fuiter (dépôt accidentel dans un repository Git par exemple).

Et l’authentification MFA alors ?

L’authentification forte, c’est le réflexe automatique de l’ingénieur sécurité débutant, qui professe que le mot de passe va mourir dans l’année et préconise que toutes les authentifications se fassent par biométrie, clé sécurisée ou après confirmation sur un téléphone mobile. Le monde sera alors sauvé.
Evidemment la réalité est bien plus contrastée ; la MFA est souvent souhaitable mais sa généralisation est parfois impossible et dans certains cas contre-productive. Elle doit être utilisée à bon escient. Mais ce n’est pas le propos ici de ratiociner sur les moyens de mettre en place une authentification parfaite, équilibre fragile entre la sécurité et la facilité d’utilisation pour tous.
L’attaque Sunburst évoque tout de même quelques réflexions sur l’authentification MFA.
La première, c’est que dans sa variante ADFS, Sunburst met en échec tous les mécanismes de sécurisation de l’authentification. La falsification des jetons SAML contourne complètement la phase même d’authentification qui devient totalement inutile.
A l’inverse, l’authentification forte est réaffirmée dans son rôle de protection des consoles d’administration cloud. Si elle avait été mise en place, la récupération du mot de passe administrateur depuis le réseau local n’aurait pas suffi à se connecter à Azure AD pour en modifier la configuration.
Finalement, on peut se dire que les mêmes techniques qui ont permis de voler les clés privées ADFS peuvent être mises en jeu pour déjouer l’authentification forte, en volant les secrets qui y sont liés. On se souvient que RSA a dû remplacer tous les token SecurID après le vol d’une clé racine au début des années 2010.
D’ailleurs, les attaquants Sunburst s’en sont effectivement pris aux secrets d’une authentification MFA. Des enquêteurs de Volexity ont déterminé que des boîtes aux lettres avaient été accédées par OWA (Outlook Web Access) alors même qu’elles étaient protégées par un dispositif Duo. Les attaquants avaient réussi à voler une clé sur le serveur OWA leur permettant de générer un cookie confirmant faussement une authentification forte inexistante lors de la connexion à la boîte.

Les bonnes pratiques de sécurité sont primordiales

Il est bien sûr trop tôt pour tirer les leçons de cette attaque d’envergure inédite, alors que de nouvelles révélations tombent encore tous les jours.
Elle montre cependant qu’un acteur motivé peut arriver à ses fins dès lors qu’il en a le temps. Les organisations compromises sont réputées pour être bien protégées. Elles ont certainement dû passer avec succès des dizaines de tests d’intrusion. Mais un test d’intrusion ne dure que quelques jours, alors que les acteurs derrière Sunburst ont disposé de nombreux mois pour compromettre des systèmes d’information entiers.
Sunburst a aussi mis en lumière la fragilité des mécanismes d’authentification, lorsque toutes les précautions ne sont pas prises.
On observe par exemple une mode du jeton JWT chez certains développeurs, qui l’utilisent pour sécuriser des applications de type SPA, en conjonction avec OAuth 2 (mais pas toujours).
Or les dernières innovations ne sont pas toujours les plus adaptées. Dans de nombreux cas, l’utilisation d’OAuth 2 pour protéger un backend abaisse le niveau de sécurité. Sunburst montre qu’il est possible (même si c’est difficile) de falsifier un JWT. Ce qui est relativement facile de faire, c’est de voler un jeton existant pour le rejouer. Il est donc important en OAuth 2 de bien appliquer les préconisations de sécurisation.
Il ne faut cependant pas perdre de vue qu’en sécurité, il nous arrive fréquemment de barricader une porte déjà difficilement accessible tout en laissant une fenêtre ouverte. Ainsi dans notre exemple, un jeton d’accès dans une application SPA se fait voler relativement facilement, alors qu’un cookie est bien mieux protégé. On aura donc intérêt – si le contexte le permet – de s’appuyer sur les sessions HTTP, certes anciennes et moins à la mode, mais plus sécurisées, car elles permettent de protéger les jetons OAuth 2 (si on en a besoin) dans un serveur.

Auteur : Marc (Directeur technique)

Leave A Comment