An IDOR that could have led to stealing money from a Fintech company

Good day, guys, It’s been a while I blogged about my security findings but today I will be talking about a vulnerability I found in a fintech company that would have allowed me to steal money from any customer of the company.

The engagement that resulted in this finding was on a vulnerability assessment and penetration testing engagement so I won’t be saying the name of the company but for the sake of the post, we will be referring to the company as “Lobster”.

About the company:

Lobster whose shortcode is “LS” is a fintech company in Nigeria that provides banking solution to Nigerians and some of their core operations involve: sending and receiving money, paying utility bills like “Nepa” bills, Cable TV, etc, saving and many more without having to go to a bank.

Every account on Lobster is assigned an account number with which you can use to perform your banking transactions, this account number also functions as your user ID. While sending money, you can either send money to a Lobster account using the recipient Lobster account number or using an external bank account.

You can fund your Lobster account with any amount by sending the money from an external account using USSD to your Lobster account number.

Testing Process:

After logging into my Lobster account and funding my account, I navigated to the functionality to send money, entered the amount I wanted to send, and the lobster account number.

A Lobster account number looks similar to this “LS160075625729”. This is required when sending money as the recipient account number is sent in the body of the request and the sender ID is sent in the URL of the request.

Looking at this account number, I was able to deduce that “LS” stands for Lobster, at first glance the numeric characters seem like random numbers generated for users but upon closer look, I realized that “160075625729” is a Unix timestamp. I confirmed this by using an online Unix timestamp converter and I was able to get the human-readable format of those digits which translates to “Wednesday, April 15, 2020 12:39:53 PM” which happened to be the date I created my account. Knowing this, all I need now is to be able to successfully brute force a valid timestamp and hope the application does not validate the user's ID when it is been used by an invalid object(unauthorized user). Luckily for me, it worked and the application does not also have rate-limiting protection in place so I was able to brute force a valid timestamp successfully.

Exploitation:

Having all this information, I decided to first test the lowest functionality that could lead to loss of money which was the functionality to buy airtime by changing the sender ID to a victim ID to see if I will be able to steal money from the victim’s account.

The request to buy airtime looks similar to

Looking at the body of the request, we can see a “userId” parameter which is the Id of the sender. Changing the ID from that to a victim user Id, the victim ID account was debited instead of the attacker account. The same action was carried on the functionality to send money to other Lobster user account or external accounts and I was able to achieve the same action.

With all of these, to massively attack other Lobster user account, we just have to brute force a valid userID and we will be randomly hitting every other user of Lobster and it will only be a matter of time before we hit an admin account.

Thanks.