T09 · Insecure Skill Coding Practices
- Location
references/installments.md:107- Finding
Unauthenticated Installment Callback Can Trigger Fraudulent Order Fulfillment
- Content
View full analysis
{ const { sessionId, status, invoiceId } = req.body; if (status === 'approved') { // Fulfill the order for invoiceId fulfillOrder(invoiceId); } // Must return 200 to acknowledge res.status(200).send('OK'); }); ``` ### Technical Analysis The documented callback handler treats the HTTP request body as authoritative and fulfills an order whenever the supplied `status` is `approved`. It does not: - Authenticate the callback sender. - Verify a cryptographic signature. - Query TBC Bank's authenticated status endpoint. - Confirm that `sessionId` belongs to `invoiceId`. - Compare the approved amount and currency with the stored order. - Reject expired or invalid sessions. - enforce idempotency or replay protection. Because a public callback URL must ordinarily be reachable over the Internet, request fields such as `status` and `invoiceId` are attacker-controlled unless the request is authenticated. Following this example directly could therefore turn a forged HTTP request into an order-fulfillment action. The `sessionId` is extracted but not used, which removes an available correlation mechanism. The example also acknowledges every request with HTTP 200 regardless of whether verification occurred. ### Attack Path 1. An attacker discovers or infers the merchant's public installment callback endpoint. 2. The attacker identifies or guesses a target invoice identifier. 3. The attacker submits a forged request such as: ```http POST /installment/callback HTTP/1.1 Content-Type: application/json { "sessionId": "attacker-controlled", "status": "approved", "invoiceId": "TARGET-INVOICE" } ``` 4. The handler accepts the u ...[truncated 1090 chars]- Remediation
View remediation
