
보안 권고: Azure APIM Developer Portal은 UI 가입 제한을 우회하여 교차 테넌트 계정 등록을 허용합니다. MSRC에 두 차례 신고되었으나 "설계상 의도된 동작(by design)"으로 종결되었습니다.
상태(01.12.2025): 이 취약점은 여전히 활성 상태이며 악용 가능합니다. Microsoft는 이 문제를 패치하지 않았으며 이를 "의도된 설계(by design)"로 간주합니다.
Azure API Management(APIM) Developer Portal의 보안 취약점으로 인해, 관리자가 포털 UI에서 사용자 가입을 비활성화했더라도 공격자는 기본 인증(Basic Authentication)이 활성화된 모든 APIM 인스턴스에 계정을 등록할 수 있습니다.
이 우회로 크로스 테넌트 계정 생성이 가능해지며, Developer Portal을 통해 노출되는 API 문서, 구독 키 및 기타 리소스에 대한 무단 액세스가 허용될 수 있습니다.
| 날짜 | 조치 |
|---|---|
| 2025-09-30 | 취약점 발견 |
| 2025-09-30 | MSRC에 최초 보고 제출 |
| 2025-10-30 | MSRC 응답: "취약점 아님"으로 종결 |
| 2025-11-01 | 추가 세부 정보와 함께 MSRC에 두 번째 보고 제출 |
| 2025-11-20 | MSRC 응답: "의도된 설계(by design)"로 종결 |
| 2025-11-20 | CERT-FI에 보고 |
| 2025-11-26 | 공개 |
| 2025-11-27 | MITRE에 CVE 요청 |
| 2026-07-09 | MITRE TL-Root/CNA-LR이 CVE-2025-66390 지정 |
Azure APIM이 Developer Portal에 대해 기본 인증으로 구성된 경우, 관리자는 Azure Portal UI를 통해 사용자 등록을 비활성화할 수 있습니다. 그러나 이는 포털 인터페이스에서 가입 양식만 숨길 뿐입니다.
백엔드 가입 API 엔드포인트는 활성 상태로 유지되며 등록 요청을 직접 수락하므로 UI 제한을 완전히 우회합니다.
두 가지 문제가 결합되어 이 취약점이 발생합니다:
공격에는 두 개의 APIM 인스턴스가 필요합니다:
단계:
Host 헤더를 자신의 인스턴스에서 대상 인스턴스로 변경합니다.핵심 기술적 세부 사항: 크로스 테넌트 우회는 가입 POST 요청에서 Host 헤더를 조작하여 작동합니다. /signup 엔드포인트는 테넌트 경계를 검증하지 않고 Host 헤더를 기반으로 요청을 처리합니다.
요청 조작 예시:
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]",...}}
핵심 문제: UI에서 가입을 비활성화해도 백엔드 API는 비활성화되지 않습니다. API 엔드포인트는 Host 헤더를 기반으로 크로스 테넌트 요청을 수락합니다.
다음의 경우 APIM 인스턴스는 취약합니다:
다음의 경우 APIM 인스턴스는 취약하지 않습니다:
핵심 사항: Azure Portal UI에서 가입을 비활성화하는 것만으로는 충분하지 않습니다. 크로스 테넌트 가입 우회를 방지하려면 기본 인증 ID 공급자를 완전히 제거해야 합니다.
이러한 속성 값을 사용하여 Azure Resource Graph, ARM 템플릿 또는 Azure Policy를 통해 취약한 APIM 인스턴스를 식별할 수 있습니다.
| 속성 경로 | 취약한 값 |
|---|
기본 인증 ID 공급자는 APIM 인스턴스 아래의 별도 리소스입니다:
Resource Type: Microsoft.ApiManagement/service/identityProviders
Name: basic
존재하면 취약: basic ID 공급자 리소스가 존재하면 기본 인증이 구성되어 있음을 나타냅니다.
Resource Type: Microsoft.ApiManagement/service/portalsettings/signup
Property: properties.enabled
| 속성 | 값 | 의미 |
|---|---|---|
properties.enabled | true | UI에 가입 표시됨 |
properties.enabled | false | UI에서 가입 숨겨짐(기본 인증이 존재하면 API는 여전히 작동함!) |
잠재적으로 취약한 APIM 인스턴스를 찾으려면 다음 쿼리를 사용하세요:
resources
| where type == "microsoft.apimanagement/service"
| where properties.developerPortalStatus == "Enabled"
| where sku.name != "Consumption"
| project name, resourceGroup, subscriptionId, location, sku.name, properties.developerPortalStatus
기본 인증 ID 공급자를 확인하려면:
resources
| where type == "microsoft.apimanagement/service/identityproviders"
| where name endswith "/basic"
| project apimInstance=tostring(split(id, "/providers/Microsoft.ApiManagement/service/")[1]), resourceGroup, subscriptionId
Developer Portal 상태 확인:
az apim show --name <apim-name> --resource-group <rg-name> --query "{name:name, portalStatus:developerPortalStatus, sku:sku.name}"
ID 공급자 나열('basic' 확인):
az apim identity-provider list --resource-group <rg-name> --service-name <apim-name> --query "[].name"
가입 설정 확인:
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"
치명적 조합: 다음 조건에서 인스턴스는 가입 우회에 취약합니다:
properties.developerPortalStatus == 'Enabled' ANDidentityProviders/basic 리소스 존재 ANDportalsettings/signup.properties.enabled == false법적 고지: 아래 정보는 조직 소유의 Azure APIM 인스턴스를 식별하고 보호하기 위한 목적으로만 제공됩니다. 컴퓨터 시스템에 대한 무단 접근은 불법입니다. 소유한 시스템 또는 테스트에 대한 명시적 서면 승인을 받은 시스템에서만 테스트하세요.
기본 인증 가입이 있는 포털 찾기(취약할 가능성이 가장 높음):
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"
로그인 페이지가 있는 포털 찾기(기본 인증이 구성되어 있을 수 있음을 나타냄):
site:developer.azure-api.net "Sign in" "Email" "Password" -"Azure AD" -"Microsoft account"
site:developer.azure-api.net inurl:/signin "password"
API 문서가 노출된 개발자 포털 찾기:
site:developer.azure-api.net inurl:/apis "Subscribe"
site:developer.azure-api.net "API" "Products" "Subscribe"
일반 탐색:
site:*.developer.azure-api.net
inurl:developer.azure-api.net "Developer Portal"
APIM Developer Portal 찾기:
http.title:"Developer Portal" http.html:"azure-api.net"
ssl.cert.subject.cn:"*.developer.azure-api.net"
http.html:"developerPortal" http.html:"azure"
대상을 발견한 후 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
조직에서 Azure APIM을 사용하는 경우 다음을 사용하여 자체 인스턴스를 식별할 수 있습니다:
Azure Portal:
Azure CLI(구독용):
# List all APIM instances in your subscriptions
az apim list --query "[].{name:name, resourceGroup:resourceGroup, url:developerPortalUrl}"
다음 방법을 사용하여 조직의 APIM 인스턴스가 취약한지 확인하세요:
검증 스크립트 사용:
# 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
내부 보안 감사에 Nuclei 사용:
# Scan your organization's APIM instances
nuclei -t azure-apim-signup-bypass.yaml -u https://YOUR-ORG.developer.azure-api.net
자체 인스턴스를 감사할 때 다음을 확인하세요:
취약하지 않은 지표:
승인된 테스트를 수행하는 보안 전문가라면:
취약한 제3자 APIM 인스턴스를 발견한 경우:
APIM 인스턴스가 취약한지 확인하기 위한 Python 스크립트가 제공됩니다.
# Basic installation (HTTP probe only)
pip install requests colorama
# Full installation (includes Azure RM property checks)
pip install requests colorama azure-identity
스크립트는 두 가지 모드를 지원합니다:
# 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
--azure 모드를 사용하면 스크립트가 Azure Resource Manager API를 직접 쿼리하여 다음을 확인합니다:
| 속성 | 취약한 값 |
|---|
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
자동화된 스캔을 위한 Nuclei 템플릿이 제공됩니다.
# 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 엔드포인트에 POST 요청 전송Microsoft 보안 대응 센터(MSRC)는 이 취약점에 대해 두 차례 통보를 받았습니다. 두 보고 모두 다음 판정으로 종결되었습니다:
"의도된 설계(By design)"
MSRC는 관리 제어 우회 및 크로스 테넌트 영향에도 불구하고 이를 보안 취약점으로 간주하지 않습니다.
apim_vuln_checker.py - Python 취약점 검증 스크립트azure-apim-signup-bypass.yaml - 자동화된 스캔용 Nuclei 템플릿README.md - 이 파일Mihalis Haatainen
Bountyy Oy - 핀란드 침투 테스트 및 보안 연구 회사
이 권고 및 관련 도구는 방어 목적으로 공개되었습니다. 책임감 있게 사용하세요.
MIT 라이선스 - 자세한 내용은 LICENSE 파일을 참조하세요.
| 설명 |
|---|
properties.developerPortalStatus | Enabled | Developer Portal에 접근 가능 |
sku.name | Developer, Basic, Standard, Premium | Consumption이 아닌 계층(Consumption 계층은 포털 기능이 제한적임) |
| 조건 | 속성/리소스 | 취약한 값 |
|---|
| 포털 활성화 | properties.developerPortalStatus | == 'Enabled' |
| 비Consumption SKU | sku.name | != 'Consumption' |
| 기본 인증 존재 | identityProviders/basic 리소스 | 리소스 존재 |
| 가입 숨김(우회 가능) | portalsettings/signup.properties.enabled | == false (기본 인증이 있는 경우) |
properties.developerPortalStatus | == 'Enabled' |
sku.name | != 'Consumption' |
identityProviders/basic 리소스 | 존재함 |
portalsettings/signup.properties.enabled | == false |