HIGH ssrfaspnetmutual tls

Ssrf in Aspnet with Mutual Tls

Ssrf in Aspnet with Mutual Tls — how this specific combination creates or exposes the vulnerability

Server-Side Request Forgery (SSRF) in an ASP.NET application becomes more nuanced when Mutual TLS (mTLS) is enforced. With mTLS, the server presents a certificate and also requires the client to present a valid certificate. This setup is typically used to authenticate and authorize services or partners that call the API. SSRF occurs when an attacker can coerce the server into making arbitrary outbound requests to internal or external endpoints.

In an ASP.NET context, SSRF often arises through user-supplied URLs used with HttpClient, HttpWebRequest, or third-party HTTP clients. Even when mTLS is in place for inbound calls, the server’s outbound HTTP client may not enforce the same strict certificate validation or may be configured to use a default handler that does not verify the server identity of the target endpoint. This can allow an attacker to supply an internal address (e.g., http://169.254.169.254/latest/meta-data/ on cloud instances) or a sensitive internal service that the server-side mTLS client trusts implicitly because it does not validate the target’s certificate properly.

The combination of mTLS and SSRF can be dangerous because mTLS ensures strong authentication for incoming requests but may create a false sense of security for outgoing requests. If the ASP.NET application does not validate the server certificate of the outbound target, an attacker can tunnel through the server to reach internal services that are not exposed externally. Additionally, if the server’s outbound client respects proxy configurations or insecure fallback settings, it may inadvertently route requests through internal networks or bypass expected certificate checks.

For example, an attacker might send a crafted request to an endpoint like /api/fetch?url=http://169.254.169.254/latest/meta-data/. Even though the inbound call is protected by mTLS, the server’s outbound HTTP call may not enforce certificate pinning or hostname verification, allowing the request to reach the metadata service. This can lead to exposure of sensitive cloud metadata, internal service URLs, or credentials that are reachable only from within the network.

middleBrick detects SSRF patterns by correlating OpenAPI/Swagger specifications with runtime behavior, including how user input flows into HTTP client calls. It flags endpoints that accept URLs and perform outbound requests without strict certificate validation or network isolation, even when mTLS is used for inbound authentication.

Mutual Tls-Specific Remediation in Aspnet — concrete code fixes

To mitigate SSRF in ASP.NET applications that use Mutual TLS, you must enforce strict certificate validation for all outbound HTTP calls and avoid using user-supplied URLs to construct requests. Below are concrete code examples illustrating secure practices.

1. Configure HttpClient with custom ServerCertificateCustomValidationCallback

Use HttpClientHandler with a callback that validates the server certificate against a known set of policies, including hostname verification.

using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
// Replace with specific validation logic
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
    if (errors == SslPolicyErrors.None)
        return true;

    // Example: allow only specific thumbprint for internal services
    const string allowedThumbprint = "A1B2C3D4E5F6...";
    if (cert is X509Certificate2 cert2)
    {
        return cert2.Thumbprint == allowedThumbprint;
    }
    return false;
};

using var client = new HttpClient(handler);
var response = await client.GetAsync("https://internal-service.example.com/data");

2. Enforce certificate pinning and hostname validation

Avoid accepting any certificate for internal endpoints. Validate the hostname and certificate chain explicitly.

handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
    if (message.RequestUri.Host.EndsWith("internal.example.com", StringComparison.OrdinalIgnoreCase))
    {
        // Perform chain validation and check thumbprint or public key
        if (errors == SslPolicyErrors.None)
        {
            // Additional checks: policy chain, revocation, etc.
            return true;
        }
    }
    return false;
};

3. Avoid user-supplied URLs for outbound requests; use allowlists

Instead of passing a user-provided URL directly to HttpClient, map it to a predefined set of endpoints.

// Example: map a short identifier to a known base URL
public string MapToKnownEndpoint(string resourceKey)
{
    return resourceKey switch
    {
        "orders" => "https://api.example.com/v1/orders",
        "profile" => "https://api.example.com/v1/profile",
        _ => throw new ArgumentException("Unknown resource")
    };
}

var url = MapToKnownEndpoint(userInput);
var response = await client.GetAsync(url);

4. Use typed clients and configure policies in Startup or Program.cs

Leverage ASP.NET Core’s typed clients to encapsulate secure HTTP calls with predefined handlers.

// Program.cs
builder.Services.AddHttpClient("SecureClient", client =>
{
    client.BaseAddress = new Uri("https://internal-service.example.com");
})
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
    {
        // Enforce mTLS by checking client cert if required and validating server cert
        return ValidateServerCertificate(message, cert, chain, errors);
    }
});

// Usage
var client = serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient("SecureClient");

5. Validate input and reject private IP ranges

Ensure that user-supplied URLs do not point to private or local network ranges.

bool IsPrivateUri(Uri uri)
{
    if (!uri.IsAbsoluteUri) return true;
    var host = uri.Host;
    if (IPAddress.TryParse(host, out var address))
    {
        return IPAddress.IsLoopback(address) ||
               address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork &&
               (address.GetAddressBytes()[0] == 10 ||
                (address.GetAddressBytes()[0] == 172 && address.GetAddressBytes()[1] >= 16 && address.GetAddressBytes()[1] <= 31) ||
                (address.GetAddressBytes()[0] == 192 && address.GetAddressBytes()[1] == 168));
    }
    // Optionally: check known private hostnames
    return false;
}

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

Does mTLS prevent SSRF in ASP.NET applications?
No. Mutual TLS secures inbound client-to-server authentication but does not inherently protect outbound server-to-server calls. SSRF can still occur if outbound HTTP clients do not validate server certificates or allow user-supplied URLs.
How does middleBrick handle SSRF detection in ASP.NET scans?
middleBrick scans the unauthenticated attack surface and maps findings to the OpenAPI/Swagger spec and runtime behavior. It flags endpoints that accept user-controlled URLs and perform outbound requests without strict certificate validation, even when mTLS is used for inbound traffic.