HIGH information disclosureazure

Information Disclosure on Azure

How Information Disclosure Manifests in Azure

Information disclosure in Azure environments often stems from misconfigured services that inadvertently expose sensitive data through error messages, debug endpoints, or overly verbose logging. Azure's distributed architecture creates unique attack surfaces where information can leak across service boundaries.

One common pattern occurs in Azure App Service applications that return detailed exception stack traces in production responses. When an unhandled exception occurs, the default behavior may expose internal file paths, database connection strings, or even Azure-specific environment variables. Consider this vulnerable ASP.NET Core controller:

[ApiController]
[Route("[controller]")]
public class OrdersController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult GetOrder(int id)
    {
        try
        {
            // Simulated database access
            var order = _orderRepository.GetById(id);
            if (order == null) return NotFound();
            return Ok(order);
        }
        catch (Exception ex)
        {
            // Vulnerable: returns full exception details
            return StatusCode(500, new { 
                Error = ex.Message, 
                StackTrace = ex.StackTrace 
            });
        }
    }
}

This exposes Azure-specific paths like C:\\home\\site\\wwwroot and potentially connection strings when exceptions occur.

Azure Blob Storage misconfigurations represent another significant vector. When anonymous access is enabled on containers, attackers can enumerate all blobs and potentially discover sensitive files. The following configuration would allow public access:

// Vulnerable: anonymous access enabled
BlobContainerClient container = new BlobContainerClient(
    connectionString: "",
    containerName: "public-data"
);
await container.SetAccessPolicyAsync(PublicAccessType.Blob);

Azure Functions also present unique disclosure risks through HTTP trigger bindings. Default function configurations may expose internal function names, execution times, and Azure Functions runtime versions in response headers:

// Vulnerable: exposes internal details
[FunctionName("OrderProcessor")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
    ILogger log)
{
    // Function name and runtime details may be exposed
    return new OkObjectResult("Processing complete");
}

Azure API Management instances often leak information through improperly configured policies. A common mistake is enabling detailed error responses in production:

<policies>
    <!-- Vulnerable: detailed errors in production -->
    <backend>
        <forward-request />
    </backend>
    <outbound>
        <send-response />
    </outbound>
    <on-error>
        <return-response>
            <status code="500" reason="Internal Server Error" />
            <set-body>
                <![CDATA[{"error": "@{(string)context.LastError.Message}"}]]>
            </set-body>
        </return-response>
    </on-error>
</policies>

Azure Key Vault presents another attack surface where misconfigured access policies can lead to credential exposure. If a web application has excessive Key Vault permissions, a successful attack could enumerate all secrets:

// Vulnerable: overly permissive Key Vault access
var kvClient = new SecretClient(
    new Uri("https://myvault.vault.azure.net/"),
    new DefaultAzureCredential()
);

// Attacker could enumerate all secrets if permissions allow
var secrets = kvClient.GetPropertiesOfSecrets().ToList();
foreach (var secret in secrets)
{
    var secretValue = kvClient.GetSecret(secret.Name);
    Console.WriteLine($"{secret.Name}: {secretValue.Value}");
}

Azure-Specific Detection

Detecting information disclosure in Azure environments requires both automated scanning and manual inspection of Azure-specific configurations. Azure provides several built-in tools, but comprehensive detection often requires specialized security scanners.

Azure Security Center (ASC) can identify some information disclosure risks through its security policies. For example, it can detect when Blob Storage containers have public access enabled:

# Azure CLI command to check for public blob access
az storage container show-permission \
    --account-name mystorageaccount \
    --name mycontainer

# Output interpretation
# If "publicAccess": "Container" or "Blob", this is a finding

For application-level detection, Azure App Service provides diagnostic logging that can reveal information disclosure patterns. Enable Application Logging and Failed Request Tracing to capture detailed error information:

# Azure CLI to enable diagnostic logs
az webapp log config \
    --name myapp \
    --resource-group mygroup \
    --application-logging true \
    --level information

# Check for verbose error messages in logs
az webapp log tail --name myapp --resource-group mygroup

middleBrick provides specialized Azure information disclosure scanning that tests the unauthenticated attack surface of Azure-hosted APIs. It identifies Azure-specific disclosure patterns including:

Check TypeAzure-Specific TargetDetection Method
Stack Trace Analysis.NET Core exception responsesRegex patterns for Azure paths, connection strings
Header DisclosureServer, X-AspNet-Version headersResponse header analysis
Blob Storage EnumerationAnonymous container accessHEAD requests to container URLs
API Management PoliciesError response configurationsPolicy XML analysis
Function Runtime InfoAzure Functions metadataTrigger endpoint analysis

The middleBrick CLI provides Azure-specific scanning capabilities:

# Install middleBrick CLI
npm install -g middlebrick

# Scan an Azure-hosted API
middlebrick scan https://myazureapp.azurewebsites.net/api/orders

# Output includes Azure-specific findings
{
  "azureInfoDisclosure": {
    "found": true,
    "severity": "high",
    "description": "Stack trace contains Azure-specific file paths",
    "remediation": "Implement custom error handling middleware"
  }
}

For Azure Functions, you can use the Azure Functions Core Tools to test for information disclosure:

# Test function locally for verbose error messages
func start --verbose

# Look for:
# - Internal runtime paths
# - Azure Functions version information
# - Connection string exposure in logs

Azure-Specific Remediation

Remediating information disclosure in Azure requires a combination of application-level fixes and Azure service configuration changes. The following approaches address Azure-specific disclosure patterns.

For ASP.NET Core applications hosted in Azure App Service, implement centralized exception handling with custom error pages:

public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            // Production: custom error handling without sensitive details
            app.UseExceptionHandler("/error");
            
            // Prevent stack trace disclosure
            app.Use(async (context, next) =>
            {
                try
                {
                    await next();
                }
                catch (Exception)
                {
                    context.Response.ContentType = "application/json";
                    context.Response.StatusCode = 500;
                    await context.Response.WriteAsync(
                        JsonSerializer.Serialize(new { 
                            error = "An unexpected error occurred. Please try again later." 
                        })
                    );
                }
            });
        }
    }
}

Configure Azure Blob Storage with least-privilege access policies:

// Secure Blob Storage configuration
BlobContainerClient container = new BlobContainerClient(
    connectionString: "",
    containerName: "secure-data"
);

// Explicitly disable public access
await container.SetAccessPolicyAsync(PublicAccessType.None);

// Use Azure AD authentication instead of shared keys
BlobClientOptions options = new BlobClientOptions
{
    Credential = new DefaultAzureCredential()
};

// Implement fine-grained access control
await container.SetAccessPolicyAsync(new BlobContainerAccessPolicy
{
    Permissions = "r" // Read-only for specific identities
});

For Azure API Management, configure policies to prevent information disclosure:

<policies>
    <!-- Secure error handling -->
    <inbound>
        <set-header name="X-Content-Type-Options" exists-action="override">
            <value>nosniff</value>
        </set-header>
        <set-header name="X-Frame-Options" exists-action="override">
            <value>SAMEORIGIN</value>
        </set-header>
    </inbound>
    
    <outbound>
        <!-- Remove server headers -->
        <set-header name="Server" exists-action="delete" />
        <set-header name="X-AspNet-Version" exists-action="delete" />
        <set-header name="X-Powered-By" exists-action="delete" />
    </outbound>
    
    <on-error>
        <!-- Generic error response without details -->
        <return-response>
            <set-status code="500" reason="Internal Server Error" />
            <set-header name="Content-Type" exists-action="override">
                <value>application/json</value>
            </set-header>
            <set-body>
                <![CDATA[{"error": "An internal error occurred. Please contact support with reference ID: @{(string)context.OperationId}"}]]>
            </set-body>
        </return-response>
    </on-error>
</policies>

Secure Azure Functions by configuring proper authorization levels and removing debug information:

// Secure Azure Function configuration
[FunctionName("SecureOrderProcessor")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req,
    ILogger log,
    TraceWriter trace)
{
    try
    {
        // Process request
        var data = await req.Content.ReadAsStringAsync();
        
        // Return generic success response
        return req.CreateResponse(HttpStatusCode.OK, new 
        { 
            status = "success", 
            message = "Order processed successfully" 
        });
    }
    catch (Exception ex)
    {
        // Log error without exposing details
        log.LogError(ex, "Error processing order");
        
        // Return generic error without stack trace
        return req.CreateErrorResponse(HttpStatusCode.InternalServerError, 
            "An error occurred while processing your request");
    }
}

Implement Azure Key Vault with least-privilege access patterns:

// Secure Key Vault access with managed identities
var kvClient = new SecretClient(
    new Uri("https://myapp-vault.vault.azure.net/"),
    new DefaultAzureCredential(new DefaultAzureCredentialOptions
    {
        // Only allow specific identities
        ExcludeSharedTokenCacheCredential = true,
        ExcludeVisualStudioCredential = true
    })
);

// Use Azure AD authentication instead of secrets
var credential = new DefaultAzureCredential();
var client = new BlobServiceClient(
    new Uri("https://myaccount.blob.core.windows.net"),
    credential
);

// Implement secret rotation policies
await kvClient.SetSecretAsync("ConnectionString", 
    "",
    new BlobHttpHeaders { ContentType = "application/json" });

Frequently Asked Questions

How does Azure's managed identity feature help prevent information disclosure?
Azure Managed Identities eliminate the need to store credentials in code or configuration files by providing Azure services with an automatically managed identity in Azure Active Directory. This prevents credential exposure through source code leaks, misconfigured storage, or application errors. When a service like Azure App Service uses a managed identity, it authenticates directly with Azure services using token-based authentication rather than connection strings or API keys, reducing the attack surface for information disclosure.
Can middleBrick detect information disclosure in Azure Logic Apps?
Yes, middleBrick can detect information disclosure in Azure Logic Apps by analyzing the exposed HTTP endpoints and workflow configurations. It tests for verbose error responses, exposed workflow names, and potential data exposure through trigger endpoints. The scanner specifically looks for Logic Apps that return detailed exception information, expose internal workflow IDs, or have overly permissive trigger access policies that could allow enumeration of workflow structures and data flows.