How to fix Business Logic Errors
in ASP.NET Core
Executive Summary
Business logic errors are the silent killers of ASP.NET Core applications. Unlike SQLi or XSS, scanners won't find these. They occur when the application's design allows an attacker to manipulate the intended workflow. Most common in e-commerce and fintech, these flaws usually stem from trusting client-side input for critical state values like prices, quantities, or permission levels. If your backend trusts the 'Total' field sent from a React frontend, you're begging to be pwned.
The Vulnerable Pattern
[HttpPost("process-payment")] public async TaskCheckout([FromBody] OrderDto order) { // VULNERABILITY: Trusting the client-side calculated total. // An attacker can intercept this request and change 'Amount' to 0.01. var paymentStatus = await _paymentGateway.ChargeAsync(order.CreditCard, order.Amount); if (paymentStatus.Success) { await _orderService.FinalizeOrder(order.Id); return Ok(); } return BadRequest();
}
The Secure Implementation
The vulnerable snippet fails because it treats the incoming DTO as the source of truth for the transaction amount. An attacker using Burp Suite can simply modify the JSON payload to reduce the cost. The secure implementation ignores any price data sent by the client. Instead, it uses the OrderId to fetch the items from the database, recalculates the total based on trusted server-side records, and ensures the order belongs to the authenticated user (preventing IDOR). Rule #1: The client is in the hands of the enemy; use it only for intent, never for state.
[HttpPost("process-payment")] [Authorize] public async TaskCheckout([FromBody] PaymentRequest request) { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; // SECURE: Fetch the source of truth from the database var order = await _context.Orders .Include(o => o.Items) .FirstOrDefaultAsync(o => o.Id == request.OrderId && o.UserId == userId); if (order == null) return NotFound("Order not found or access denied."); // SECURE: Recalculate the total server-side. Never trust client-side math. decimal serverCalculatedTotal = order.Items.Sum(item => item.UnitPrice * item.Quantity); var paymentStatus = await _paymentGateway.ChargeAsync(request.CreditCard, serverCalculatedTotal); if (paymentStatus.Success) { order.IsPaid = true; await _context.SaveChangesAsync(); return Ok(); } return BadRequest("Payment failed.");
}
Your ASP.NET Core API
might be exposed to Business Logic Errors
74% of ASP.NET Core apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
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.