Background
A Singapore-based payments fintech preparing to launch a card-not-present payment processing API engaged CyberneticsPlus for a pre-launch security assessment. The company was targeting PCI DSS Level 1 certification — required for processing more than 6 million transactions annually — and their QSA (Qualified Security Assessor) had mandated a penetration test before the certification audit.
API scope:
- Payment initiation API (REST, OAuth2 authentication)
- Merchant management API (CRUD for merchant accounts and configurations)
- Webhook delivery system (for payment status notifications)
- Admin API (internal operations team access)
The platform was built on Node.js (Express), with PostgreSQL and Redis, deployed on AWS (EKS).
Assessment Approach
Type: Grey-box — provided with API documentation, test merchant credentials, and one standard API consumer account. Admin API was tested with a read-only admin credential.
Primary focus: OWASP API Security Top 10, PCI DSS API requirements (12.3.2), authentication and authorisation.
Critical Findings
Critical: JWT Algorithm Confusion Attack — Authentication Bypass
Finding: The payment API accepted JWTs signed with either RS256 (RSA) or HS256 (HMAC). The verification logic:
const decoded = jwt.verify(token, publicKey); // Uses RS256
However, when an HS256 JWT was presented, the library interpreted publicKey as the HMAC secret. Since the public key is, by definition, public (available from the JWKS endpoint at /api/.well-known/jwks.json), an attacker could:
- Obtain the server’s RSA public key from the JWKS endpoint
- Sign a forged JWT with HS256, using the RSA public key as the HMAC secret
- Include any desired claims (merchant ID, elevated permissions)
- The server verifies the HS256 signature using the public key → verification succeeds
- Attacker has forged credentials for any merchant account
Proof of concept: CyberneticsPlus forged a JWT claiming to be merchant_id: 1 (the test environment’s highest-revenue merchant) and successfully accessed their payment history, configuration, and initiated a $1.00 test transaction.
Fix: Algorithm explicitly pinned to RS256 in the JWT verification configuration. HS256 requests rejected at middleware level.
Critical: Webhook Signature Not Validated
Finding: The webhook delivery system sent payment notifications to merchant-configured URLs. The receiving merchant’s API was expected to validate the request signature (HMAC-SHA256 using a per-merchant webhook secret). However, the platform’s internal API — used by the merchant team to manually trigger webhook re-deliveries — did not include the webhook signature header.
Impact: Any internal user with access to the re-delivery endpoint could trigger webhook deliveries to merchant URLs without a valid signature. Merchants relying on signature validation to confirm webhooks were from the platform would receive forged notifications.
In a payment context: an attacker who could access the re-delivery endpoint could trigger false “payment_completed” webhook deliveries to merchant systems, potentially triggering product fulfillment without actual payment.
Fix: Webhook signature applied consistently to all delivery paths, including re-deliveries.
High Findings
Excessive Data in API Responses (OWASP API3)
Finding: The /api/v1/merchants/{merchant_id} endpoint returned the full merchant object, including:
internal_risk_score— the platform’s fraud risk assessmentkyc_verification_statusandkyc_rejection_reasonsupport_notes— internal notes added by the operations teamfee_discount_percentage— custom fee negotiated by the merchant (business-sensitive)
None of these fields were documented in the merchant API and all were intended for internal use only.
Fix: Response serialiser updated to explicit allowlist of fields returned to merchant API consumers.
BOLA on Payment Records
Finding: GET /api/v1/payments/{payment_id} returned payment details without verifying the requesting merchant owned the payment. Payment IDs were UUIDs (non-guessable), but the endpoint was vulnerable once a payment ID was known.
In a real attack scenario: a compromised merchant account could access payment data of other merchants if they obtained payment IDs (potentially via the platform’s reporting/export features).
Fix: Ownership check added — every payment query filtered by merchant_id derived from the authenticated JWT claim.
Medium Findings (4 Identified)
- Rate limiting on OAuth2 token endpoint (100 requests/minute — too high; reduced to 10)
- Admin API accessible without IP allowlisting (restricted to office IP range)
- API documentation exposed in production without authentication (Swagger UI at
/api/docs) - Sensitive data in CloudWatch logs (partial card numbers appearing in debug log output)
Remediation Timeline
CyberneticsPlus delivered the report 5 days after assessment completion. The client’s engineering team worked against the following remediation schedule (agreed with QSA):
| Finding | Severity | Fixed Within |
|---|---|---|
| JWT algorithm confusion | Critical | 24 hours |
| Webhook signature gap | Critical | 48 hours |
| Excessive data exposure | High | 5 days |
| BOLA on payments | High | 5 days |
| Rate limiting | Medium | 7 days |
| Admin API IP restriction | Medium | 2 days |
| Swagger UI access control | Medium | 3 days |
| Log redaction | Medium | 7 days |
All findings remediated within 2 weeks. CyberneticsPlus conducted a full retest — all critical and high findings confirmed resolved.
PCI DSS Outcome
The QSA reviewed the penetration test report and retest evidence as part of the PCI DSS Level 1 assessment:
- Requirement 11.3.1 (external penetration testing): satisfied
- Requirement 11.3.2 (internal penetration testing): satisfied by the API assessment scope
- Requirement 6.4.1 (web-facing application security): pentest findings and remediation accepted as evidence
PCI DSS Level 1 certification achieved. The company launched to their first enterprise merchants 8 weeks after the assessment.
The fintech now conducts semi-annual API security assessments — increased frequency (vs. standard annual) due to the high-risk nature of payment processing and the pace of API development.