Dns Cache Poisoning in Aspnet with Mutual Tls
Dns Cache Poisoning in Aspnet with Mutual Tls — how this specific combination creates or exposes the vulnerability
DNS cache poisoning (also known as DNS spoofing) occurs when an attacker injects a malicious DNS response that causes a resolver to cache an incorrect mapping between a hostname and an IP address. In an ASP.NET application that uses mutual TLS (mTLS), the client authenticates the server using a server certificate, and the server may also request a client certificate. While mTLS protects the transport channel and ensures endpoint identity, it does not inherently prevent a poisoned DNS entry from directing the client to a rogue server that presents a valid certificate for the expected hostname.
Consider an ASP.NET application that resolves a backend service hostname at startup or on each request. If the hostname resolves to a poisoned IP, the application’s HTTP client (e.g., HttpClient or HttpWebRequest) will connect to the attacker-controlled IP. If the attacker’s server presents a certificate that chains to a trusted CA for that hostname, mTLS will succeed from a certificate validation perspective, and the client may unknowingly send sensitive requests or receive tampered responses. This is especially relevant when the server presents a client certificate for authentication, because the client may still accept the server’s certificate if name validation is not strictly enforced.
The combination of DNS cache poisoning and mTLS in ASP.NET can expose applications to several risks:
- Man-in-the-middle (MITM) against backend services: An attacker who can poison DNS for a service name used by your ASP.NET app can intercept traffic if they present a certificate trusted by your client or server trust stores.
- Bypassing expected network boundaries: Applications may assume that mTLS confines communication to known hosts; poisoned DNS can redirect traffic to unintended endpoints that satisfy certificate validation.
- Downgrade or redirection attacks: If the poisoned record maps a hostname to an IP under attacker control, they can terminate TLS with a valid certificate and perform protocol-level tampering before the application inspects responses.
Importantly, mTLS does not prevent DNS cache poisoning; it only ensures that, if the client proceeds with the connection, the server’s certificate must be valid and trusted. Therefore, defenses must be applied at the DNS layer and in certificate validation practices within the ASP.NET application.
To mitigate this risk in ASP.NET, ensure strict certificate validation, including hostname verification, and avoid relying solely on mTLS for endpoint authenticity. Use hardened DNS resolvers, DNSSEC where available, and consider application-level mechanisms such as certificate pinning or authorization of expected IPs or hostnames. The following sections outline concrete remediation steps and code examples for enforcing robust certificate validation in ASP.NET when using mutual TLS.
Mutual Tls-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on ensuring that your ASP.NET client validates server certificates correctly, enforces hostname alignment, and does not inadvertently trust certificates that do not match the expected service identity. Below are code examples for both server-side and client-side configurations in ASP.NET Core.
Server-side mTLS setup (ASP.NET Core)
The server requires a certificate for TLS and optionally requests a client certificate. Configure Kestrel to require client certificates and use explicit certificate validation callbacks to enforce strict checks.
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Security.Cryptography.X509Certificates;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificate = new X509Certificate2("server.pfx", "password");
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.AllowAnyClientCertificate(); // Avoid this in production; use custom validation.
});
});
});
// Optional: custom client certificate validation
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
{
// Perform strict validation: check chain, revocation, and custom policies
if (cert == null) return false;
if (!cert.Issuer.Contains("YourTrustedCA")) return false;
// additional custom checks, e.g., thumbprint or subject constraints
return chain?.Build(cert) ?? false;
};
});
});
var app = builder.Build();
app.UseHttpsRedirection();
app.MapGet("/", () => "Secure mTLS endpoint");
app.Run();
Client-side mTLS with strict server certificate validation
In your ASP.NET client (e.g., a backend service calling another API), enforce hostname verification and validate the server certificate chain explicitly. Do not use ServerCertificateCustomValidationCallback to bypass checks.
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
var handler = new SocketsHttpHandler
{
SslOptions = new System.Security.Authentication.SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
{
if (cert == null) return false;
// Ensure the certificate matches the expected hostname
if (!cert.Subject.Contains("CN=expected-service.example.com")) return false;
// Validate chain and policy (e.g., revocation)
chain?.Build(cert);
// Optionally check enhanced key usage for server auth
foreach (var extension in cert.Extensions)
{
// Implement specific OID checks if needed
}
return errors == SslPolicyErrors.None;
},
// Enforce TLS 1.2 or 1.3
EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13,
},
};
using var client = new HttpClient(handler);
// Now use client to call the mTLS-protected service
var response = await client.GetAsync("https://expected-service.example.com/api/values");
response.EnsureSuccessStatusCode();
Additional hardening recommendations
- Pin server certificates or public keys in the client where appropriate to reduce reliance on DNS and CA trust for critical services.
- Use multiple, independent DNS resolvers and monitor for DNS anomalies in your environment.
- Combine mTLS with application-level identity tokens or assertions to ensure that the authenticated peer is also logically authorized beyond certificate validation.