[Browser Session Start / Proxy Traffic]
↓
[Static RSA Public Key fetched from /auth/auth/key (same key every session, every user)]
↓
[Reverse main.js - locate RSA encryption + Syn-Key/Syn-Signature (timestamp-based)]
↓
[Python script built: Crypto.PublicKey.RSA + PKCS1_v1_5 encrypt + header forgery]
↓
[Client-side crypto fully bypassed → arbitrary plaintext payloads under attacker control]
↓
[Username Enumeration via /auth/2fa/load (valid = masked mobile/email; invalid = generic error)]
↓
[Valid user IDs harvested → userid.txt]
↓
[Submit real OTP once → harvest reusable otpkey (unbound to user/session/transaction, never expires)]
↓
[Account Takeover: Enter the wrong Pass for the Valid usernames and make the ACCOUNTS suspented → POST /auth/auth/reactivateacct (bypassed encryption + new password)]
↓
[Expired or suspended accounts fully reactivated and controlled]
↓
[Fund Transfer Flow → Intercept OTP confirmation request]
↓
[Tamper server response (errorCode:0 + replay harvested otpkey)]
↓
[2FA bypassed → unauthorized transfers executed]
↓
[Full automation: enum → reactivation → mass fund drainage in 10–20 minutes]Hy aLL !! Mr_Curi0sity here !! As usual I began the assessment like any other — proxy open, first request captured. The traffic was fully encrypted end-to-end. Payloads looked opaque, integrity checks appeared solid. For a moment, the classic banking mantra echoed in my head: "It's encrypted, therefore it's safe."
I almost called it a day.
But something felt off. Banking apps that rely heavily on client-side processing often hide their weakest links behind layers of obfuscation. I decided to dig deeper.

What followed was three gruelling days of reverse engineering the application. Using the browser's debugger Network tab, I first identified that the app was fetching a static RSA public key from /auth/auth/key on every session load — the same key, every time, for every user.

Searching for "Syn-Signature && Syn-key" (which played a major role integrity checks ) and "Public" across the loaded JavaScript (JS) bundles in the Sources panel revealed the exact file (`main.js`) responsible for payload construction.
The encryption logic was entirely client-side; the app fetched the public key, RSA-encrypted the request body, and appended a Syn-Key and Syn-Signature header computed from a timestamp.


I decompiled, traced cryptographic routines, mapped key derivation, and dissected how integrity validation worked on the device. This process was slow, frustrating, and at times felt akin to chasing shadows in the dark.

Then the breakthrough came. I wrote a Python script — using `Crypto.PublicKey.RSA` and `Crypto.Cipher.PKCS1_v1_5` — that could re-encrypt arbitrary plain-text payloads with the static public key and recalculate the "Syn-Key" and "Syn-Signature" headers using the same timestamp-based derivation the application used. The illusion of security evaporated. The application now effectively communicated in plain-text, under my control.

The Kill Chain: When Small Cracks Become a Flood
Once the client-side encryption and integrity mechanisms were fully bypassed, the vulnerabilities unfolded like dominoes.
Username Enumeration Accessing /auth/2fa/load with arbitrary usernames produced subtly different responses — a valid username returned an OTP delivery confirmation with mobile and email details partially masked, while an invalid one returned a generic error.



OTP Replay Vulnerability The one-time password system had a critical design flaw: the otpkey token returned by the server upon a valid OTP submission was never bound to a specific user, session, or transaction. It never expired. I could generate a valid otpkey once using any legitimate account and a real OTP, then replay that same token across completely different users and flows.


Sending the same OTP request multiple times confirmed the attack — the server returned a fresh transaction reference number on each replay, incrementing with each submission, proving repeated acceptance without re-verification.

OTP replay to Authentication Bypass — Two Vectors
Expired Account Bypass: Logging in with an expired account username returned a clear "Your account is expired" response in the proxy.

Rather than stopping there, the request was replayed the request directly to /auth/auth/reactivateacct — an endpoint that required no prior authentication. By re-encrypting the body with my bypass script and submitting a new password, the server accepted the reactivation.

The account was then fully accessible with the new credential.

Suspended Account Takeover: The same endpoint worked identically against accounts that had been locked after three failed login attempts. The suspension flag was checked at the login UI layer, but the /auth/auth/reactivateacct endpoint performed no equivalent state validation. The script iterated through userid.txt, executed the reactivation payload for each, and stored the newly set password in "userpassword.txt". At scale, this meant every enumerated account — expired or suspended — could be silently taken over.

OTP Replay to Transaction 2FA Bypassx`
With a harvested OTP key in hand, I moved to the fund transfer flow. After filling out a transfer (recipient bank, account number, beneficiary name, amount), the app prompted for OTP verification before executing. I intercepted the confirmation request in Burp, entered a random OTP, then intercepted the server's response — which correctly returned an expired OTP error.

I replaced the request with a the pre-harvested OTP key.

The server processed the password reset or transfer without any fresh OTP bound to that transaction. The 2FA layer collapsed entirely.
Automation: From Manual Chain to Mass Exploitation With all the pieces aligned, I scripted the entire attack chain. The automation:
● Enumerated valid usernames at scale via the /auth/2fa/load response differential
● Re-encrypted payloads on the fly using the extracted static public key and recalculated Syn-Key/Syn-Signature headers
● Enter the wrong password thrice for the valid usernames In-order to make the account SUSPENDED
● Authenticated via the expired or suspended account reactivation vector, pulling user IDs from userid.txt and writing new credentials to userpassword.txt
● Replayed the stored otpkey across sessions to bypass transaction 2FA and push through fund transfers
Result? In 10–20 minutes, the script could systematically drain the balances of every enumerated account. .

Always test with explicit permission. Stay ethical. Report responsibly.
Curiosity remains the best fuel for discovery.