Man In The Middle in Aspnet with Hmac Signatures
Man In The Middle in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability
In ASP.NET applications, using HMAC signatures to protect request integrity is common, but a Man-in-the-Middle (MitM) scenario can undermine this protection if transport-layer security is missing or inconsistently applied. HMACs ensure that a request has not been altered in transit by validating a signature computed with a shared secret. However, if an attacker can intercept or redirect traffic on an unencrypted channel, they can observe the data in flight and potentially modify both the payload and the signature.
The specific vulnerability arises when an ASP.NET endpoint validates HMAC signatures without first ensuring that the transport is authenticated and encrypted. For example, an attacker positioned between client and server can perform a request replay or tamper with nonces and timestamps if HTTPS is not enforced. Even if the HMAC verifies successfully, the integrity guarantee is only as strong as the channel securing the key exchange and the initial secret distribution. If the secret is transmitted or derived insecurely, an adversary could compute valid signatures for modified requests, effectively bypassing the integrity check.
Additionally, improper handling of clock skew and nonce storage in ASP.NET can compound MitM risks. Without proper replay protection, an intercepted signed request can be resent to the server, potentially leading to duplicate transactions or privilege escalation. The server-side validation logic must ensure that each signature is tied to a one-time nonce or short-lived timestamp, but this protection is insufficient if the attacker can observe and forward valid signed requests over an insecure channel.
Consider an ASP.NET Core API that accepts JSON payloads and expects an HMAC-SHA256 signature in a custom header. If the endpoint does not mandate HTTPS, an attacker on the same network can capture the request, recompute the signature with the observed secret (if weak or exposed), or forward the request while altering non-critical parameters. The server may still validate the signature if the attacker correctly mirrors the signing process, highlighting that HMAC alone does not prevent MitM without strict transport enforcement and secure secret management.
Compliance frameworks such as OWASP API Top 10 and relevant controls in PCI-DSS and SOC2 emphasize the need for authenticated and encrypted channels alongside integrity checks. middleBrick scans identify scenarios where endpoints with HMAC-based integrity lack enforced HTTPS or exhibit weak nonce/timestamp handling, providing prioritized findings and remediation guidance to close the gap between signature validation and transport security.
Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes
To secure HMAC signatures in ASP.NET, enforce HTTPS across the application, validate signatures with strict replay protection, and use cryptographically strong keys managed outside the codebase. The following examples demonstrate a secure implementation pattern for ASP.NET Core.
First, enforce HTTPS redirection and require secure transport in the pipeline:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpsRedirection(options => {
options.HttpsPort = 443;
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Next, implement a robust HMAC validation filter that checks the signature, timestamp, and nonce to prevent replay attacks:
// HmacValidationFilter.cs
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
public class HmacValidationFilter : IAsyncActionFilter {
private readonly IConfiguration _config;
private readonly IMemoryCache _cache;
public HmacValidationFilter(IConfiguration config, IMemoryCache cache) {
_config = config;
_cache = cache;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) {
if (!context.HttpContext.Request.Headers.TryGetValue("X-API-Signature", out var signatureHeader)) {
context.Result = new UnauthorizedObjectResult("Missing signature");
return;
}
if (!context.HttpContext.Request.Headers.TryGetValue("X-API-Nonce", out var nonceHeader) ||
!context.HttpContext.Request.Headers.TryGetValue("X-API-Timestamp", out var timestampHeader)) {
context.Result = new UnauthorizedObjectResult("Missing nonce or timestamp");
return;
}
var nonce = nonceHeader.FirstOrDefault();
var timestampString = timestampHeader.FirstOrDefault();
if (!long.TryParse(timestampString, out var timestamp) ||
DateTimeOffset.UtcNow.ToUnixTimeSeconds() - timestamp > 300) {
context.Result = new UnauthorizedObjectResult("Timestamp expired");
return;
}
if (_cache.Get(nonce) != null) {
context.Result = new UnauthorizedObjectResult("Nonce already used");
return;
}
var secret = _config["HmacSettings:Secret"];
if (string.IsNullOrEmpty(secret)) {
context.Result = new StatusCodeResult(500);
return;
}
using var sha = SHA256.Create();
var body = await new StreamReader(context.HttpContext.Request.Body).ReadToEndAsync();
context.HttpContext.Request.Body.Position = 0;
var data = $"{timestamp}{nonce}{body}";
var computedHash = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(data + secret)));
if (!CryptographicOperations.FixedTimeEquals(Convert.FromBase64String(signatureHeader.FirstOrDefault()), Encoding.UTF8.GetBytes(computedHash))) {
context.Result = new UnauthorizedObjectResult("Invalid signature");
return;
}
_cache.Set(nonce, true, TimeSpan.FromMinutes(5));
await next();
}
}
Register the filter globally or per-controller/action and ensure secrets are loaded from a secure configuration provider:
// Program.cs additions
builder.Services.AddControllers(options => {
options.Filters.Add<HmacValidationFilter>();
});
builder.Services.AddMemoryCache();
These steps ensure that even if an attacker can observe traffic, they cannot forge valid requests without the secret, and replay attempts are blocked by nonce and timestamp validation. middleBrick can detect endpoints where HMAC is present but HTTPS or replay protection is missing, helping you align implementation with OWASP and compliance requirements.