Exploiting a Banking Playground-Vulnerable Bank Application 🏦
·3673 words·18 mins·
I decided to spend some time playing around with a purposely vulnerable banking application. The goal of this walkthrough is to try replicate common issues I frequently encounter during real-world security assessments and document my thought process, testing approach, and findings.
Kudos to the lab creator, the vulnerabilities built into this project are highly relatable and mirror real scenarios in production environments. We will attempt to exploit them to gain hands-on experience and see how such flaws can be identified, exploited, and most importantly, remediated. At the end, I will be consolidating everything into a structured vulnerability table for easy reference including risk ratings, affected endpoints, and remediation recommendations.
Once the application launches, it’s immediately clear that it mimics the typical features you’d expect in a modern online banking platform. Users can register, log in, view account balances, transfer funds, pay bills, apply for loans, and manage cards. These are core workflows that real financial applications also implement, which makes the lab both engaging and realistic. Our goal here is explore not just the functionality, but also the common vulnerabilities that often accompany such features.
In practice, as an attacker the approach here is to start by mapping out the attack surface and identifying potential entry points. Typical attack vectors that came to my mind based on the features include:
Authentication Bypass Attempts: Testing for weak or misconfigured login mechanisms.
Enumeration Opportunities: Looking for differences in error messages or responses that reveal valid usernames or accounts.
Parameter Tampering: Modifying values in requests (e.g., account numbers, transfer amounts) to see if server-side validation exists.
Checking whether tokens are predictable, improperly scoped, or lacking secure flags well known as session hijacking
Probing for injection flaws in endpoints that handle transactions or search queries.
Business Logic issues: Exploring whether processes like loan approvals, manipulating account balance, unathorized transfer. or card creation can be bypassed or tricked by manipulating request flows.
LLM related vulnerabilties.
For this walkthrough, my review is going to simulate how a real adversary would approach this environment. Instead of following a rigid, structured methodology. I will take a more fluid approach. The idea is to engage with the application as an attacker would. This means
Reconnaissance will happen naturally as I interact with the app and discover features
Exploitation attempts will flow directly from observations, without waiting to complete a checklist.
Technical flaws (e.g., SQL injection, IDOR, broken access controls, weak session handling) will be called out as they appear.
Logic weaknesses (e.g., bypassing approval flows, manipulating transaction limits) we will attempt to exploit on the fo
In addition to the web application, the lab also has set of vulnerable APK. This opens up an entirely different attack surface, mobile security testing. Unlike the web interface, mobile apps introduce unique vectors such as local storage issues, insecure use of device permissions, and reverse engineering opportunities so it will be good to explore that as well.
That said, it’s important to note that in most cases, the backend APIs remain the same. The mobile application is essentially another client communicating with the same API endpoints as the web interface. This means that weaknesses identified on the backend are often exploitable through both channels.They also have some set of vulnerable APk, that will also be interesting to review as the mobile attack surface is quite different from the web but in most cases the backend API calls tend to be the same. I will drop a mobile application review soon
Another key area of interest was the presence of Swagger documentation. This is essentially an interactive blueprint of the backend APIs, providing detailed definitions of available endpoints. Swagger not only reveals the API structure but also expected Payload, data types, response models an in some cases hidden functionality. What I can say is , from a security perspective, this is incredibly valuable.
Having explored the frontend of the application, we can now begin our application security review with the goal of hunting for vulnerabilities. You can fire up proxy tool of your choice, for my case I will be using HTTP Toolkit and configured it with an upstream proxy to Burp Suite.
When it comes to AppSec one of the most crucial steps is to understand the requests being sent and the responses being returned. By analyzing API calls, we uncover what is happening behind the scenes. I always say “”studying request/Response is an intriguing exercise and necessary when it comes to application security.""
To begin, we’ll approach the application from the perspective of a normal user. The most logical starting point is the registration process, since this is often the first interaction any user has with a banking application. Creating an account will help us establish a baseline for how the application logic works and allows us to start interacting with the core features identified earlier.
The application accepts weak or insecure passwords without enforcing any complexity requirements. For instance, passwords such as 12345 or password are allowed without warning or rejection as indicated above.
When attempting to register an account with an existing username, the application responds with a message such as “username already exists.” Attackers can use this to enumerate valid users by automating registration attempts with a list of common usernames or leaked credentials. This greatly aids targeted brute-force or credential-stuffing attacks.
Upon intercepting the registration request, I observed that the application returns excessive and sensitive information in the response payload. This included fields such as accountNumber, debuginfo, account_number, is_admin, and user_ID, these values should never be returned at the point of registration, as they provide unnecessary insights into backend logic and internal identifiers.
Using the information exposed in the registration response (such as is_admin, user_id, and balance), I attempted to manipulate the request body by including additional fields that should not be user-controlled.For my test cases I injected the balance value in the request body (“balance”: 5000) that should not be user-controlled. And just like that the backend accepted this unvalidated parameter and updated the account balance directly of the new user
Issue 5: Privilege Escalation via Mass Assignment#
Since mass assignment is possible, it was also feasible to tamper with the request body by adding an introduce additional parameter, and for my test case I injected is_admin": true and the backend processed this field without validation and created the user with administrative privileges.
With the registration complete, the next step is to authenticate and explore the login functionality. Since login endpoints are high-value targets for attackers, I decided to test for potential SQL Injection (SQLi) vulnerabilities.
I saved the login request (login.req) in my proxy tool, capturing the username and password parameters in the POST body. These fields are prime candidates for injection since they are used directly in the authentication logic.
To automate testing,we can leverage SQLMap, a powerful SQL injection exploitation framework. Because we already have an idea of the backend database engine powering the application, I specified it in the command to speed up detection.
Issue 6: SQL Injection in Login (Boolean-Based Blind)#
Based on the results we can see that the username parameter in the JSON body of the login request is vulnerable to SQL Injection. The parameter is injectable through a Boolean-based blind SQL injection technique using a WHERE/HAVING clause. TThis can allows an attacker to manipulate the SQL queries executed by the backend, enabling database enumeration and data extraction.
Another sensitive functionality in banking applications is the password reset process. In this case, the application uses a 3-digit Reset PIN for verification. This by by design is a red flags, as the total keyspace is only 1,000 possibilities (000–999) trivially brute-forceable by an attackerI created a simple Python script that generates all possible 3-digit PINs and writes them to a wordlist file as shown belowUsing this wordlist, we can perform fuzzing against the reset endpoint to test all possible PINs until the correct one is found. This can be done with tools like Burp Suite Intruder, ffuf, or a custom script. I used ffuf for my case and was able to a get a valid Reset PIN. In worst-case scenario, If administrative or high-value accounts are targeted, full compromise of the platform is possible.
Upon successful login, we are presented with the application homepage. From here,we can interact with typical banking features. At this stage, the focus shifts to capturing and analyzing all API calls made by the frontend as we click around and interact with each feature. Using the proxy setup, every request/response pair is logged for review. This provides us with a complete map of the application’s functionality and backend endpoints.
With this data in hand, we can now proceed to review each feature focusing on what parameters are accepted, what responses are returned, OWASP Top 10 issues, and potential business logic isssues.
Since the application includes a funds transfer functionality, which requires both a sender account and a recipient account number.
I registered a second account so I could perform transfers between the two accounts.
When performing a transfer, the backend request is structured as follows, we can observe how the server processes transfer parameters. With this we can attempt to manipulate values (like amount) to test for potential flaws in transaction validation.
Issue 8: Transfer of Negative Amounts (Business Logic Flaw)#
We can see the aplication allows negative values to be processed as valid transfer inputs. When a negative amount is entered, instead of being rejected, the appkication incorrectly adjusts the account balance. For instance in our case , in our account it had an initial balance of 900 but after making number of “transfer” –100. Instead of reducing the balance, the application recalculated the account balance incorrectly and reflected a new balance of 100, effectively allowing an illegitimate credit.
Beyond negative amount manipulation, another critical test for we can perform is to see if the application is resilient against race condition attacks.
A race condition occurs when multiple requests are sent to the server concurrently, and the backend fails to properly synchronize or enforce consistency. In the context of funds transfers, this could lead to scenarios where fraudulent transactions slip through before validation checks completed
Issue 9: Race Conditions in Transfers & Bill Payments#
Using Burp Suite, I intercepted a normal transfer request between the Sploit Account and the Tuff Account.I configured Burp to queue multiple identical transfer requests targeting the same transaction. Instead of forwarding them immediately, burp held them until I forwarded them all at once.By forwarding all the requests simultaneously, the backend is forced to handle multiple transfer operations on the same account balance at the exact same time. This is con be confirmed in due the reference number
You will note the application accepts proceses all payments and reuses the same transaction reference
While testing the loan application process, I observed that the request is accepted upon submission but still requires approval before it is finalized. This indicates the presence of a maker–checker workflow, where administrative users (e.g., loan officers or managers, administrators) must authorize or reject loan requests.
From an attacker’s perspective, the question should be Can I escalate privileges to register as an administrator? or Can I identify and abuse hidden administrative endpoints?
While reviewing the previously exposed Swagger documentation, I identified an endpoint /admin/create_admin. This is an indication that administrative accounts could be created via the API.
I attempted to interact with the endpoint using the following request:
curl-XPOST"http://192.168.45.143:5000/admin/create_admin"-H"Content-Type: application/json"-d'{"username":"newadmin","password":"adminpass123"}'{Â "error":"Token is missing"}
In our attempt the application needs a valid token, let add a token from the authenticated user, but after adding the token the application still does not accept the request and we get access is denied.It seems the application verifies the token is valid, and also enforces a role or privilege check before allowing access to administrative functionality. Lets actually review decode the token to see the actual values and see if we can pull any jwt based attacksFrom our review in the payload we can see special claim is_admin that is set to false,we can attempt to tamper with it and set it to true to see if we can get admin access.Also there is a posibility if we tamper with the ID we can get another users account and possibly lead to account takeover
For this we are going to forge the jwt token. JWTs are signed using a secret key to ensure integrity. If we modify the payload (is_admin or user_id), the signature will no longer match, and the server should reject the token.
To successfully exploit this, we need to obtain or crack the secret signing key used by the application.
Using tools like jwt_tool.py or hashcat, we can attempt to brute-force the JWT secret key if it is weak or predictable and hulla just like that we have a secret key[+] secret123 is the CORRECT key!
We can verify this using burp suite and re-sign arbitrary JWTs after tampering with the payload claims.
Now lets go ahead an tamper with the payload claim and set admin to true and then retry sending the request again for admin creation
Armed with the forged token, I retried the previously blocked request to create an admin user and this time, the request succeeded, confirming that administrative functionality is now accessible with the tampered token.
curl-XPOST"http://192.168.100.37:5000/admin/create_admin"-H"Content-Type: application/json"-H"Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InNwbG9pdEBnbWFpbC5jb20iLCJpc19hZG1pbiI6dHJ1ZSwiaWF0IjoxNzU4MjIzODIwfQ.H4NlPfYu9842IK1egO2raAymb_nEHFazlaFbt0re5qk"-d'{"username":"newadmin","password":"adminpass123"}'{"message":"Admin created successfully","status":"success"}
Let’s verify the credentials are working, and holla we are in. with this it open up a whole around of other attack vectors we can pull up
The application uses JWTs for session management but relies on a weak secret (secret123) to sign tokens. Once the secret is discovered, attackers can forge arbitrary tokens. By modifying the is_admin claim, I escalated privileges from a normal user to an administrator and successfully created a new admin account.
After confirming that the JWT secret was weak and could be cracked (secret123), I explored whether it was possible to tamper with other claims beyond is_admin.I modified the JWT payload to replace my own user_id with that of another known user:New Token
With the tampered token, I attempted to perform actions as the victim. Specifically, I issued a request to create a virtual card on behalf of this other account.
Issue 11: Account Takeover via JWT user_id Manipulation#
Because JWTs are signed with a weak secret, attackers can re-sign modified tokens. By tampering with the user_id claim, I was able to impersonate another user and perform operations on their behalf, including sensitive actions like creating virtual cards.
While reviewing the transaction history feature, I observed that the application makes API calls that include an account_id parameter to fetch transaction records.
By intercepting and modifying this parameter, I was able to access transaction history records of other customers.Tampering of Account B with ID and we note we can be able see other users transaction history
Issue 12: Insecure Direct Object Reference (IDOR) in Transaction History#
Description: The transactions endpoint is vulnerable to Insecure Direct Object Reference (IDOR). By tampering with the account_id parameter in the request, an attacker can retrieve transaction records belonging to other customers.
While testing the virtual card creation and management functionality, I noted below issues
Issue 13: Lack of Encryption for Sensitive Parameters#
When creating a virtual card, sensitive parameters (such as card type and card details) are transmitted unencrypted within API requests. This makes them susceptible to interception and manipulation if network traffic is compromised.
Issue 14: Lack of Input Validation in Card Creation#
The API accepts arbitrary values for the card_type parameter. Although only two types are valid (Standard and Premium), tampering with the request (e.g., “card_type”: “Gold”) still results in successful card creation.
In the virtual cards created the application has quite a number of actions that can be performed in the card such updating the limit, freeze the card and checking the card detailsWhen performing operations on a virtual card (e.g., updating the limit), the application responds with excessive information such as current balance, Card status and other backend metadata. The data discloses unnecessary insights into the card system’s inner workings.
Issue 16: Mass Assignment in Card Limit Update (Broken Access Control)#
The endpoint /api/virtual-cards/{id}/update-limit is vulnerable to mass assignment. By adding unexpected parameters such as “balance”: 5000 in the request body, I was able to update the current balance of the card, even beyond the limit that had been specified.
Tampered Requestthe application successfully handles the request and updates the current balance in the card which is not meant to be greater than the limit that has been specified meaning there is a broken access control.
Issue 17: Unauthenticated Access to Billers Endpoint#
The /api/billers endpoint responds to requests even without an authentication token. This means attackers can directly query the endpoint without logging into the application
Request ARequest B- After removing the token the application still gives a valid response. The category_id parameter within the request can be manipulated to reveal details of different billers in the system
Overall, the application is good for leaning application security. I’ve enjoyed hunting down some of the same issues I’ve run into during real-world engagements. The fun part? I explored it from scratch, no guides, just recon, tampering, and attempting to breaking things
What I’ve shared here is just the surface. There are definitely more bugs hiding in the code that I didn’t touch or didn’t manage to pick up this round. If you’re reading this, go ahead and dig deeper. you’ll likely find your own paths to break it.
For me, this wasn’t just about the usual web bugs. I’m also keen on diving into LLM vulnerabilities and seeing how the attack surface evolves as AI gets integrated into real-world applications. The game keeps changing, and so does the hunt.
Stay curious. Stay breaking.
If I get some time , I intend to perform source code review to uncover the insecure coding practices that make the application exploitable and how to fix them , am taking it as a challenge.