Dns Cache Poisoning in Aspnet with Bearer Tokens
Dns Cache Poisoning in Aspnet with Bearer Tokens — 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 into a resolver’s cache, causing the application to resolve a domain to a rogue IP address. In an ASP.NET application that relies on Bearer token authentication, this vector can undermine the integrity of token validation and enable request interception or token redirection.
When an ASP.NET app performs outbound HTTP calls (for example to an identity provider or a downstream service) and uses a hostname that is susceptible to DNS poisoning, the poisoned resolution can redirect traffic to an attacker-controlled endpoint. If the application then sends Bearer tokens to that endpoint—whether via Authorization headers or by forwarding tokens embedded in introspection requests—those credentials can be captured, logged, or relayed. This is particularly relevant when token validation logic depends on outbound calls to certificate revocation lists (CRLs) or OAuth introspection endpoints, as a poisoned DNS record can silently redirect those calls.
ASP.NET’s default HTTP client behavior does not inherently validate the provenance of DNS responses, so poisoned entries can persist across requests. Combined with Bearer tokens, which are typically high-value secrets, this creates a scenario where an attacker can observe or substitute tokens without needing to compromise the application server directly. The risk is amplified when applications cache DNS results for extended periods or when they resolve internal service hostnames that share naming patterns with external domains.
An attacker capable of on-path network influence can craft DNS responses that cause the runtime to resolve api.identity-provider.com to a malicious host. If the ASP.NET app subsequently sends an access token to that host, the attacker can harvest tokens and replay them against legitimate services. This does not require code execution on the server, but it does require network position relative to the resolver or the poisoned cache target.
middleBrick detects this class of issue by correlating runtime behavior with spec-defined host resolution patterns and outbound call surfaces, surfacing findings related to unvalidated external redirection and unsafe consumption of network endpoints. While the scanner does not fix DNS infrastructure, it highlights where token-bearing requests traverse potentially compromised resolution paths, enabling teams to apply network-level mitigations and design compensating controls.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on ensuring that token handling and outbound HTTP calls are resilient to DNS manipulation. Use explicit IP endpoints or pinned connections where feasible, validate server identity strictly, and avoid relying on DNS for critical security endpoints. Below are concrete patterns for ASP.NET that reduce exposure when Bearer tokens are used.
1. Prefer explicit IPs or service mesh endpoints for token introspection
When your app must validate tokens via a remote endpoint, resolve the target to a specific IP or use a service mesh address that is not dynamically resolved at runtime. This reduces reliance on DNS and limits the window for poisoning.
services.AddHttpClient("IntrospectionClient", client =>
{
// Use a pinned IP or internal service address instead of a dynamic hostname
client.BaseAddress = new Uri("https://10.0.2.15:8443");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "token_placeholder");
});
2. Use named HttpClient with custom HttpClientHandler for server certificate validation
Ensure that outbound calls validate server certificates and, where appropriate, pin public keys. This prevents an attacker who successfully poisons DNS from impersonating a valid TLS endpoint even if the IP resolves correctly.
services.AddHttpClient("SecureTokenClient", client =>
{
client.BaseAddress = new Uri("https://auth.example.com");
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
// Enforce certificate validation (default); add custom validation or pinning if needed
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator // NOT for production
});
For production, replace the custom validation with a callback that checks certificate thumbprints or public key pins.
3. Avoid placing Bearer tokens in URLs; use headers only
Tokens in query strings can be leaked in logs, browser history, and proxy caches. Always send Bearer tokens in the Authorization header.
// Correct: Bearer token in header
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/resource");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "your-access-token");
// Incorrect: token in query string
// https://api.example.com/resource?access_token=your-access-token
4. Validate audience and issuer in token validation logic
When using JWT Bearer tokens, enforce audience and issuer checks to reduce the impact of token leakage or substitution via DNS attacks.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://auth.example.com";
options.Audience = "api-resource";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://auth.example.com",
ValidateAudience = true,
ValidAudience = "api-resource",
ValidateLifetime = true
};
});
5. Use policy-based authorization with explicit claims checks
After tokens are validated, enforce granular authorization using claims-based policies rather than relying solely on token presence. This limits the blast radius if a token is intercepted through a DNS-poisoned route.
services.AddAuthorization(options =>
{
options.AddPolicy("RequireScope", policy =>
{
policy.Requirements.Add(new ScopeRequirement("api.read"));
});
});
// Example handler
public class ScopeRequirement : IAuthorizationRequirement { public string Scope { get; } }
public class ScopeHandler : AuthorizationHandler<ScopeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ScopeRequirement requirement)
{
var scope = context.User.FindFirst("scope")?.Value;
if (scope != null && scope.Contains(requirement.Scope))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
6. Monitor and restrict outbound calls in ASP.NET
Instrument outbound HTTP calls to log destinations and detect anomalies. Combine this with network-level egress filtering to prevent tokens from reaching unexpected hosts, especially those resolved via mutable DNS records.
// Example: logging outbound request targets
app.Use(async (context, next) =>
{
var destination = context.Request.Headers["Host"];
// Log destination for audit; integrate with your monitoring
await next.Invoke();
});