API security testing case study: a digital bank and its hidden endpoints
A digital bank was about to connect partner companies to its systems. Its mobile app and those partners reach customer accounts through APIs (the connections that let one piece of software ask another for data or actions). The bank wanted to know whether a customer or partner could reach data or functions they should never see.
A bank about to open up to partners
Every service the bank offered ran through APIs: onboarding with electronic identity checks (e-KYC), balances, transfers and e-statements. New partner integrations were weeks away. They had to meet OJK’s expectations on API security (OJK is Indonesia’s financial services regulator) and PCI DSS, the card industry’s security standard.
The engineering team moved fast. New endpoints (the individual addresses an app can call) appeared every sprint. The documentation lagged behind, and different services checked identity in different ways. Manual security review could not keep pace.
Counting what was really there
We started by finding every endpoint, documented or not. The bank’s API documentation listed 84. By combining that documentation with captured app traffic and automated probing, we found 121. The 37 extra endpoints were live in production, and they were on nobody’s list.
Next, we built a simple table of every type of user against every endpoint, showing who should be allowed to do what. Our testers then checked each cell. Can a customer read another customer’s data? Can a partner call a function meant for bank staff? The tests followed the OWASP API Security Top 10 (2023), a public list of the most common API weaknesses, and the API chapters of OWASP ASVS 4.0.
Three problems that mattered
We reported 41 findings: 2 critical, 7 high, 14 medium and 18 low. Three stood out.
The most serious was on the balance endpoint. Account numbers in the request ran in sequence, and the system never checked that the account belonged to the person asking. Anyone logged in could read any customer’s balance by changing a number. All 37 undocumented endpoints shared the same flaw. Testers call this broken object-level authorization, or BOLA.
The second let a partner call a staff-only reversal function. A partner could reverse its own failed transfer and be credited twice. This is broken function-level authorization (BFLA).
The third was in an older login service. It accepted security tokens with no signature at all, and it never replaced long-lived login tokens. Either weakness could let an attacker pose as a real user.
For the bank, the first finding meant a leak of customer data at scale. The second meant money leaving through a partner channel.
Fixing the pattern once
Patching the endpoints one by one would have left the next new endpoint exposed. Instead, the bank rewrote the authorization policy at its API gateway so that every request is refused unless it is explicitly allowed. It also added a shared library that checks account ownership on every call.
Our retest confirmed that both critical findings were closed. The bank then added an API inventory and automated contract tests to its build pipeline, so each new endpoint is tested before it goes live. It used our mapping against the OWASP API Top 10 as technical evidence for OJK.
Notes for the engineering team
Discovery combined OpenAPI specs, traffic capture and fuzz-based enumeration. The critical finding was on GET /accounts/{id}/balance. The BFLA finding was POST /admin/reversal, callable with a partner role. The legacy auth service accepted JWTs with alg=none and did not rotate refresh tokens. Authentication across services mixed JWTs, API keys and mutual TLS. Each finding came with a curl command to replay it and a suggested gateway rule. We also tested for excessive data exposure, mass assignment, injection and missing rate limits.
Banks and fintechs whose apps and partners reach core systems through APIs should assume, as this bank learned, that some endpoints are missing from the documentation.