HIGH aspnetssrf cloud metadata

Ssrf Cloud Metadata in Aspnet

How SSRF Cloud Metadata Manifests in ASP.NET

Server-Side Request Forgery (SSRF) targeting cloud metadata services is a critical vulnerability in ASP.NET applications where an attacker manipulates the application into making requests to internal cloud provider endpoints. These endpoints, such as AWS EC2 Instance Metadata Service (IMDS) at 169.254.169.254 or Azure Instance Metadata Service at 169.254.169.254/metadata/instance, expose sensitive credentials and configuration data. In ASP.NET, this often occurs through user-controlled input in HTTP clients without proper validation.

Common attack patterns include:

  • URL Parameter SSRF: An API endpoint accepts a url query parameter and uses HttpClient to fetch that resource. An attacker provides ?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ to retrieve AWS IAM role credentials.
  • JSON Body SSRF: A POST endpoint expects a JSON payload with a targetUrl field. The server-side code deserializes this and passes it directly to an HTTP client.
  • Header-Based SSRF: Less common, but some applications use user-supplied URLs in headers like X-Forwarded-Url or Referer for internal routing or logging.

Vulnerable ASP.NET code typically looks like this:

[HttpGet("fetch")]
public async Task<IActionResult> Fetch(string url)
{
    using var client = new HttpClient();
    var response = await client.GetStringAsync(url);
    return Content(response);
}

This pattern is dangerous because HttpClient will attempt to connect to any provided address, including private IP ranges reserved for cloud metadata services. The impact is severe: an attacker can exfiltrate cloud credentials, leading to full account compromise. Notably, CVE-2022-22965 (Spring4Shell) highlighted similar SSRF risks in Java; ASP.NET applications are equally susceptible when user input influences request destinations without sanitization.

ASP.NET-Specific Detection

Detecting SSRF in ASP.NET requires both static code analysis and dynamic testing. Statically, search for any use of HttpClient, RestSharp, WebRequest, or third-party HTTP libraries where the request URL incorporates user input (query parameters, route values, JSON body, headers). Pay special attention to any lack of validation against private IP ranges (RFC 1918, link-local, cloud metadata IPs).

Dynamically, you must test API endpoints that accept URLs. The test payloads target well-known cloud metadata IPs:

  • AWS: http://169.254.169.254/latest/meta-data/
  • Azure: http://169.254.169.254/metadata/instance?api-version=2021-02-01 (requires Metadata:true header)
  • GCP: http://metadata.google.internal/computeMetadata/v1/ (requires Metadata-Flavor: Google header)

If the application returns data from these endpoints, SSRF is confirmed. For example, a successful AWS credential leak might return JSON with AccessKeyId, SecretAccessKey.

middleBrick automates this detection. When you submit an ASP.NET API endpoint to middleBrick's web dashboard or use the middlebrick CLI (middlebrick scan https://api.example.com/fetch?url=169.254.169.254), it performs a black-box scan. The SSRF check actively probes for cloud metadata access by sending payloads like the above to any parameter that looks like a URL. If the response contains metadata-specific strings (e.g., ami-id, instance-id, AccessKeyId), middleBrick flags it with a high severity finding, includes the vulnerable parameter, and provides remediation guidance tailored to ASP.NET. The scan runs in seconds, requiring no credentials or configuration.

ASP.NET-Specific Remediation

Remediating SSRF in ASP.NET involves strict input validation and using safe HTTP client patterns. Never trust user-supplied URLs. Implement defense-in-depth:

1. Input Validation with Allow-Listing

If your application only needs to fetch a known set of external APIs, maintain a strict allow-list of domains. Validate the URL's hostname against this list. For dynamic use cases where any public URL is allowed, block private IP ranges and cloud metadata IPs explicitly.

public static bool IsUrlAllowed(string url)
{
    if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
        return false;

    // Allow only HTTPS
    if (uri.Scheme != Uri.UriSchemeHttps)
        return false;

    // Block private IP ranges and cloud metadata IPs
    var host = uri.Host;
    if (IPAddress.TryParse(host, out var ip))
    {
        if (ip.IsPrivate() || ip.Equals(IPAddress.Parse("169.254.169.254")))
            return false;
    }
    else
    {
        // Optional: resolve hostname and check IPs
        var addresses = Dns.GetHostAddresses(host);
        if (addresses.Any(ip => ip.IsPrivate() || ip.Equals(IPAddress.Parse("169.254.169.254"))))
            return false;
    }
    return true;
}

Use this validation before any HTTP request. Note: DNS resolution can be spoofed; consider using a sandboxed DNS resolver or blocking by IP after resolution.

2. Use HttpClientFactory with Outgoing Handlers

In ASP.NET Core, register a custom DelegatingHandler with HttpClientFactory to enforce validation for all outgoing requests. This centralizes the logic.

public class SsrfValidationHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri is null)
            throw new ArgumentException("Request URI is required");

        if (!IsUrlAllowed(request.RequestUri.ToString()))
            throw new HttpRequestException("URL is not allowed due to SSRF protection");

        return await base.SendAsync(request, cancellationToken);
    }

    private static bool IsUrlAllowed(string url)
    {
        // Same validation logic as above
        // ...
    }
}

// In Program.cs
builder.Services.AddHttpClient("SafeClient")
    .AddHttpMessageHandler<SsrfValidationHandler>();

Then inject IHttpClientFactory and use the named client "SafeClient" for all external requests.

3. Cloud-Specific Hardening

  • AWS: Enable IMDSv2 (session-oriented) on EC2 instances. This requires a token for metadata access, mitigating simple SSRF. Use the AWS SDK's built-in IMDSv2 support.
  • Azure: The Azure metadata endpoint requires the header Metadata:true. Ensure your application only sends this header when intentionally accessing Azure metadata, not from user input.
  • GCP: The metadata endpoint requires Metadata-Flavor: Google. Same principle: never add this header based on user input.

4. Network-Level Controls

Deploy your ASP.NET application in a VPC with security groups or network policies that block egress to 169.254.169.254 from application servers. This is a failsafe if application-level validation fails.

Finally, integrate scanning into your development lifecycle. Use middleBrick's GitHub Action to automatically test your API in CI/CD. Configure the Pro plan to fail builds if SSRF findings appear, ensuring vulnerabilities are caught before deployment.

Frequently Asked Questions

Can middleBrick detect SSRF vulnerabilities that require authentication to exploit?
No. middleBrick performs unauthenticated black-box scanning only. It tests the publicly accessible attack surface without credentials. SSRF vulnerabilities that require an attacker to be logged in or present a valid session token would not be detected. For authenticated scanning, you would need a different tool or manual testing.
How does ASP.NET Core's built-in HttpClientFactory help prevent SSRF?
HttpClientFactory itself does not prevent SSRF. However, it provides a clean way to inject custom DelegatingHandler instances (like the SsrfValidationHandler shown above) that can validate every outgoing request's URL. This centralizes validation logic and ensures all HttpClient instances created by the factory adhere to the same SSRF protections, reducing the risk of a developer forgetting validation in one part of the codebase.