SC-043: API Abuse & Rate Limit Bypass¶
Scenario Header
Type: API Security / Financial Fraud | Difficulty: ★★★★☆ | Duration: 2–3 hours | Participants: 4–8
Threat Actor: Cybercriminal syndicate — API exploitation and financial fraud
Primary ATT&CK Techniques: T1190 · T1059 · T1078.004 · T1499.003 · T1565.001 · T1530 · T1040
Threat Actor Profile¶
RATE BREAKER is a synthetic cybercriminal syndicate specializing in API vulnerability exploitation targeting financial services platforms. The group combines deep technical knowledge of REST/GraphQL API architecture with expertise in financial system business logic. Their operations focus on identifying and exploiting rate limiting gaps, authentication weaknesses, and business logic flaws in payment processing APIs.
RATE BREAKER operates a structured team: reconnaissance specialists who discover and document API endpoints, exploit developers who craft abuse techniques, and operators who execute the attacks at scale. The group sells API exploit kits and "configs" on underground forums, allowing lower-skilled criminals to replicate their attacks against other targets.
Motivation: Financial — direct monetary theft through payment manipulation, fraudulent transactions, and resale of API exploitation toolkits. Average campaign yield: $500K–$2M before detection.
Public Research Context
This scenario is informed by publicly documented API security incidents:
- OWASP API Security Top 10 (2023): Broken Object Level Authorization (BOLA), Broken Authentication, and Unrestricted Resource Consumption are the top 3 API vulnerabilities
- Salt Security State of API Security (2024): 94% of organizations experienced API security incidents — 17% suffered a data breach through an API vulnerability
- Venmo/Cash App race conditions (public disclosures): Multiple fintech platforms have disclosed race condition vulnerabilities in payment APIs that allowed duplicate transactions
- Stripe API key exposure incidents: Thousands of API keys discovered in public GitHub repositories — enabling unauthorized payment processing
All technical details in this scenario are synthetic. No real payment processor data or infrastructure is used.
Scenario Narrative¶
Phase 1 — API Discovery & Reconnaissance (~30 min)¶
FinEdge Payments is a synthetic payment processing company providing REST APIs for e-commerce merchants. FinEdge processes $2.3 billion in annual transaction volume across 14,000 merchant accounts. Their API platform (api.finedge-payments.example.com) handles payment authorization, capture, refund, and settlement operations.
RATE BREAKER begins reconnaissance on FinEdge's API surface:
Step 1 — Public Documentation Mining:
The attacker discovers FinEdge's public API documentation at docs.finedge-payments.example.com, which includes:
- OpenAPI/Swagger specification (
/openapi.json) with all endpoint definitions - Authentication flows (API key + HMAC signature)
- Request/response schemas with example payloads
- Rate limit headers documented:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset - Sandbox environment:
sandbox.api.finedge-payments.example.com(no rate limiting)
Step 2 — API Endpoint Enumeration:
Using the OpenAPI spec and brute-force directory scanning, RATE BREAKER maps the full API surface:
| Endpoint | Method | Purpose | Auth Required | Rate Limit |
|---|---|---|---|---|
/v2/payments | POST | Create payment | API key + HMAC | 100/min |
/v2/payments/{id} | GET | Get payment details | API key | 500/min |
/v2/payments/{id}/capture | POST | Capture authorized payment | API key + HMAC | 100/min |
/v2/payments/{id}/refund | POST | Refund payment | API key + HMAC | 50/min |
/v2/payments/{id}/void | POST | Void payment | API key + HMAC | 50/min |
/v2/merchants/{id} | GET | Merchant details | API key | 200/min |
/v2/merchants/{id}/balance | GET | Merchant balance | API key | 200/min |
/v2/webhooks | POST | Configure webhooks | API key | 20/min |
/v1/payments | POST | Legacy endpoint — deprecated | API key only (no HMAC) | No rate limit |
/internal/health | GET | Health check — exposed | None | None |
/internal/metrics | GET | Prometheus metrics — exposed | None | None |
Step 3 — Vulnerability Identification:
RATE BREAKER identifies four critical vulnerabilities:
- Legacy API without rate limiting:
/v1/paymentsis deprecated but still active, with no rate limiting and weaker authentication (API key only, no HMAC signature) - Exposed internal endpoints:
/internal/healthand/internal/metricsare accessible without authentication, leaking infrastructure details and transaction volume metrics - BOLA on merchant endpoints:
/v2/merchants/{id}and/v2/merchants/{id}/balanceaccept any merchant ID — no authorization check that the API key belongs to the requested merchant - Rate limit bypass via header manipulation: The
X-Forwarded-Forheader is trusted for rate limiting — injecting different IPs resets the rate limit counter
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| WAF Logs | Directory brute-force scan: 14,200 requests to non-existent paths — Source: 192.0.2.30 — Tools: gobuster signature — 2026-02-20T14:00:00Z to 2026-02-20T16:30:00Z |
| API Gateway | Requests to /internal/metrics from external IP 192.0.2.30 — 12 requests — Responses: HTTP 200 with Prometheus metrics including transaction counts, error rates, and active merchant count — 2026-02-20T15:22:00Z |
| API Gateway | Requests to /v1/payments — deprecated endpoint — 340 requests from 192.0.2.30 with test card numbers — 2026-02-20T16:00:00Z to 2026-02-20T17:00:00Z |
| API Gateway | BOLA probing: sequential merchant ID enumeration on /v2/merchants/{id} — IDs 1 through 5,000 — Source: 192.0.2.30 — 2026-02-20T17:30:00Z |
Phase 1 — Discussion Inject
Technical: The attacker discovered a deprecated v1 API that lacks rate limiting and HMAC authentication. What API lifecycle management practices would have prevented this? How should deprecated APIs be decommissioned — sunset headers, traffic monitoring, or hard shutdown?
Decision: The internal metrics endpoint (/internal/metrics) is exposed to the internet. This endpoint reveals transaction volumes, error rates, and active merchant counts. Should internal observability endpoints ever be accessible from external networks? What network architecture prevents this?
Expected Analyst Actions: - [ ] Investigate the directory scanning activity from 192.0.2.30 — this is active reconnaissance - [ ] Audit all API endpoints — identify any that are deprecated, undocumented, or lack proper authentication - [ ] Verify that internal endpoints (/internal/*) are not accessible from external networks - [ ] Review rate limiting configuration — is it IP-based only? Does it trust X-Forwarded-For? - [ ] Check for BOLA vulnerabilities — do API endpoints verify that the authenticated user owns the requested resource?
Phase 2 — Rate Limit Bypass & Authentication Abuse (~35 min)¶
RATE BREAKER exploits the identified vulnerabilities systematically.
Attack Vector 1 — Rate Limit Bypass via X-Forwarded-For:
The API gateway uses the X-Forwarded-For header value for rate limiting instead of the actual source IP. By rotating the X-Forwarded-For value, the attacker bypasses the 100 requests/minute limit entirely:
POST /v2/payments HTTP/1.1
Host: api.finedge-payments.example.com
Authorization: Bearer sk_live_REDACTED
X-Forwarded-For: 10.0.0.1
Content-Type: application/json
{
"amount": 100,
"currency": "USD",
"source": "tok_REDACTED",
"description": "Test payment"
}
By cycling through 10,000 spoofed X-Forwarded-For addresses, RATE BREAKER achieves an effective rate of 10,000 requests/minute — 100x the intended limit.
Attack Vector 2 — BOLA on Merchant Balance Endpoint:
Using a single compromised API key (from a small merchant account merchant_12847), the attacker queries the balance endpoint for all 14,000 merchants:
GET /v2/merchants/merchant_00001/balance HTTP/1.1
Host: api.finedge-payments.example.com
Authorization: Bearer sk_live_REDACTED
Response (should return 403 but returns 200):
{
"merchant_id": "merchant_00001",
"available_balance": 847293.50,
"pending_balance": 124500.00,
"currency": "USD",
"last_payout": "2026-02-19T00:00:00Z"
}
RATE BREAKER enumerates all 14,000 merchant accounts, collecting balance information and identifying high-value targets for the next phase.
Attack Vector 3 — Legacy API Exploitation:
The deprecated /v1/payments endpoint accepts API key authentication without HMAC signatures. Using the compromised API key, the attacker creates payment authorizations on the legacy endpoint without rate limiting:
POST /v1/payments HTTP/1.1
Host: api.finedge-payments.example.com
X-API-Key: pk_live_REDACTED
Content-Type: application/json
{
"amount": 0.01,
"card_number": "4111111111111111",
"exp_month": 12,
"exp_year": 2028,
"cvv": "REDACTED"
}
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| API Gateway | X-Forwarded-For spoofing detected: 10,000 unique X-Forwarded-For values from single source IP 192.0.2.30 — 2026-02-22T08:00:00Z to 2026-02-22T12:00:00Z |
| API Gateway | /v2/merchants/*/balance — 14,000 sequential requests — All from API key sk_live_...12847 — All returned HTTP 200 — BOLA vulnerability confirmed — 2026-02-22T10:00:00Z |
| API Gateway | /v1/payments — 8,400 requests in 1 hour — No rate limiting applied — API key auth only — 2026-02-22T14:00:00Z |
| API Gateway | Error rate on /v1/payments: 34% (card declines) — 66% success rate — 5,544 authorized payments created — 2026-02-22T14:00:00Z |
| Application Logs | Merchant merchant_12847 API key used to query 14,000 other merchant balances — normal activity for this merchant: 50–80 API calls/day to own endpoints only |
Phase 2 — Discussion Inject
Technical: The rate limiter trusts the X-Forwarded-For header for client identification. This is a common misconfiguration in reverse-proxy architectures. How should the rate limiter identify the true client IP when behind a CDN/load balancer? What is the correct way to handle X-Forwarded-For in a multi-proxy architecture?
Decision: The BOLA vulnerability on the merchant balance endpoint exposes the financial data of all 14,000 merchants. This is a critical vulnerability that likely violates PCI DSS requirements. Should FinEdge immediately disable the affected endpoint (impacting legitimate merchants) or deploy a hotfix with authorization checks?
Expected Analyst Actions: - [ ] Block the source IP 192.0.2.30 at the WAF/firewall level - [ ] Revoke the compromised API key sk_live_...12847 - [ ] Audit all API endpoints for BOLA — verify resource ownership checks - [ ] Fix rate limiting to use the true client IP, not X-Forwarded-For - [ ] Disable or properly secure the deprecated /v1/payments endpoint - [ ] Assess data exposure: 14,000 merchant balances accessed without authorization
Phase 3 — Business Logic Exploitation & Financial Fraud (~30 min)¶
RATE BREAKER escalates to their primary objective: financial fraud through business logic exploitation.
Attack Vector 4 — Race Condition on Payment Capture:
The attacker discovers a time-of-check-to-time-of-use (TOCTOU) race condition in the payment capture flow. When a payment is authorized, it can be captured (settled) exactly once. However, sending multiple simultaneous capture requests before the database transaction commits allows the same authorization to be captured multiple times:
Thread 1: POST /v2/payments/pay_ABC123/capture → Check: not captured → Process capture → DB commit
Thread 2: POST /v2/payments/pay_ABC123/capture → Check: not captured (Thread 1 hasn't committed yet) → Process capture → DB commit
Thread 3: POST /v2/payments/pay_ABC123/capture → Check: not captured (Thread 1 hasn't committed yet) → Process capture → DB commit
Result: A single $500 authorization is captured 3 times, resulting in $1,500 deposited to the merchant account.
RATE BREAKER automates this attack:
- Create a payment authorization for $500 using a controlled merchant account
- Send 50 simultaneous capture requests within a 10ms window
- Average success rate: 3–5 duplicate captures per authorization
- Repeat across 200 authorizations over 4 hours
| Metric | Value |
|---|---|
| Authorizations created | 200 |
| Total capture requests | 10,000 (50 per auth) |
| Successful captures | 840 (avg 4.2 per auth) |
| Expected settlement | $100,000 (200 x $500) |
| Actual settlement (fraudulent) | $420,000 (840 x $500) |
| Excess funds (stolen) | $320,000 |
Attack Vector 5 — Price Manipulation via Unsigned Amount:
On the legacy /v1/payments endpoint, the payment amount is client-specified and not cryptographically signed. The attacker creates a payment flow where:
- A legitimate checkout shows $500 to the customer
- The API call to
/v1/paymentssubmits"amount": 0.01instead of500.00 - The payment processes for $0.01 but the merchant's system records it as $500.00
This allows the attacker to purchase high-value goods for $0.01 each through compromised merchant integrations.
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| Application Logs | Race condition: payment pay_ABC123 captured 5 times — Timestamps within 8ms window — Total captured: $2,500 (authorized: $500) — 2026-02-23T09:14:22.001Z to 2026-02-23T09:14:22.009Z |
| Database | 640 duplicate capture records — 200 unique payment IDs with 3–5 captures each — Total excess: $320,000 — 2026-02-23T09:00:00Z to 2026-02-23T13:00:00Z |
| Settlement System | Merchant merchant_12847 settlement queue: $420,000 — Expected (based on authorizations): $100,000 — Discrepancy: $320,000 — Flagged by automated reconciliation at 2026-02-24T06:00:00Z |
| API Gateway | /v1/payments — 340 transactions with amount < 1.00 — Corresponding merchant order records show item values of $200–$800 — Price mismatch pattern — 2026-02-23T14:00:00Z to 2026-02-23T18:00:00Z |
| Fraud System | Traditional fraud rules (velocity, geographic anomaly, card testing) did not trigger — business logic abuse is invisible to transaction-level fraud detection |
Phase 3 — Discussion Inject
Technical: The race condition allows multiple captures of a single authorization. What database-level controls prevent TOCTOU race conditions? Consider: row-level locking, optimistic concurrency control (version fields), idempotency keys, and distributed locks.
Decision: The automated reconciliation system detected the $320,000 discrepancy 21 hours after the fraud began. Should real-time reconciliation be implemented? What is the trade-off between real-time monitoring (higher infrastructure cost) and batch reconciliation (delayed detection)?
Expected Analyst Actions: - [ ] Immediately freeze settlement for merchant merchant_12847 - [ ] Identify all duplicate captures — reverse the fraudulent ones - [ ] Implement idempotency keys on the capture endpoint to prevent race conditions - [ ] Audit the /v1/payments endpoint for price manipulation — compare submitted amounts with merchant order values - [ ] Implement server-side amount validation — the payment amount must match the merchant's order system - [ ] Assess total financial exposure and initiate the fraud recovery process
Detection & Hunting¶
KQL Detection Queries¶
// Detect X-Forwarded-For spoofing — many unique XFF values from single source IP
ApiManagementGatewayLogs
| where TimeGenerated > ago(1h)
| extend XFF = tostring(parse_json(RequestHeaders)["X-Forwarded-For"])
| extend SourceIP = CallerIpAddress
| summarize UniqueXFF = dcount(XFF), RequestCount = count() by SourceIP
| where UniqueXFF > 100 and RequestCount > 500
| sort by UniqueXFF desc
// Detect BOLA — single API key accessing multiple merchant resources
ApiManagementGatewayLogs
| where TimeGenerated > ago(24h)
| where RequestPath matches regex @"/v2/merchants/[^/]+/balance"
| extend MerchantID = extract(@"/v2/merchants/([^/]+)/", 1, RequestPath)
| extend APIKey = tostring(parse_json(RequestHeaders)["Authorization"])
| summarize UniqueMerchants = dcount(MerchantID), RequestCount = count() by APIKey
| where UniqueMerchants > 10
| sort by UniqueMerchants desc
// Detect race condition — multiple captures on same payment ID within short window
AppRequests
| where TimeGenerated > ago(24h)
| where Url contains "/capture"
| extend PaymentID = extract(@"/payments/([^/]+)/capture", 1, Url)
| summarize CaptureCount = count(),
MinTime = min(TimeGenerated),
MaxTime = max(TimeGenerated)
by PaymentID
| extend WindowMs = datetime_diff('millisecond', MaxTime, MinTime)
| where CaptureCount > 1 and WindowMs < 1000
| sort by CaptureCount desc
SPL Detection Queries¶
// Detect X-Forwarded-For manipulation
index=api sourcetype=api_gateway
| stats dc(xff_ip) as unique_xff_values, count as request_count by src_ip
| where unique_xff_values > 100 AND request_count > 500
| sort -unique_xff_values
// Detect BOLA — API key accessing unauthorized merchant resources
index=api sourcetype=api_gateway uri_path="/v2/merchants/*/balance"
| rex field=uri_path "/v2/merchants/(?<merchant_id>[^/]+)/balance"
| stats dc(merchant_id) as merchants_accessed, count as request_count by api_key
| where merchants_accessed > 10
| sort -merchants_accessed
// Detect duplicate payment captures (race condition)
index=api sourcetype=api_gateway uri_path="*/capture" method=POST status=200
| rex field=uri_path "/payments/(?<payment_id>[^/]+)/capture"
| stats count as capture_count, range(_time) as time_window by payment_id
| where capture_count > 1 AND time_window < 1
| sort -capture_count
Indicators of Compromise (IOCs)¶
Synthetic IOCs — For Training Only
All indicators below are synthetic and generated for educational purposes. Do not use in production detection systems.
| Type | Indicator | Context |
|---|---|---|
| IP Address | 192.0.2.30 | Primary attack source — reconnaissance and exploitation |
| Domain | api.finedge-payments.example.com | Target API (synthetic) |
| Domain | sandbox.api.finedge-payments.example.com | Sandbox environment used for testing |
| API Endpoint | /v1/payments | Deprecated endpoint — no rate limit, weak auth |
| API Endpoint | /internal/metrics | Exposed internal endpoint |
| API Key | sk_live_...12847 | Compromised merchant API key |
| Merchant ID | merchant_12847 | Compromised/attacker-controlled merchant account |
| HTTP Header | X-Forwarded-For with rotating values from single source | Rate limit bypass technique |
| Behavior | >10 unique merchant IDs queried per API key per hour | BOLA exploitation indicator |
| Behavior | >1 capture per payment ID within 1-second window | Race condition exploitation |
| Behavior | Payment amounts <$1.00 with order values >$200 | Price manipulation indicator |
Full Attack Timeline¶
| Time | Event | ATT&CK ID |
|---|---|---|
| 2026-02-20 14:00 | API reconnaissance — directory brute-force scanning | T1190 |
| 2026-02-20 15:22 | Internal metrics endpoint discovered and queried | T1530 |
| 2026-02-20 16:00 | Legacy /v1/payments endpoint discovered and tested | T1190 |
| 2026-02-20 17:30 | BOLA probing — merchant ID enumeration | T1530 |
| 2026-02-22 08:00 | Rate limit bypass via X-Forwarded-For spoofing | T1499.003 |
| 2026-02-22 10:00 | BOLA exploitation — 14,000 merchant balances exfiltrated | T1530 |
| 2026-02-22 14:00 | Legacy API exploitation — 5,544 unauthorized payments | T1190 |
| 2026-02-23 09:00 | Race condition exploitation — duplicate captures begin | T1565.001 |
| 2026-02-23 13:00 | Race condition exploitation complete — $320,000 excess | T1565.001 |
| 2026-02-23 14:00 | Price manipulation via legacy API — $0.01 payments for $500 goods | T1565.001 |
| 2026-02-24 06:00 | Automated reconciliation flags $320,000 discrepancy | — |
| 2026-02-24 08:00 | Incident response initiated — merchant account frozen | — |
Lessons Learned¶
Critical Failures¶
-
Deprecated API left active: The
/v1/paymentsendpoint was marked deprecated in documentation but remained fully functional with no rate limiting and weaker authentication. API deprecation must include a hard sunset date with traffic monitoring and eventual decommissioning. -
Rate limiting based on spoofable header: Using
X-Forwarded-Forfor rate limiting without validating the header chain allows trivial bypass. Rate limiting must use the true client IP determined by the outermost trusted proxy. -
No object-level authorization: The merchant balance endpoint performed authentication (valid API key) but not authorization (does this key belong to the requested merchant). BOLA/IDOR vulnerabilities are the #1 API security risk per OWASP.
-
No race condition protection: The payment capture endpoint lacked idempotency controls, optimistic concurrency, or database-level locking. Financial transaction endpoints require atomic operations with proper concurrency control.
-
Internal endpoints exposed:
/internal/healthand/internal/metricswere accessible from the internet, leaking infrastructure details and transaction metrics that aided reconnaissance.
Recommended Controls¶
| Control | Priority | OWASP API Risk |
|---|---|---|
| Implement object-level authorization on all resource endpoints | Critical | API1:2023 (BOLA) |
Fix rate limiting — use true client IP, not X-Forwarded-For | Critical | API4:2023 (Unrestricted Resource Consumption) |
Decommission deprecated /v1/payments endpoint | Critical | API9:2023 (Improper Inventory Management) |
| Implement idempotency keys and database locking on capture/refund endpoints | Critical | API8:2023 (Security Misconfiguration) |
| Restrict internal endpoints to private networks only | Critical | API8:2023 (Security Misconfiguration) |
| Implement server-side amount validation — cryptographically sign order amounts | High | API3:2023 (BOPLA) |
| Deploy real-time transaction reconciliation (not batch) | High | — |
| Implement API key scoping — keys should only access own merchant resources | High | API1:2023 (BOLA) |
| Deploy API security gateway with behavioral analysis | Medium | API4:2023 |
| Conduct regular API security assessments (OWASP API Top 10) | Medium | — |
Cross-References¶
- Chapter 30: Application Security — API security, OWASP Top 10, and web application attack vectors
- Chapter 30: Application Security — Secure development, business logic security, and race condition prevention
- Chapter 35: DevSecOps Pipeline — API security testing in CI/CD, DAST for APIs, and security automation