
Aviso de seguridad: Azure APIM Developer Portal permite el registro de cuentas entre inquilinos al eludir las restricciones de registro de la interfaz de usuario. Reportado a MSRC dos veces - cerrado como «por diseño».
Estado (01.12.2025): Esta vulnerabilidad sigue activa y explotable. Microsoft no ha corregido este problema y lo considera «por diseño».
Una vulnerabilidad de seguridad en el portal para desarrolladores de Azure API Management (APIM) permite a los atacantes registrar cuentas en cualquier instancia de APIM que tenga habilitada la autenticación básica, incluso cuando los administradores han deshabilitado el registro de usuarios en la interfaz del portal.
Este bypass permite la creación de cuentas entre inquilinos, lo que potencialmente permite el acceso no autorizado a la documentación de las API, las claves de suscripción y otros recursos expuestos a través del portal para desarrolladores.
| Fecha | Acción |
|---|---|
| 2025-09-30 | Vulnerabilidad descubierta |
| 2025-09-30 | Informe inicial enviado a MSRC |
| 2025-10-30 | Respuesta de MSRC: cerrado como «no es una vulnerabilidad» |
| 2025-11-01 | Segundo informe enviado a MSRC con detalles adicionales |
| 2025-11-20 | Respuesta de MSRC: cerrado como «por diseño» |
| 2025-11-20 | Notificado a CERT-FI |
| 2025-11-26 | Divulgación pública |
| 2025-11-27 | CVE solicitado a MITRE |
| 2026-07-09 | CVE-2025-66390 asignado por MITRE TL-Root/CNA-LR |
Cuando Azure APIM está configurado con autenticación básica para el portal para desarrolladores, los administradores pueden deshabilitar el registro de usuarios a través de la interfaz de Azure Portal. Sin embargo, esto solo oculta el formulario de registro en la interfaz del portal.
El endpoint subyacente de la API de registro permanece activo y acepta solicitudes de registro directamente, omitiendo por completo la restricción de la interfaz.
Dos problemas se combinan para crear esta vulnerabilidad:
El ataque requiere dos instancias de APIM:
Pasos:
Host de su instancia a la instancia objetivoDetalle técnico clave: el bypass entre inquilinos funciona manipulando la cabecera Host en la solicitud POST de registro. El endpoint /signup procesa las solicitudes basándose en la cabecera Host sin validar los límites entre inquilinos.
Ejemplo de manipulación de solicitud:
POST /signup HTTP/1.1
Host: target-apim.developer.azure-api.net <-- Changed from attacker's instance
Origin: https://attacker-apim.developer.azure-api.net
Content-Type: application/json
{"challenge":{...},"signupData":{"email":"[email protected]",...}}
El problema principal: deshabilitar el registro en la interfaz no deshabilita la API subyacente. El endpoint de la API acepta solicitudes entre inquilinos basándose en la cabecera Host.
Tu instancia de APIM es vulnerable si:
Tu instancia de APIM NO es vulnerable si:
Punto clave: deshabilitar el registro en la interfaz de Azure Portal NO es suficiente. El proveedor de identidad de autenticación básica debe eliminarse por completo para prevenir el bypass de registro entre inquilinos.
Usa estos valores de propiedad para identificar instancias de APIM vulnerables mediante Azure Resource Graph, plantillas ARM o Azure Policy.
El proveedor de identidad de autenticación básica es un recurso independiente dentro de la instancia de APIM:
Resource Type: Microsoft.ApiManagement/service/identityProviders
Name: basic
Vulnerable si existe: la presencia de un recurso de proveedor de identidad basic indica que la autenticación básica está configurada.
Resource Type: Microsoft.ApiManagement/service/portalsettings/signup
Property: properties.enabled
| Propiedad | Valor | Significado |
|---|---|---|
properties.enabled | true | Registro visible en la interfaz |
properties.enabled | false | Registro oculto en la interfaz (¡la API sigue funcionando si existe autenticación básica!) |
Usa esta consulta para encontrar instancias de APIM potencialmente vulnerables:
resources
| where type == "microsoft.apimanagement/service"
| where properties.developerPortalStatus == "Enabled"
| where sku.name != "Consumption"
| project name, resourceGroup, subscriptionId, location, sku.name, properties.developerPortalStatus
Para comprobar los proveedores de identidad de autenticación básica:
resources
| where type == "microsoft.apimanagement/service/identityproviders"
| where name endswith "/basic"
| project apimInstance=tostring(split(id, "/providers/Microsoft.ApiManagement/service/")[1]), resourceGroup, subscriptionId
Comprueba el estado del portal para desarrolladores:
az apim show --name <apim-name> --resource-group <rg-name> --query "{name:name, portalStatus:developerPortalStatus, sku:sku.name}"
Enumera los proveedores de identidad (comprueba si hay 'basic'):
az apim identity-provider list --resource-group <rg-name> --service-name <apim-name> --query "[].name"
Comprueba la configuración de registro:
az rest --method get --url "https://management.azure.com/subscriptions/<sub-id>/resourceGroups/<rg-name>/providers/Microsoft.ApiManagement/service/<apim-name>/portalsettings/signup?api-version=2022-08-01" --query "properties.enabled"
Combinación crítica: una instancia es vulnerable al bypass de registro cuando:
properties.developerPortalStatus == 'Enabled' YidentityProviders/basic existe Yportalsettings/signup.properties.enabled == falseAVISO LEGAL: la información que aparece a continuación se proporciona únicamente para identificar y proteger las instancias de Azure APIM de tu propia organización. El acceso no autorizado a sistemas informáticos es ilegal. Solo prueba sistemas que te pertenezcan o para los que tengas autorización explícita por escrito.
Encuentra portales con registro de autenticación básica (probablemente vulnerables):
site:developer.azure-api.net "Sign up" "Email" "Password"
site:developer.azure-api.net "Create account" "Username"
site:developer.azure-api.net inurl:/signup "register"
Encuentra portales con páginas de inicio de sesión (indica que la autenticación básica puede estar configurada):
site:developer.azure-api.net "Sign in" "Email" "Password" -"Azure AD" -"Microsoft account"
site:developer.azure-api.net inurl:/signin "password"
Encuentra portales para desarrolladores con documentación de API expuesta:
site:developer.azure-api.net inurl:/apis "Subscribe"
site:developer.azure-api.net "API" "Products" "Subscribe"
Descubrimiento general:
site:*.developer.azure-api.net
inurl:developer.azure-api.net "Developer Portal"
Encuentra portales para desarrolladores de APIM:
http.title:"Developer Portal" http.html:"azure-api.net"
ssl.cert.subject.cn:"*.developer.azure-api.net"
http.html:"developerPortal" http.html:"azure"
Después de descubrir objetivos, escanéalos con Nuclei:
# Save targets to file
echo "https://target1.developer.azure-api.net" > targets.txt
echo "https://target2.developer.azure-api.net" >> targets.txt
# Mass scan
nuclei -t azure-apim-signup-bypass.yaml -l targets.txt -o vulnerable.txt
Si tu organización usa Azure APIM, puedes identificar tus propias instancias usando:
Azure Portal:
Azure CLI (para tus suscripciones):
# List all APIM instances in your subscriptions
az apim list --query "[].{name:name, resourceGroup:resourceGroup, url:developerPortalUrl}"
Usa estos métodos para comprobar si las instancias de APIM de TU organización son vulnerables:
Uso del script de verificación:
# Check your own instance
python apim_vuln_checker.py https://YOUR-ORG.developer.azure-api.net
# With Azure RM property checks (recommended for internal audits)
python apim_vuln_checker.py --azure -s YOUR-SUB-ID -g YOUR-RG -n YOUR-APIM-NAME
Uso de Nuclei para auditorías de seguridad internas:
# Scan your organization's APIM instances
nuclei -t azure-apim-signup-bypass.yaml -u https://YOUR-ORG.developer.azure-api.net
Al auditar tus propias instancias, busca lo siguiente:
Indicadores de NO vulnerabilidad:
Si eres un profesional de la seguridad que realiza pruebas autorizadas:
Si descubres una instancia de APIM vulnerable de terceros:
Se proporciona un script de Python para comprobar si tu instancia de APIM es vulnerable.
# Basic installation (HTTP probe only)
pip install requests colorama
# Full installation (includes Azure RM property checks)
pip install requests colorama azure-identity
El script admite dos modos:
# HTTP probe (external check)
python apim_vuln_checker.py https://your-apim.developer.azure-api.net
# Azure RM property check (requires az login)
python apim_vuln_checker.py --azure -s <subscription-id> -g <resource-group> -n <apim-name>
# Combined check (both HTTP probe and Azure RM)
python apim_vuln_checker.py https://your-apim.developer.azure-api.net \
--azure -s <subscription-id> -g <resource-group> -n <apim-name>
# Verbose output
python apim_vuln_checker.py https://your-apim.developer.azure-api.net -v
# Skip SSL verification
python apim_vuln_checker.py https://your-apim.developer.azure-api.net -k
# JSON output
python apim_vuln_checker.py https://your-apim.developer.azure-api.net --json
Cuando se usa el modo --azure, el script consulta directamente la API de Azure Resource Manager para comprobar:
| Propiedad |
|---|
Requisitos previos para el modo Azure RM:
azure-identity: pip install azure-identityaz login ___ __ ____
/ _ )___ __ _____ / /___ ____ __ / __ \__ __
/ _ / _ \/ // / _ \/ __/ // / // / / /_/ / // /
/____/\___/\_,_/_//_/\__/\_, /\_, / \____/\_, /
/___//___/ /___/
Author: Mihalis Haatainen, Bountyy Oy - www.bountyy.fi
======================================================================
Azure APIM Vulnerability Checker
Cross-Tenant Signup Bypass Detection
======================================================================
[?] Checking signup endpoint accessibility...
[i] Signup endpoint is accessible
[?] Checking if Basic Auth signup API is accessible...
[!] Basic Auth signup API ACTIVE (captcha validation)
[?] Checking if signup is hidden/disabled in UI...
[i] Signup page returns 404 (hidden in UI)
======================================================================
VULNERABILITY ASSESSMENT RESULTS
======================================================================
Target: https://example.developer.azure-api.net
Risk Level: CRITICAL - VULNERABLE TO SIGNUP BYPASS
Detailed Checks:
[!] signup_ui: Signup endpoint is accessible
[!] basic_auth_api: Basic Auth signup API ACTIVE (captcha validation)
[+] signup_ui_hidden: Signup page returns 404 (hidden in UI)
Recommendations:
CRITICAL: SIGNUP BYPASS VULNERABILITY CONFIRMED
The Basic Auth signup API is accessible even though UI hides signup.
Attackers can register accounts by calling the API directly.
Immediate actions:
1. DISABLE Basic Authentication in Azure Portal immediately
2. Audit all developer portal user accounts for unauthorized signups
3. Review user creation logs - check for API-based registrations
4. Implement Azure AD authentication only
Se proporciona una plantilla de Nuclei para el escaneo automatizado.
# Single target
nuclei -t azure-apim-signup-bypass.yaml -u https://target.developer.azure-api.net
# Multiple targets from file
nuclei -t azure-apim-signup-bypass.yaml -l targets.txt
# With proxy (for debugging)
nuclei -t azure-apim-signup-bypass.yaml -u https://target.developer.azure-api.net -proxy http://127.0.0.1:8080
# Skip SSL verification
nuclei -t azure-apim-signup-bypass.yaml -u https://target.developer.azure-api.net -insecure
/signup con datos de captcha de pruebaSe notificó dos veces al Centro de respuesta de seguridad de Microsoft (MSRC) sobre esta vulnerabilidad. Ambos informes se cerraron con la siguiente determinación:
«Por diseño»
MSRC no considera que esto sea una vulnerabilidad de seguridad, a pesar del bypass de los controles administrativos y de las implicaciones entre inquilinos.
apim_vuln_checker.py: script de verificación de vulnerabilidades en Pythonazure-apim-signup-bypass.yaml: plantilla de Nuclei para el escaneo automatizadoREADME.md: este archivoMihalis Haatainen
Bountyy Oy: empresa finlandesa de pruebas de penetración e investigación en seguridad
Este aviso y las herramientas asociadas se publican con fines defensivos. Úsalas de forma responsable.
Licencia MIT: consulta el archivo LICENSE para obtener más detalles.
| Ruta de la propiedad | Valor vulnerable | Descripción |
|---|
properties.developerPortalStatus | Enabled | El portal para desarrolladores es accesible |
sku.name | Developer, Basic, Standard, Premium | Niveles que no son de consumo (el nivel de consumo tiene funciones limitadas del portal) |
| Condición | Propiedad/recurso | Valor vulnerable |
|---|
| Portal habilitado | properties.developerPortalStatus | == 'Enabled' |
| SKU que no es de consumo | sku.name | != 'Consumption' |
| Autenticación básica existente | Recurso identityProviders/basic | El recurso existe |
| Registro oculto (bypass posible) | portalsettings/signup.properties.enabled | == false (con autenticación básica) |
| Valor vulnerable |
|---|
properties.developerPortalStatus | == 'Enabled' |
sku.name | != 'Consumption' |
Recurso identityProviders/basic | Existe |
portalsettings/signup.properties.enabled | == false |