News

Azure APIM Signup Bypass: 97.9% of Developer Portals Still Exploitable Anonymously and from the Internet

  • None--securityboulevard.com
  • published date: 2026-03-24 00:00:00 UTC

None

<div data-elementor-type="wp-post" data-elementor-id="10966" class="elementor elementor-10966" data-elementor-post-type="post"> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-93afc5a e-con-full e-flex e-con e-parent" data-id="93afc5a" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-86067b8 elementor-widget elementor-widget-text-editor" data-id="86067b8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The Azure APIM signup bypass is a critical vulnerability affecting 97.9% of internet-facing Developer Portals. Azure API Management (APIM) exposes APIs to external consumers through a Developer Portal, the interface where developers self-register, obtain API keys, and make API calls. The default APIM configuration ships with Basic Authentication enabled as the identity provider and the Starter product set to auto-approve subscriptions. When an administrator disables developer self-signup, they reasonably expect that endpoint to no longer be reachable.</p> <p>It doesn’t. An anonymous attacker can create an account, subscribe to API products, obtain valid API keys, and access backend services, all without authentication or relationship to the target organization. The “disable signup” toggle in Azure APIM’s Developer Portal is purely cosmetic. The backend REST API continues to accept registrations from anyone. This is an <strong>unauthenticated, internet-facing vulnerability</strong> in a service that is internet-facing by design.</p> <p>Praetorian noted that the original issue was detected by security researcher Mihalis Haatainen at <a href="https://www.bountyy.fi/">Bountyy Oy</a> in September 2025 (see <a href="https://github.com/bountyyfi/Azure-APIM-Cross-Tenant-Signup-Bypass/security/advisories/GHSA-vcwf-73jp-r7mv">GHSA-vcwf-73jp-r7mv</a>). Mihalis Haatainen reported the issue to Microsoft’s Security Response Center (MSRC). After two submissions and additional technical details, MSRC issued its final determination: <strong>“By design.”</strong></p> <p>Four months later, we assessed the real-world prevalence.</p> <p>We built a full reproduction environment, demonstrated the complete attack chain from anonymous internet access to sensitive API data exfiltration, and conducted a wide-scale analysis across the internet-facing APIM landscape. We found over 25,000 Azure APIM Developer Portals exposed to the internet. Based on our heuristic analysis, we estimated that 97.9% of them still accept signup requests. Only 51 instances out of 25,379 have actually removed the vulnerable Basic Authentication provider. The attack requires a web browser and a curl command; no credentials, no prior access, and no Azure subscription in the target tenant.</p> <p> </p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-8c71d64 e-con-full e-flex e-con e-parent" data-id="8c71d64" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4d027db elementor-widget elementor-widget-heading" data-id="4d027db" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h2 class="elementor-heading-title elementor-size-default">The Vulnerability</h2> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-9040393 e-con-full e-flex e-con e-parent" data-id="9040393" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-568bfd5 elementor-widget elementor-widget-text-editor" data-id="568bfd5" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <a id="the-three-part-flaw"></a> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-a4066f6 e-con-full e-flex e-con e-parent" data-id="a4066f6" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-ae49ae8 elementor-widget elementor-widget-heading" data-id="ae49ae8" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">The Three-Part Flaw</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-e6910fb e-con-full e-flex e-con e-parent" data-id="e6910fb" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-0a00cc7 elementor-widget elementor-widget-text-editor" data-id="0a00cc7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The fundamental issue is a disconnect between what administrators see in the Azure Portal and what actually happens on the backend. Three separate design decisions combine to create the vulnerability:</p> <p><strong>1. The UI toggle is cosmetic:</strong> When an administrator sets portalsettings/signup.properties.enabled to false, the developer portal reads this flag and hides the signup form. The underlying REST API endpoint at /signup remains active and continues to accept registration requests regardless of what the UI displays.</p> <p><strong>2. No tenant validation on the signup endpoint.</strong> Azure APIM Developer Portals are multi-tenant. The APIM infrastructure uses the Host header in incoming requests to route them to the correct instance. When an attacker sends a POST /signup request with Host: victim-portal.developer.azure-api.net, the infrastructure routes it to the victim’s instance. There is no validation that the request originated from that tenant’s portal, that the sender has any relationship to the target organization, or that the request was initiated from the target’s domain.</p> <p><strong>3. The CAPTCHA service is shared across all tenants.</strong> The signup flow includes a CAPTCHA challenge. However, the CAPTCHA validation service is global to Azure APIM. A challenge generated on Instance A is accepted as valid when submitted to Instance B.</p> <p><a id="X7b726d72045493ee04b98d787fee093aed871b0"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-30e11bf e-con-full e-flex e-con e-parent" data-id="30e11bf" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-a5691fb elementor-widget elementor-widget-heading" data-id="a5691fb" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h2 class="elementor-heading-title elementor-size-default">The Kill Chain: From Anonymous Access to API Keys</h2> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-8130df1 e-con-full e-flex e-con e-parent" data-id="8130df1" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-15a59e6 elementor-widget elementor-widget-text-editor" data-id="15a59e6" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Account creation is the entry point. The actual severity depends on what APIs are exposed through the Developer Portal and whether the attacker can obtain subscription keys to call them. We reproduced the full attack chain on controlled infrastructure to map each step.</p> <p><a id="why-account-creation-alone-is-not-enough"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-aab12e7 e-con-full e-flex e-con e-parent" data-id="aab12e7" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-9bf00e2 elementor-widget elementor-widget-heading" data-id="9bf00e2" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">Why Account Creation Alone Is Not Enough</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-4ebf48b e-con-full e-flex e-con e-parent" data-id="4ebf48b" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-6f62cfc elementor-widget elementor-widget-text-editor" data-id="6f62cfc" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>An APIM Developer Portal account gives the attacker a session. What they can do with that session depends on the <strong>product configuration</strong>, a second layer of APIM settings that determines post-authentication access.</p> <p>APIs in APIM are not exposed directly. They are grouped into <strong>Products</strong>, and users must subscribe to a product to obtain a subscription key. Two product-level settings, subscriptionRequired and approvalRequired, determine whether an attacker can self-serve to obtain API access. The critical combination is subscriptionRequired: true with approvalRequired: false (subscription needed, but auto-approved). This is the <strong>default configuration</strong> for the built-in Starter product that ships with every new APIM instance. An attacker who creates an account can immediately subscribe and receive a valid API key without administrator involvement.</p> <p><a id="attack-path-overview"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-6868fdd e-con-full e-flex e-con e-parent" data-id="6868fdd" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-63f1ca5 elementor-widget elementor-widget-heading" data-id="63f1ca5" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">Attack Path Overview</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-7dcc48d e-con-full e-flex e-con e-parent" data-id="7dcc48d" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-d2a4dec elementor-widget elementor-widget-text-editor" data-id="d2a4dec" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-00bfab0 e-con-full e-flex e-con e-parent" data-id="00bfab0" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-3298fe1 elementor-widget elementor-widget-image" data-id="3298fe1" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img fetchpriority="high" decoding="async" width="544" height="1308" src="https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-attack-steps-from-anonymous-attacker-disco-1.webp" class="attachment-full size-full wp-image-10950" alt="Flowchart showing attack steps from anonymous attacker discovering target via Shodan to creating developer account and exfiltrating data" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-attack-steps-from-anonymous-attacker-disco-1.webp 544w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-attack-steps-from-anonymous-attacker-disco-1-125x300.webp 125w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-attack-steps-from-anonymous-attacker-disco-1-426x1024.webp 426w" sizes="(max-width: 544px) 100vw, 544px"><figcaption class="widget-image-caption wp-caption-text">Attack path from anonymous attacker to data exfiltration</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-9af606b e-con-full e-flex e-con e-parent" data-id="9af606b" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4d2d10a elementor-widget elementor-widget-heading" data-id="4d2d10a" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">Simulated Attack Chain</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-589ceef e-con-full e-flex e-con e-parent" data-id="589ceef" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-741602a elementor-widget elementor-widget-text-editor" data-id="741602a" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>We demonstrated this against a controlled APIM instance under our ownership, configured with a mock healthcare IoT API behind the default Starter product. The CAPTCHA was generated cross-tenant from a separate APIM instance we control to demonstrate the cross-tenant replay.</p> <p><a id="step-1-identify-the-target."></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-ae38fb7 e-con-full e-flex e-con e-parent" data-id="ae38fb7" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-9ae8846 elementor-widget elementor-widget-heading" data-id="9ae8846" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h4 class="elementor-heading-title elementor-size-default">Step 1: Identify the target.</h4> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-79225a3 e-con-full e-flex e-con e-parent" data-id="79225a3" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-65104af elementor-widget elementor-widget-text-editor" data-id="65104af" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The attacker discovers the target’s Developer Portal hostname. These are publicly indexed; our Shodan enumeration found 25,379 unique instances.</p> <p>Target: apim-research-target-t3.developer.azure-api.net</p> <p><a id="X6b2794b1dd9fa9a2772ac2a5ffcb82f2e4e1b0f"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-cacc5de e-con-full e-flex e-con e-parent" data-id="cacc5de" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-ee4847b elementor-widget elementor-widget-heading" data-id="ee4847b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h4 class="elementor-heading-title elementor-size-default">Step 2: Verify the target appears locked down, then bypass it.</h4> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-26e0b9e e-con-full e-flex e-con e-parent" data-id="26e0b9e" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-1c4f22c elementor-widget elementor-widget-text-editor" data-id="1c4f22c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The target organization’s portal shows no signup option, and the administrator has “disabled” signup. The only visible option is “Sign in”:</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-25c2f34 e-con-full e-flex e-con e-parent" data-id="25c2f34" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-88b03ef elementor-widget elementor-widget-image" data-id="88b03ef" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img decoding="async" width="1720" height="1328" src="https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1.webp" class="attachment-full size-full wp-image-10951" alt="API portal webpage with header navigation showing Home, APIs, Products links and Sign In button, main content area displays 'page content' text" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1.webp 1720w, https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1-300x232.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1-1024x791.webp 1024w, https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1-768x593.webp 768w, https://www.praetorian.com/wp-content/uploads/2026/03/api-portal-webpage-with-header-navigation-showing-home-apis-1-1-1536x1186.webp 1536w" sizes="(max-width: 1720px) 100vw, 1720px"><figcaption class="widget-image-caption wp-caption-text">The target’s Developer Portal. The administrator has disabled signup. No “Sign up” button is visible anywhere on the page.</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-2c45dd5 e-con-full e-flex e-con e-parent" data-id="2c45dd5" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-9500280 elementor-widget elementor-widget-text-editor" data-id="9500280" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Azure APIM Developer Portal with signup disabled showing only a Sign In option and no Sign Up button visible</p> <p><em>The target’s Developer Portal. The administrator has disabled signup. No “Sign up” button is visible anywhere on the page.</em></p> <p>However, a single request confirms whether the signup endpoint is still active behind the scenes:</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0f2b990 e-con-full e-flex e-con e-parent" data-id="0f2b990" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-b2756da elementor-widget elementor-widget-image" data-id="b2756da" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img decoding="async" width="960" height="424" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-post-request-to-signup-api-returning-h-1.webp" class="attachment-full size-full wp-image-10952" alt="Terminal showing curl POST request to signup API returning HTTP 400 error with ValidationError for challenge and signupData fields" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-post-request-to-signup-api-returning-h-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-post-request-to-signup-api-returning-h-1-300x133.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-post-request-to-signup-api-returning-h-1-768x339.webp 768w" sizes="(max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">POST /signup probe with empty JSON body returns ValidationError confirming active endpoint</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-deaa032 e-con-full e-flex e-con e-parent" data-id="deaa032" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4ea5391 elementor-widget elementor-widget-text-editor" data-id="4ea5391" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>POST signup probe with empty JSON body returning HTTP 400 ValidationError confirming the signup endpoint is still active</p> <p><em>POST /signup probe with empty JSON body returns ValidationError confirming active endpoint</em></p> <p>The HTTP 400 ValidationError with challenge and signupData fields confirms the /signup endpoint is live and Basic Auth is enabled. The toggle only hid the button.</p> <p><a id="step-3-create-a-cross-tenant-account."></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-1ca1c56 e-con-full e-flex e-con e-parent" data-id="1ca1c56" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-9a6e194 elementor-widget elementor-widget-heading" data-id="9a6e194" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h4 class="elementor-heading-title elementor-size-default">Step 3: Create a cross-tenant account.</h4> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-bc35f9d e-con-full e-flex e-con e-parent" data-id="bc35f9d" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-fa4a867 elementor-widget elementor-widget-text-editor" data-id="fa4a867" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The attacker generates and solves a CAPTCHA on their own APIM instance, then replays the solution against the target:</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-b9bd2d3 e-con-full e-flex e-con e-parent" data-id="b9bd2d3" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-b3248f1 elementor-widget elementor-widget-image" data-id="b3248f1" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="500" height="436" src="https://www.praetorian.com/wp-content/uploads/2026/03/http-post-request-to-signup-endpoint-with-json-payload-conta-1.webp" class="attachment-full size-full wp-image-10953" alt="HTTP POST request to signup endpoint with JSON payload containing CAPTCHA challenge data and user registration details" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/http-post-request-to-signup-endpoint-with-json-payload-conta-1.webp 500w, https://www.praetorian.com/wp-content/uploads/2026/03/http-post-request-to-signup-endpoint-with-json-payload-conta-1-300x262.webp 300w" sizes="auto, (max-width: 500px) 100vw, 500px"><figcaption class="widget-image-caption wp-caption-text">Cross-tenant signup POST request with attacker credentials and replayed CAPTCHA</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-b54db11 e-con-full e-flex e-con e-parent" data-id="b54db11" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-ae3b262 elementor-widget elementor-widget-image" data-id="ae3b262" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="420" height="176" src="https://www.praetorian.com/wp-content/uploads/2026/03/http-response-showing-status-200-ok-content-type-application-1.webp" class="attachment-full size-full wp-image-10954" alt="HTTP response showing status 200 OK, Content-Type application/json header, and response body containing the string OK" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/http-response-showing-status-200-ok-content-type-application-1.webp 420w, https://www.praetorian.com/wp-content/uploads/2026/03/http-response-showing-status-200-ok-content-type-application-1-300x126.webp 300w" sizes="auto, (max-width: 420px) 100vw, 420px"><figcaption class="widget-image-caption wp-caption-text">HTTP 200 OK response confirming account creation</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-9184338 e-con-full e-flex e-con e-parent" data-id="9184338" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-c079ed7 elementor-widget elementor-widget-image" data-id="c079ed7" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="1316" height="488" src="https://www.praetorian.com/wp-content/uploads/2026/03/email-from-researchpraetoriancom-asking-user-to-confirm-new-1-1.webp" class="attachment-full size-full wp-image-10955" alt="Email from [email protected] asking user to confirm new API account by clicking a suspicious link with long parameters" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/email-from-researchpraetoriancom-asking-user-to-confirm-new-1-1.webp 1316w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-researchpraetoriancom-asking-user-to-confirm-new-1-1-300x111.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-researchpraetoriancom-asking-user-to-confirm-new-1-1-1024x380.webp 1024w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-researchpraetoriancom-asking-user-to-confirm-new-1-1-768x285.webp 768w" sizes="auto, (max-width: 1316px) 100vw, 1316px"><figcaption class="widget-image-caption wp-caption-text">Email invitation after successful self-sign-up</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0b8f379 e-con-full e-flex e-con e-parent" data-id="0b8f379" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-49ca69a elementor-widget elementor-widget-text-editor" data-id="49ca69a" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Email invitation received after successful anonymous self-signup to the target Azure APIM Developer Portal</p> <p><em>Email invitation after successful self-sign-up</em></p> <p>The backend processes the request without validating the tenant of origin. The account is created in the target’s APIM instance. The attacker receives a confirmation email and can now log in.</p> <p><a id="Xadf1d2eff9fa4ebf9c1108a4310cd6aad77b8f3"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-189e3a5 e-con-full e-flex e-con e-parent" data-id="189e3a5" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-2da9547 elementor-widget elementor-widget-heading" data-id="2da9547" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h4 class="elementor-heading-title elementor-size-default">Step 4: Authenticate, subscribe to a product, and obtain an API key.</h4> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-5cdc911 e-con-full e-flex e-con e-parent" data-id="5cdc911" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-8c6fd2b elementor-widget elementor-widget-text-editor" data-id="8c6fd2b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The default Starter product ships with approvalRequired: false. The attacker self-subscribes using a PUT request to the management API. No administrator approval is needed:</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-a3ba61d e-con-full e-flex e-con e-parent" data-id="a3ba61d" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-001045d elementor-widget elementor-widget-image" data-id="001045d" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="960" height="304" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-command-making-api-call-to-azure-manag-1.webp" class="attachment-full size-full wp-image-10956" alt="Terminal showing curl command making API call to Azure Management API with Basic authentication, returning HTTP 200 response with JSON ID" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-command-making-api-call-to-azure-manag-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-command-making-api-call-to-azure-manag-1-300x95.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-showing-curl-command-making-api-call-to-azure-manag-1-768x243.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">Attacker can authenticate as a Developer to the APIM developer portal</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-c7ad55d e-con-full e-flex e-con e-parent" data-id="c7ad55d" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-fdd9af9 elementor-widget elementor-widget-image" data-id="fdd9af9" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="960" height="324" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-creating-azure-subscrip-1.webp" class="attachment-full size-full wp-image-10957" alt="Terminal window showing curl command creating Azure subscription with PUT request, displaying HTTP 201 response with JSON data" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-creating-azure-subscrip-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-creating-azure-subscrip-1-300x101.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-creating-azure-subscrip-1-768x259.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">Self-subscribe PUT request to Starter product returns 201 Created</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-e719eab e-con-full e-flex e-con e-parent" data-id="e719eab" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-37ec580 elementor-widget elementor-widget-image" data-id="37ec580" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="960" height="344" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-azure-api-with-http-1-1.webp" class="attachment-full size-full wp-image-10958" alt="Terminal window showing curl command to Azure API with HTTP 200 response containing primaryKey and secondaryKey JSON values" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-azure-api-with-http-1-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-azure-api-with-http-1-1-300x108.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-azure-api-with-http-1-1-768x275.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">listSecrets response containing primary and secondary API keys</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-9f9154a e-con-full e-flex e-con e-parent" data-id="9f9154a" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-7e3c937 elementor-widget elementor-widget-image" data-id="7e3c937" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="1332" height="621" src="https://www.praetorian.com/wp-content/uploads/2026/03/email-from-praetorian-research-welcoming-elgin-lee-to-starte-1.webp" class="attachment-full size-full wp-image-10959" alt="Email from Praetorian Research welcoming Elgin Lee to Starter subscription, showing start date 3/13/2026 and API usage details" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/email-from-praetorian-research-welcoming-elgin-lee-to-starte-1.webp 1332w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-praetorian-research-welcoming-elgin-lee-to-starte-1-300x140.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-praetorian-research-welcoming-elgin-lee-to-starte-1-1024x477.webp 1024w, https://www.praetorian.com/wp-content/uploads/2026/03/email-from-praetorian-research-welcoming-elgin-lee-to-starte-1-768x358.webp 768w" sizes="auto, (max-width: 1332px) 100vw, 1332px"><figcaption class="widget-image-caption wp-caption-text">Confirmation email of a successful subscription to Starter</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-158a6cb e-con-full e-flex e-con e-parent" data-id="158a6cb" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4a1c780 elementor-widget elementor-widget-heading" data-id="4a1c780" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h4 class="elementor-heading-title elementor-size-default">Step 5: Call backend APIs.</h4> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0df09b6 e-con-full e-flex e-con e-parent" data-id="0df09b6" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-0186939 elementor-widget elementor-widget-text-editor" data-id="0186939" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>With a valid subscription key, the attacker makes authenticated API calls through the APIM gateway:</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-eb3b039 e-con-full e-flex e-con e-parent" data-id="eb3b039" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-ae5d147 elementor-widget elementor-widget-image" data-id="ae5d147" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="960" height="304" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-medical-device-api-r-1.webp" class="attachment-full size-full wp-image-10960" alt="Terminal window showing curl command to medical device API returning HTTP 200 response with JSON data showing total patient count of 12847" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-medical-device-api-r-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-medical-device-api-r-1-300x95.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-curl-command-to-medical-device-api-r-1-768x243.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">Patient count API returns 12,847 records accessible</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-5b0bd8c e-con-full e-flex e-con e-parent" data-id="5b0bd8c" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-efe2d1c elementor-widget elementor-widget-image" data-id="efe2d1c" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="960" height="1224" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-json-response-from-medical-api-with-1-1.webp" class="attachment-full size-full wp-image-10961" alt="Terminal window showing JSON response from medical API with patient records including names, diagnoses, and physician details" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-json-response-from-medical-api-with-1-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-json-response-from-medical-api-with-1-1-235x300.webp 235w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-json-response-from-medical-api-with-1-1-803x1024.webp 803w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-json-response-from-medical-api-with-1-1-768x979.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"><figcaption class="widget-image-caption wp-caption-text">Patient search returns full records with MRNs, names, DOBs, diagnoses, and insurance IDs. All data shown above is entirely synthetic, generated by a mock API we built for research.</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0881ea2 e-con-full e-flex e-con e-parent" data-id="0881ea2" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-52e168d elementor-widget elementor-widget-text-editor" data-id="52e168d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Simulated patient health records returned via APIM API showing MRNs, names, dates of birth, diagnoses, and insurance IDs from synthetic test data</p> <p><em>Patient search returns full records with MRNs, names, DOBs, diagnoses, and insurance IDs. All data shown above is entirely synthetic, generated by a mock API we built for research.</em></p> <p>From anonymous internet access to patient health records and IoT device authentication tokens. Five steps, no credentials, no prior access to the target organization.</p> <p><a id="X3b0c89f01e5f0b95d7d85b6baf4140534fa4076"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-196f374 e-con-full e-flex e-con e-parent" data-id="196f374" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-28773d4 elementor-widget elementor-widget-heading" data-id="28773d4" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h2 class="elementor-heading-title elementor-size-default">Impact Spectrum: From Noise to Critical Data Exposure</h2> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-a0ecf3b e-con-full e-flex e-con e-parent" data-id="a0ecf3b" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-bd4c3aa elementor-widget elementor-widget-text-editor" data-id="bd4c3aa" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Not every exploitable instance carries the same risk. The Azure APIM signup bypass is the common entry point, but the severity depends on what the organization has placed behind its Developer Portal. We configured three tiers of APIM instances to illustrate the range.</p> <p><a id="the-exploitability-matrix"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-4e77759 e-con-full e-flex e-con e-parent" data-id="4e77759" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-5ec516e elementor-widget elementor-widget-heading" data-id="5ec516e" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">The Exploitability Matrix</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0880218 e-con-full e-flex e-con e-parent" data-id="0880218" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-a550547 elementor-widget elementor-widget-text-editor" data-id="a550547" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-4c7cf49 e-con-full e-flex e-con e-parent" data-id="4c7cf49" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-8cdd448 elementor-widget elementor-widget-image" data-id="8cdd448" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <figure class="wp-caption"> <img loading="lazy" decoding="async" width="1768" height="1254" src="https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1.webp" class="attachment-full size-full wp-image-10962" alt="Flowchart showing security risk paths from cross-tenant signup through subscription decisions to final risk outcomes" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1.webp 1768w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1-300x213.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1-1024x726.webp 1024w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1-768x545.webp 768w, https://www.praetorian.com/wp-content/uploads/2026/03/flowchart-showing-security-risk-paths-from-cross-tenant-sign-1-1536x1089.webp 1536w" sizes="auto, (max-width: 1768px) 100vw, 1768px"><figcaption class="widget-image-caption wp-caption-text">Exploitability decision tree showing impact tiers based on product configuration</figcaption></figure> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-b7518ed e-con-full e-flex e-con e-parent" data-id="b7518ed" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-271b93e elementor-widget elementor-widget-heading" data-id="271b93e" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h2 class="elementor-heading-title elementor-size-default">At Scale: 25,000+ Developer Portals Exposed</h2> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-aadbc6f e-con-full e-flex e-con e-parent" data-id="aadbc6f" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-b31aeb1 elementor-widget elementor-widget-text-editor" data-id="b31aeb1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>The original advisory demonstrated the vulnerability against individual instances. We assessed the scope: how many Azure APIM Developer Portals are internet-facing, and how many are likely vulnerable?</p> <p><a id="methodology"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-cee4eb4 e-con-full e-flex e-con e-parent" data-id="cee4eb4" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-5185086 elementor-widget elementor-widget-heading" data-id="5185086" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">Methodology</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-30f55b3 e-con-full e-flex e-con e-parent" data-id="30f55b3" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-9575057 elementor-widget elementor-widget-text-editor" data-id="9575057" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>We queried Shodan for all hosts matching hostname:developer.azure-api.net, which returned <strong>69,248 matching banners</strong> for individual port/service observations across internet-facing APIM infrastructure. After deduplication, we identified <strong>25,379 unique APIM Developer Portal instances</strong>. We used this as our sample set for heuristic analysis.</p> <p><strong>Limitation:</strong> This search only identifies portals using the default *.developer.azure-api.net hostname. Organizations that configure custom domains (e.g., developers.contoso.com with a CNAME to Azure APIM) are not captured. Azure uses a single wildcard TLS certificate for all APIM portals, so Certificate Transparency logs do not reveal individual instance names.</p> <p><a id="X41aea7440729aec4e61385a47baf1e16fde56eb"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-9ac8b5e e-con-full e-flex e-con e-parent" data-id="9ac8b5e" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4a7698e elementor-widget elementor-widget-heading" data-id="4a7698e" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">Heuristic Analysis: Estimating Vulnerability at Scale</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-f694220 e-con-full e-flex e-con e-parent" data-id="f694220" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-4ecae6c elementor-widget elementor-widget-text-editor" data-id="4ecae6c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>We designed a non-invasive heuristic probe to classify instances without triggering any signup flow or creating any accounts on third-party infrastructure.</p> <p>Our approach: send a POST /signup request with an empty JSON body ({}), no email, password, CAPTCHA, or PII, to every instance. This request cannot create an account and does not complete any step of the signup flow. The probe classifies responses based on error message content: an HTTP 400 containing “ValidationError,” “captcha,” or “challenge” indicates the signup endpoint is active and consistent with an enabled Basic Auth provider; an HTTP 404 indicates the signup endpoint does not exist. These are heuristic-based estimates, not confirmed exploits.</p> <p>Even accounting for the margin of error, <strong>the vast majority of internet-facing APIM Developer Portals, on the order of 23,000 to 25,000 instances, show responses consistent with an active Basic Auth signup endpoint.</strong> Only 51 instances returned HTTP 404 on /signup, indicating the Basic Auth provider has been explicitly removed.</p> <p><a id="what-this-means"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-234047d e-con-full e-flex e-con e-parent" data-id="234047d" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-87f8e55 elementor-widget elementor-widget-heading" data-id="87f8e55" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">What This Means</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-6ba5a4e e-con-full e-flex e-con e-parent" data-id="6ba5a4e" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-1e94cea elementor-widget elementor-widget-text-editor" data-id="1e94cea" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Four months after Haatainen’s public disclosure, the data suggests that very few organizations have taken the remediation step of removing the Basic Auth provider. Because MSRC classified this as “by design,” there was no security advisory or automated patch to drive remediation. Organizations that use the “disable signup” toggle as their primary control may not realize that the Azure APIM signup bypass remains exploitable and that additional action is required.</p> <p><a id="remediation-closing-the-gap"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-52536c2 e-con-full e-flex e-con e-parent" data-id="52536c2" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-e870a2a elementor-widget elementor-widget-heading" data-id="e870a2a" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h2 class="elementor-heading-title elementor-size-default">Remediation: Closing the Gap</h2> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-64645fb e-con-full e-flex e-con e-parent" data-id="64645fb" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-fd6ecc4 elementor-widget elementor-widget-text-editor" data-id="fd6ecc4" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Because MSRC has classified this behavior as “by design,” no patch or automated fix is forthcoming. Organizations running APIM need to take explicit action to close the signup endpoint. The fix is straightforward, but the Azure Portal’s “disable signup” toggle alone is not sufficient.</p> <p><a id="X56a8c51815d2afc6c4c811ac051689e6daa59df"></a> </p></div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-b00aaf8 e-con-full e-flex e-con e-parent" data-id="b00aaf8" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-737a970 elementor-widget elementor-widget-heading" data-id="737a970" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">1. Delete the Basic Authentication identity provider entirely.</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-073b3c5 e-con-full e-flex e-con e-parent" data-id="073b3c5" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-638726d elementor-widget elementor-widget-text-editor" data-id="638726d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>This is the only remediation that fully eliminates the attack surface. Removing the Basic Auth provider deactivates the /signup endpoint; there is no registration mechanism left for the attacker to target.</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-d8ef701 e-con-full e-flex e-con e-parent" data-id="d8ef701" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-3be925b elementor-widget elementor-widget-image" data-id="3be925b" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <img loading="lazy" decoding="async" width="960" height="164" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-delete-basic-au-1.webp" class="attachment-full size-full wp-image-10963" alt="Terminal window showing Azure CLI command to delete Basic Auth Provider from API Management service with subscription and resource group parameters" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-delete-basic-au-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-delete-basic-au-1-300x51.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-delete-basic-au-1-768x131.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-79a7fbe e-con-full e-flex e-con e-parent" data-id="79a7fbe" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-2e121e6 elementor-widget elementor-widget-heading" data-id="2e121e6" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">2. Switch to Azure AD (Entra ID) as the sole identity provider.</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-d41523e e-con-full e-flex e-con e-parent" data-id="d41523e" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-1a389e9 elementor-widget elementor-widget-text-editor" data-id="1a389e9" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Azure AD authentication ties account creation to your organization’s directory. Cross-tenant signups are not possible because users must authenticate through your tenant’s identity system. This is the long-term architectural fix. Learn more about <a href="https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-aad">configuring Azure AD as an identity provider for APIM</a>.</p> <p> </p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-0e1caac e-con-full e-flex e-con e-parent" data-id="0e1caac" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-1537899 elementor-widget elementor-widget-heading" data-id="1537899" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">3. Require admin approval for all product subscriptions.</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-dca0e3a e-con-full e-flex e-con e-parent" data-id="dca0e3a" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-f497d51 elementor-widget elementor-widget-text-editor" data-id="f497d51" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Even if you cannot immediately remove Basic Auth, setting approvalRequired: true on every product prevents attackers from self-subscribing and obtaining API keys. The attacker can create an account, but cannot obtain API keys without administrator approval.</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-f100636 e-con-full e-flex e-con e-parent" data-id="f100636" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-b272011 elementor-widget elementor-widget-image" data-id="b272011" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <img loading="lazy" decoding="async" width="960" height="204" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-set-approval-re-1.webp" class="attachment-full size-full wp-image-10964" alt="Terminal window showing Azure CLI command to set approval required on Starter product using PATCH method with JSON body" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-set-approval-re-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-set-approval-re-1-300x64.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-set-approval-re-1-768x163.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-150642a e-con-full e-flex e-con e-parent" data-id="150642a" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-0342996 elementor-widget elementor-widget-heading" data-id="0342996" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default"> <h3 class="elementor-heading-title elementor-size-default">4. Audit existing developer portal accounts.</h3> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-bfec1db e-con-full e-flex e-con e-parent" data-id="bfec1db" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-ba1b348 elementor-widget elementor-widget-text-editor" data-id="ba1b348" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <p>Look for accounts that were created after you “disabled” signup. Check for accounts using external email domains or accounts created via the Basic identity provider. Remove any unauthorized accounts and revoke their subscription keys.</p> </div> </div> <div data-particle_enable="false" data-particle-mobile-disabled="false" class="elementor-element elementor-element-8513f4e e-con-full e-flex e-con e-parent" data-id="8513f4e" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-7a90143 elementor-widget elementor-widget-image" data-id="7a90143" data-element_type="widget" data-e-type="widget" data-widget_type="image.default"> <img loading="lazy" decoding="async" width="960" height="244" src="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-list-developer-1-1.webp" class="attachment-full size-full wp-image-10965" alt="Terminal window showing Azure CLI command to list developer portal users with Basic authentication, displaying API endpoint URL" srcset="https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-list-developer-1-1.webp 960w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-list-developer-1-1-300x76.webp 300w, https://www.praetorian.com/wp-content/uploads/2026/03/terminal-window-showing-azure-cli-command-to-list-developer-1-1-768x195.webp 768w" sizes="auto, (max-width: 960px) 100vw, 960px"> </div> </div> </div><p>The post <a href="https://www.praetorian.com/blog/azure-apim-signup-bypass/">Azure APIM Signup Bypass: 97.9% of Developer Portals Still Exploitable Anonymously and from the Internet</a> appeared first on <a href="https://www.praetorian.com/">Praetorian</a>.</p><div class="spu-placeholder" style="display:none"></div><div class="addtoany_share_save_container addtoany_content addtoany_content_bottom"><div class="a2a_kit a2a_kit_size_20 addtoany_list" data-a2a-url="https://securityboulevard.com/2026/03/azure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet/" data-a2a-title="Azure APIM Signup Bypass: 97.9% of Developer Portals Still Exploitable Anonymously and from the Internet"><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F03%2Fazure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet%2F&amp;linkname=Azure%20APIM%20Signup%20Bypass%3A%2097.9%25%20of%20Developer%20Portals%20Still%20Exploitable%20Anonymously%20and%20from%20the%20Internet" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F03%2Fazure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet%2F&amp;linkname=Azure%20APIM%20Signup%20Bypass%3A%2097.9%25%20of%20Developer%20Portals%20Still%20Exploitable%20Anonymously%20and%20from%20the%20Internet" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F03%2Fazure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet%2F&amp;linkname=Azure%20APIM%20Signup%20Bypass%3A%2097.9%25%20of%20Developer%20Portals%20Still%20Exploitable%20Anonymously%20and%20from%20the%20Internet" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F03%2Fazure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet%2F&amp;linkname=Azure%20APIM%20Signup%20Bypass%3A%2097.9%25%20of%20Developer%20Portals%20Still%20Exploitable%20Anonymously%20and%20from%20the%20Internet" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F03%2Fazure-apim-signup-bypass-97-9-of-developer-portals-still-exploitable-anonymously-and-from-the-internet%2F&amp;linkname=Azure%20APIM%20Signup%20Bypass%3A%2097.9%25%20of%20Developer%20Portals%20Still%20Exploitable%20Anonymously%20and%20from%20the%20Internet" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share"></a></div></div><p class="syndicated-attribution">*** This is a Security Bloggers Network syndicated blog from <a href="https://www.praetorian.com/blog/">Offensive Security Blog: Latest Trends in Hacking | Praetorian</a> authored by <a href="https://securityboulevard.com/author/0/" title="Read other posts by n8n-publisher">n8n-publisher</a>. Read the original post at: <a href="https://www.praetorian.com/blog/azure-apim-signup-bypass/">https://www.praetorian.com/blog/azure-apim-signup-bypass/</a> </p>