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
urlquery parameter and usesHttpClientto 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
targetUrlfield. 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-UrlorRefererfor 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(requiresMetadata:trueheader) - GCP:
http://metadata.google.internal/computeMetadata/v1/(requiresMetadata-Flavor: Googleheader)
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.