HIGH missing tlsaspnetmutual tls

Missing Tls in Aspnet with Mutual Tls

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

When an ASP.NET API is configured to require client certificates (mutual TLS) but fails to enforce transport layer security (TLS) at the server level, the channel between client and server can be downgraded or intercepted. This specific combination—expecting client certificates while the server listens without enforced TLS—creates a scenario where authentication based on certificates is undermined by an unencrypted or weakly encrypted path.

Mutual TLS relies on both parties proving identity through certificates over a cryptographically secured channel. If the server does not require and enforce TLS, an attacker positioned on the network may be able to redirect or manipulate traffic before it reaches the point where client certificate validation occurs. For example, a request could be intercepted in plaintext or routed to a malicious endpoint that terminates TLS independently, bypassing the intended mutual authentication boundary. In ASP.NET applications, this can happen when development settings or misconfigured IIS/Kestrel endpoints allow HTTP alongside HTTPS, or when the server’s certificate bindings do not mandate TLS for all listener endpoints.

Additionally, improper certificate validation in the server can compound the issue. If the server validates client certificates but does so after accepting connections over non-TLS transports, the client certificate may be exposed in cleartext or subject to tampering during initial negotiation phases. Attackers can exploit this by forcing a client to send its certificate over an unencrypted path, then replaying or modifying it. Common missteps include binding certificates to HTTP.sys or Kestrel without corresponding HTTPS enforcement, or using development profiles that disable HTTPS during debugging but remain active in environments where they should be disabled entirely.

Another vector specific to ASP.NET involves the use of HTTP.sys or IIS with mismatched bindings. For instance, a site might listen on port 80 for certain paths while expecting client certs only on port 443. If routing rules or reverse proxies direct traffic to the non-TLS port, the mutual TLS assurance is effectively nullified. OWASP API Security Top 10 categories such as Security Misconfiguration and Broken Object Level Authorization can intersect here when unauthenticated or weakly authenticated paths expose endpoints that should be protected by both transport and certificate checks.

To detect such issues, scanning tools evaluate whether server endpoints enforce TLS before any sensitive authentication handshake, including client certificate exchange. They also check whether certificate validation logic is consistently applied across all routes and whether insecure configurations remain reachable. This ensures that the mutual TLS setup is not only present in code or deployment artifacts but is actually enforced at the network and application layer for every request path.

Mutual Tls-Specific Remediation in Aspnet — concrete code fixes

Remediation centers on enforcing HTTPS across all endpoints and ensuring that client certificate validation is applied before any business logic processes the request. Below are concrete configurations and code examples for ASP.NET Core that demonstrate how to require TLS and validate client certificates robustly.

Enforce HTTPS and Require Client Certificates in Program.cs

var builder = WebApplication.CreateBuilder(args);

// Require HTTPS redirection for all requests
builder.Services.Configure(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

// Add authentication with certificate requirements
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.AllowedCertificateTypes = CertificateTypes.All;
        options.RevocationMode = X509RevocationMode.Online;
        options.ValidationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                // Validate thumbprint, subject, or other custom logic
                var allowedThumbprint = "A1B2C3D4E5F6...";
                if (context.ClientCertificate?.Thumbprint != allowedThumbprint)
                {
                    context.Fail("Invalid certificate thumbprint.");
                }
                return Task.CompletedTask;
            }
        };
    });

builder.Services.AddAuthorization();

var app = builder.Build();

// Enforce HTTPS for all endpoints
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/secure", () => "Mutual TLS verified");

app.Run();

Kestrel Server Configuration with Mutual TLS

Configure Kestrel in appsettings.json to require HTTPS and client certificates:


{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    },
    "Endpoints": {
      "Https": {
        "Url": "https://0.0.0.0:5001",
        "Protocols": "Http2",
        "Certificate": {
          "Path": "path/to/server.pfx",
          "Password": "server-password"
        },
        "ClientCertificateMode": "RequireCertificate",
        "AllowedClients": [ "192.168.1.100" ]
      }
    }
  }
}

With this configuration, Kestrel will reject connections that do not present a valid client certificate and will enforce TLS 1.2 or higher depending on system settings. The AllowedClients filter provides an additional layer by IP, though certificate validation remains the primary authentication mechanism.

IIS or HTTP.sys Integration

When hosting behind IIS or using HTTP.sys directly, ensure that the applicationHost.config or equivalent binding settings require SSL and client certificates. In web.config, set sslFlags to require both client certificates and SSL:

<system.webServer>
  <security>
    <access sslFlags="Ssl, SslNegotiateCert" />
  </security>
  <authentication>
    <clientCertificateMappingAuthentication enabled="true">
      <clear />
    </clientCertificateMappingAuthentication>
  </authentication>
</system.webServer>

Ensure that the server certificate is correctly installed in the local machine store and that the binding includes the correct IP and port. This setup complements the ASP.NET Core authentication logic by enforcing TLS and client certificate requirements at the reverse proxy or host level before requests reach the application pipeline.

Validation and Testing

After applying these configurations, test using a client that presents a valid certificate and verify that requests without TLS or without a valid client certificate are rejected. Use tools like curl with --cert and --key to simulate mutual TLS, and confirm that endpoints do not respond over plain HTTP. Continuous monitoring and scanning help ensure that future changes do not inadvertently reintroduce insecure bindings.

Related CWEs: encryption

CWE IDNameSeverity
CWE-319Cleartext Transmission of Sensitive Information HIGH
CWE-295Improper Certificate Validation HIGH
CWE-326Inadequate Encryption Strength HIGH
CWE-327Use of a Broken or Risky Cryptographic Algorithm HIGH
CWE-328Use of Weak Hash HIGH
CWE-330Use of Insufficiently Random Values HIGH
CWE-338Use of Cryptographically Weak PRNG MEDIUM
CWE-693Protection Mechanism Failure MEDIUM
CWE-757Selection of Less-Secure Algorithm During Negotiation HIGH
CWE-261Weak Encoding for Password HIGH

Frequently Asked Questions

What happens if I configure client certificate validation but do not enforce HTTPS in ASP.NET?
If client certificate validation is enabled while HTTPS is not enforced, clients may establish plaintext HTTP connections that bypass mutual TLS protections. The server could accept or reject certificates only after the connection is established, exposing certificate metadata or allowing downgraded attacks. Always enforce HTTPS via middleware and Kestrel/IIS settings to ensure the TLS layer is active before certificate validation occurs.
How can I verify that my ASP.NET API is enforcing mutual TLS correctly in production?
Use a scanning tool that checks whether endpoints require TLS before certificate exchange and validates that client certificates are enforced. You can also test manually with curl or Postman by omitting the client certificate and confirming the connection is rejected, and by verifying that HTTP redirects to HTTPS are in place.