HOME Resources Blog It’s Not a Bug, It’s Feature Abuse: A Deep Dive Into Azure Web App Logs and Attack Visibility

|

It’s Not a Bug, It’s Feature Abuse: A Deep Dive Into Azure Web App Logs and Attack Visibility

Azure makes it easy to spin up serverless functions and web apps, a convenience  that often comes with security blind spots. Logs are fragmented across services, authentication defaults may leave endpoints exposed, and preview environments can accidentally leak sensitive files.

To understand how attackers can abuse these gaps, and what defenders can monitor, we explored the following areas:

  1. Azure Functions (the backend): We deployed a Python function, analyzed how different Azure data sources log activity, and looked at attack scenarios around unauthorized access and exfiltration.
  2. Azure Static Web App Preview URLs (the frontend): We explored how preview environments expose branch-specific content and demonstrated how sensitive files can become publicly available.

Part 1: Azure Functions – Logs, Risks, and Attack Scenarios

Function Setup and Exposure

We created a Python Azure Function App with an HTTP-triggered route:

  • Route: /api/sendEmail
  • Authorization level: ANONYMOUS
  • Behavior: takes an email parameter,, sends sensitive data to it, and returns confirmation.

Developers choose anonymous authentication mainly for its simplicity and to provide a frictionless experience for users trying out an application. Setting up anonymous access requires minimal configuration, allowing immediate interaction without the need for creating accounts, entering credentials, or sharing personal information.

At this stage, anyone on the internet with the URL could call it. Leaving functions open like this risks data exfiltration, spam, or reconnaissance. The anonymous authentication is set in the function code, inside the route definition: 

Authentication and Public URLs

By default, the function is reachable at:

With ANONYMOUS authentication, this endpoint is completely open. One effective way to secure the endpoint without relying on keys is by using Microsoft Entra ID authentication, which makes the anonymous auth setting effectively irrelevant.

Configuring Entra ID authentication involves enabling the Azure Function App’s built-in authentication feature and adding Microsoft Entra ID as an identity provider through the Azure portal.  Once configured, any unauthenticated request to the function is redirected to a login page or rejected outright, ensuring only authorized users or applications can access the function.

Entra ID authentication is well-suited for scenarios involving human users within an organization who authenticate through their Entra ID accounts, providing seamless Single Sign-On (SSO). It’s also useful for automation or service-to-service calls when using managed identities or app registrations with proper permissions. This method offers robust security without managing API keys manually and enables fine-grained access control over which tenants, users, and applications can call the function.

Importantly, with Entra ID authentication enabled, the authorization check is enforced by the platform before the function code executes, rendering the function’s auth_level setting (such as anonymous) irrelevant in terms of security enforcement.

What the Logs Show – Microsoft Sentinel Tables

When new function code is deployed or updated after creation, it triggers a specific event recorded in AzureActivity: Microsoft.Web/sites/functions/write – indicating the deployment or update of function code.

However, Capturing function execution events is more challenging because they are data plane events, unlike Azure control plane events that appear in the AzureActivity logs. To monitor executions, you need to enable diagnostic logs or Application Insights for each function individually.

  • Diagnostic logs: Execution records are ingested into the FunctionAppLogs table in Microsoft Sentinel.
  • Application Insights: Execution records are sent to the AppRequests and AppTraces tables.

Since the logs from both sources are very similar, you can choose which table best fits your needs. In this case, I selected FunctionAppLogs.

The FunctionAppLogs capture execution details along with status codes, but they do not include information about the caller, IP address, or even the App ID. The most relevant fields here are:

  • EventName: This indicates the lifecycle stage, showing “FunctionStarted” when execution begins and “FunctionCompleted” when it ends.
  • FunctionName: This contains the name of the function that was executed.

Once authentication is enabled, additional tables provide more insights about the execution:

  • AzureActivity: Logs administrative actions such as Microsoft.Web/sites/config/write  for saving or modifying authentication settings.
  • SigninLogs: Records login attempts when Entra ID authentication is active, including username, IP address, and the display name of the authenticating app. However, it does not specify which function was executed.
  • AuditLogs: Track lifecycle changes related to app registrations, secret management, and permission grants.

A critical question arises: if a malicious actor triggers the function to exfiltrate data, how can such unauthorized executions be detected?

Closing the Visibility Gap

By default, runtime execution logs and authentication logs are separate:

  • FunctionAppLogs – shows execution, not the caller.
  • SigninLogs – shows the caller, not which function exactly was executed.

Correlation is necessary, but the only reliable key available is the application display name. FunctionAppLogs don’t expose the App ID, IP address, or other identifiers that could tie an execution back to a specific user – only the app name. For this to work, the Function App name must match the identity provider’s display name (the app registration name created when Entra ID authentication was enabled). If they don’t match, it’s recommended to keep a watchlist that maps the identity provider name to the function name, and use it for correlation.

In practice, this means joining AppName from FunctionAppLogs with AppDisplayName from SigninLogs. This makes it possible to determine which user invoked which function, from where, and under what context.

Without this correlation step, you only know that a function was executed or that a user signed in to a function app – never that the two events are connected. For detection engineering, closing this gap is critical.

Part 2: Azure Static Web App Preview URLs – Exposure in Development

How Preview URLs Work

Azure Static Web Apps automatically create live preview environments for pull requests. These URLs follow the format:

You can find more information here in Microsoft documentation.

Hidden Files Made Public

To show how this can go wrong, we set up a production landing page:

Then we opened a pull request and added three files in /src:

  • debug.html – developer debug console
  • Now, anyone on the internet with the public preview URL can add /debug.html and reach this page:

This is a debug console that developers sometimes leave in preview builds. It exposes stack traces, environment variables, and test data that should never be public. Attackers love these pages because they often leak sensitive details about the system.

  • admin.html – admin panel with no authentication
  • By simply appending /admin.html to the preview link, anyone can access a fully exposed admin panel:

With no authentication in place, this kind of page can allow attackers to manipulate users, settings, or data.

  • config.dev.json – development configuration with secrets
  • Preview also made this file public at /config.dev.json:

contains secrets such as API keys and database passwords. Config leaks like this are extremely common, and real attackers actively scan for these files.

None of these files were linked from the homepage, but the preview deployment exposed them anyway. A simple reconnaissance scan on the preview domain would quickly reveal them – the filenames are generic, and automated tools exist specifically to hunt for files like debug.html, admin.html, and config.dev.json.

Detecting Preview URLs in Logs

Preview domains follow a predictable pattern. In Defender telemetry, you can search for the preview URL access with the following regex:

@”^(?:https?://)?[a-z0-9-]+-\d+\.[a-z0-9.-]*\.azurestaticapps\.net(?:/|$)”

This regex reliably detects PR-based preview URLs that use a numeric suffix. Access to preview URLs is recorded in the AppPageViews or AppRequests tables in Microsoft Sentinel. However, this requires that Application Insights is configured to forward events from the application to Microsoft Sentinel. For detailed guidance on setting up logging, see the documentation here and here.
However, this approach isn’t limited to Defender – the regex can be applied in any network monitoring solution (e.g., firewalls, proxies, or other security appliances) to flag access to these preview domains.

Securing Preview Environments

Security here cannot rely on obscurity. Defenses include:

  • Protect branches from including debug tools or secrets, as preview environments will publish any committed content unless safeguards are in place.
  • Putting Static Web Apps behind Azure Front Door or Azure Application Gateway.
  • Enforcing authentication for all environments, including testing.
  • Treating preview builds with the same caution as production.

Lessons Learned

From both experiments, the main takeaways are:

  • Anonymous endpoints are dangerous: Functions and preview URLs are always exposed.
  • Logs are incomplete in isolation: FunctionAppLogs or other application insight related tables lack caller details; SigninLogs lack execution details. Correlation is necessary.
  • Preview environments = production risk: Anything committed can go live.

Conclusion

Azure Functions and Static Web Apps show how quickly services can be deployed — and how easily they can be misconfigured or exposed. Out-of-the-box, logs do not provide full visibility into who executed functions, what parameters they used, or whether deployments were tampered with. Preview environments make development files publicly available without warning.

By enforcing authentication, enriching logs, monitoring sensitive events, and treating previews like production, defenders can close visibility gaps and detect attacks before they cause damage.

About the Author

Liora Itkin is a Security Researcher currently working at CardinalOps, where she focuses on detection engineering and threat coverage optimization. She previously worked as a Security Researcher at Palo Alto Networks, in incident response at a leading MDR company, and in an intelligence unit—building a strong foundation in SOC operations and detection strategy. She is particularly interested in advancing detection methodologies and frequently collaborates with the security community through research and knowledge sharing.