GuardAPI Logo
GuardAPI
Automated Security Protocol

How to fix Insecure Webhooks
in ASP.NET Core

Executive Summary

Webhooks are essentially unauthenticated entry points unless you enforce cryptographic integrity. Relying on obscurity or IP whitelisting is a failing strategy. In ASP.NET Core, an insecure webhook allows an attacker to forge events, escalate privileges, or poison the database by simply POSTing a JSON blob to your endpoint. To secure this, you must implement HMAC (Hash-based Message Authentication Code) verification to ensure the payload is authentic and untampered.

The Vulnerable Pattern

VULNERABLE CODE
[HttpPost("api/webhooks/receive")]
public async Task InsecureWebhook()
{
    using var reader = new StreamReader(Request.Body);
    var payload = await reader.ReadToEndAsync();
    var data = JsonConvert.DeserializeObject(payload);
// VULNERABILITY: No signature verification. 
// Anyone can POST any JSON to this endpoint.
ProcessEvent(data);

return Ok();

}

The Secure Implementation

The vulnerable code blindly trusts the HTTP request body, making it trivial to spoof. The secure implementation introduces three critical layers: 1. It retrieves a shared secret known only to the provider and the app. 2. It re-computes the HMAC SHA256 hash of the raw request body. 3. It uses CryptographicOperations.FixedTimeEquals for the comparison. This prevents side-channel timing attacks that could allow an attacker to brute-force the signature byte-by-byte. If the hashes don't match exactly, the request is discarded as malicious.

SECURE CODE
[HttpPost("api/webhooks/receive")]
public async Task SecureWebhook()
{
    if (!Request.Headers.TryGetValue("X-Hub-Signature-256", out var signature))
        return BadRequest("Missing signature");
Request.EnableBuffering();
using var reader = new StreamReader(Request.Body, leaveOpen: true);
var payload = await reader.ReadToEndAsync();
Request.Body.Position = 0;

var secret = Encoding.UTF8.GetBytes(_config["WebhookSecret"]);
var payloadBytes = Encoding.UTF8.GetBytes(payload);

using var hmac = new HMACSHA256(secret);
var computedHash = hmac.ComputeHash(payloadBytes);
var headerHash = Convert.FromHexString(signature.ToString().Replace("sha256=", ""));

// Use FixedTimeEquals to prevent timing attacks
if (!CryptographicOperations.FixedTimeEquals(computedHash, headerHash))
    return Unauthorized("Invalid signature");

var data = JsonConvert.DeserializeObject<WebhookEvent>(payload);
ProcessEvent(data);
return Ok();

}

System Alert • ID: 1667
Target: ASP.NET Core API
Potential Vulnerability

Your ASP.NET Core API might be exposed to Insecure Webhooks

74% of ASP.NET Core apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.