Missing Tls in Aspnet with Hmac Signatures
Missing Tls in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Using HMAC signatures in an ASP.NET API without enforcing TLS exposes the signature material and the integrity-protected payload to interception. HMAC ensures that a request has not been altered, but it does not protect confidentiality. If the endpoint is served over HTTP or is missing strict transport security, an on-path attacker can observe the request, capture the signature, and replay it or tamper with the message while the signature remains valid.
In ASP.NET, this often occurs when developers configure signature logic (e.g., using a shared secret) but do not enforce HTTPS at the transport layer or via middleware. Consider a scenario where the signature is computed over selected headers and the request body; without TLS, an attacker performing passive sniffing or a man-in-the-middle can copy the signed request and replay it because the signature does not expire or bind to a channel. This is especially risky when signatures are used for idempotency or authorization, as replay can lead to duplicate transactions or privilege escalation.
Another subtle issue arises when applications accept both HTTP and HTTPS and route based on headers or load balancer configuration. If the signature validation logic does not verify that the request was received over a secure channel, the effective security of HMAC is reduced to integrity alone, with confidentiality and anti-replay guarantees missing. MiddleBrick’s unauthenticated scan detects missing TLS by inspecting the application’s behavior, identifying endpoints that serve signed requests without enforcing transport security.
Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes
Remediation requires two complementary controls: enforce TLS at the infrastructure and application levels, and design signature usage to mitigate replay where appropriate. Always serve APIs over HTTPS and use HTTP Strict Transport Security (HSTS) to prevent downgrade attacks. In ASP.NET, this is typically enforced at the hosting layer and via middleware, not just in application code.
Below are concrete code examples for an ASP.NET Core API that uses HMAC signatures in request headers. The examples show how to compute and validate signatures over selected headers and the body, and how to require HTTPS for signed endpoints.
Server-side signature validation with HTTPS enforcement
// Program.cs or minimal API setup
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// Require HTTPS for all requests (redirect HTTP to HTTPS in development)
builder.WebHost.UseUrls("https://*:5001");
builder.Services.AddHsts(options =>
{
options.MaxAge = TimeSpan.FromDays(365);
options.IncludeSubDomains = true;
options.Preload = true;
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseHsts();
app.UseAuthorization();
app.MapControllers();
app.Run();
Example controller with HMAC validation and HTTPS requirement
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private const string Secret = "super-secret-shared-key"; // store securely, e.g., Key Vault
[HttpPost("purchase")]
[RequireHttps]
public IActionResult Purchase([FromBody] PurchaseModel body, [FromHeader(Name = "X-API-Signature")] string providedSignature)
{
var json = System.Text.Json.JsonSerializer.Serialize(body);
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(Secret));
var computedSignature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(json)));
if (!CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(computedSignature), Encoding.UTF8.GetBytes(providedSignature)))
{
return Unauthorized(new { error = "Invalid signature" });
}
// Ensure the request is fresh to mitigate replay (e.g., check a nonce or timestamp header)
if (!Request.Headers.TryGetValue("X-Request-Timestamp", out var timestampHeader) ||
!DateTimeOffset.TryParse(timestampHeader, out var timestamp) ||
DateTimeOffset.UtcNow - timestamp > TimeSpan.FromMinutes(5))
{
return Unauthorized(new { error = "Request expired or missing timestamp" });
}
// Process the order
return Ok(new { status = "accepted" });
}
}
public class PurchaseModel
{
public string ProductId { get; set; }
public int Quantity { get; set; }
}
Client-side signing example
Clients must compute the signature over the same canonical representation (e.g., sorted JSON body and selected headers) and send it in X-API-Signature, along with a timestamp header to support replay protection.
using System.Security.Cryptography;
using System.Text;
public static class SignatureHelper
{
private const string Secret = "super-secret-shared-key";
public static string ComputeSignature(string jsonBody, long timestamp)
{
var data = $"{timestamp}:{jsonBody}";
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(Secret));
return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(data)));
}
}
// Usage
var body = new { ProductId = "abc", Quantity = 2 };
var json = System.Text.Json.JsonSerializer.Serialize(body);
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var signature = SignatureHelper.ComputeSignature(json, timestamp);
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Signature", signature);
client.DefaultRequestHeaders.Add("X-Request-Timestamp", timestamp.ToString());
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.example.com/api/orders/purchase", content);
These examples show how to combine HTTPS enforcement, HMAC validation, and timestamp checks to reduce the risk of replay and interception. MiddleBrick’s scans verify that endpoints requiring signatures also enforce transport security, helping you detect missing TLS configurations before they are exploited.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |