Phishing Api Keys in Aspnet with Hmac Signatures
Phishing API Keys in ASP.NET with HMAC Signatures — how this specific combination creates or exposes the vulnerability
When API keys are embedded in ASP.NET applications and used with HMAC signatures, a phishing risk arises if the application reveals or mishandles the key during signature generation or transmission. HMAC relies on a shared secret to sign requests; if an attacker can phish the key, they can forge valid signatures and impersonate the client or server.
In ASP.NET, a common pattern is to store an API key in configuration and use it to compute an HMAC over request data (e.g., payload or selected headers). If the application logs the key, exposes it in error messages, or transmits it in an unauthenticated request, a phishing vector is introduced. For example, an attacker might lure a developer or operator to a malicious endpoint that captures the key, or trick the application into sending a signature that can be reused in a different context.
Consider an ASP.NET Core service that signs a JSON body using HMAC-SHA256. If the signing route does not enforce strict authentication and the client-supplied data is not carefully validated, an attacker may phish the key by observing a single valid signed request and extracting the key through offline cryptanalysis or by leveraging weak key management. Weak key storage in ASP.NET (e.g., plain text in appsettings.json without runtime protection) further increases the risk that a phished key remains usable.
Real-world attack patterns mirror findings from OWASP API Top 10 and similar frameworks: compromised credentials lead to unauthorized access, and replay of signed requests can occur when nonces or timestamps are omitted. For instance, if the signature is computed over the request body but the server does not enforce strict schema validation and replay protection, a phished key and a captured request can be reused to perform unauthorized actions.
Using middleBrick, such risks are identified by checks for unsafe consumption, input validation, and authentication. The scanner inspects the unauthenticated attack surface of your ASP.NET endpoint and flags whether signatures are generated or verified in a way that could expose secrets, without requiring credentials.
HMAC Signatures-Specific Remediation in ASP.NET — concrete code fixes
To mitigate phishing risks around HMAC signatures in ASP.NET, use constant-time comparison, avoid leaking the secret, and ensure proper request validation. Below are concrete code examples for generating and verifying HMAC-SHA256 signatures safely.
Server-side verification with constant-time comparison
using System;
using System.Security.Cmac;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
public class HmacValidationMiddleware
{
private readonly RequestDelegate _next;
private readonly byte[] _apiKey;
public HmacValidationMiddleware(RequestDelegate next, IConfiguration configuration)
{
_next = next;
// Retrieve key securely at runtime (e.g., from Azure Key Vault or environment)
var keyBase64 = configuration["Hmac:ApiKeyBase64"];
_apiKey = Convert.FromBase64String(keyBase64);
}
public async Task InvokeAsync(HttpContext context)
{
// Expects header: X-API-Signature
if (!context.Request.Headers.TryGetValue("X-API-Signature", out var receivedSignature))
{
context.Response.StatusCode = 401;
return;
}
// Compute signature over the raw body (or selected canonical parts)
string body;
using (var reader = new System.IO.StreamReader(context.Request.Body))
{
body = await reader.ReadToEndAsync();
}
// Restore stream for downstream middleware if needed
context.Request.Body = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(body));
string computedSignature;
using (var hmac = new HMACSHA256(_apiKey))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
computedSignature = Convert.ToBase64String(hash);
}
// Use constant-time comparison to prevent timing attacks
if (!ConstantTimeEquals(computedSignature, receivedSignature))
{
context.Response.StatusCode = 401;
return;
}
await _next(context);
}
// Constant-time comparison to avoid timing leaks
private static bool ConstantTimeEquals(string a, string b)
{
if (a.Length != b.Length)
return false;
var result = 0;
for (var i = 0; i < a.Length; i++)
{
result |= a[i] ^ b[i];
}
return result == 0;
}
}
Client-side signing example
using System;
using System.Security.Cmac;
using System.Security.Cryptography;
using System.Text;
public static class HmacSigner
{
public static string ComputeSignature(string body, string apiKeyBase64)
{
var key = Convert.FromBase64String(apiKeyBase64);
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
return Convert.ToBase64String(hash);
}
}
}
// Usage example (do not log or expose apiKeyBase64):
// string signature = HmacSigner.ComputeSignature(requestBody, apiKeyBase64);
Best practices to reduce phishing and replay risks
- Never log, print, or expose the API key in error messages or telemetry.
- Store keys securely at runtime (e.g., environment variables, secret stores) and avoid plain-text configuration in source control.
- Include a timestamp or nonce in the signed payload and enforce short validity windows to prevent replay.
- Validate and normalize the request canonicalization (e.g., selected headers, body) before signing to avoid signature malleability.
- Use HTTPS to prevent on-path interception of signed requests and keys.
These practices align with checks in middleBrick’s authentication, input validation, and unsafe consumption scans, which surface risks where HMAC usage may inadvertently expose secrets or allow phishing-based forgery.