Payment Village at PHDays 11: how online banking was tested for strength

Tomcat

Professional
Messages
2,689
Reaction score
915
Points
113
Hi all! In our blog, we already talked about the fact that at the Positive Hack Days 11 forum there was a special Payment Village zone, where anyone could look for vulnerabilities in online banking, ATMs (if you missed it, read the detailed write-up) and POS terminals. The competition to discover vulnerabilities in online banking is not new, but in recent years it has been slightly replaced by ethical hacking activities in other financial systems. In 2022, we decided to correct this injustice and created a new banking platform, applying the experience accumulated over all this time. Participants were asked to find typical banking vulnerabilities and report them to us. According to the competition scenario, you could play either as “white hats” (participate in the online bank’s bug bounty program) or as “black hats” (try to steal as much money from the bank as possible).

First of all, we assessed the criticality of each bug found, then we calculated the total number of vulnerabilities that the participant found during the study of the banking system. A reward of 50 thousand rubles was traditionally awarded to the one who discovered the most dangerous gaps - this year the winner was catferq. He found the largest number of vulnerabilities we had introduced, among which were two critical bugs, as well as one bug that even we didn’t suspect existed :). In addition to catferq, other participants who discovered vulnerabilities with a lower level of risk were awarded: hundred303, null1337undefined, kab5fa2hs, HackathonDev and c0rv4x. We thank everyone who took part in our competition: it was very interesting to read your reports and feedback on improving activity.

A little about online banking​

This year we decided not to use previous developments, but to create a new service for the competition from scratch. This problem with an asterisk was taken on by one of the youngest specialists in our team for researching the security of banking systems - he worked on this project under the mentorship of more experienced colleagues. Our online bank consisted of front-end and back-end parts, as well as an automated banking system (ABS). Together with a database (postgres) and cookie storage (redis), it was raised in several containers connected to each other. By the way, the bank is still available - you can study it right now.

To participate in the competition, it was necessary to go through a simple registration, which, according to our idea, already contained shortcomings (we’ll talk about this during the course of the article). Reports could be submitted through a special form, which opened by clicking on the bug on the main page.

00a39fc5a5ec76405dab924d8df28d35.png


To discover the vulnerabilities that we built into the online bank, the participants needed to be smart and use all their pentesting skills.

Defects in authorization and password policy of online banking​

Let's start analyzing the tasks with the entry point for any attacker - the login form to your personal account.

Brute force login form​

During registration, attentive participants may have noticed:
  • weak online banking password policy;
  • The IP address of the attacker who tried to hack accounts by brute-force attacks was not blocked.
Let's look at this case using one of the accounts as an example and try to guess the password for the User1234 account. Despite the large number of attempts to enter an incorrect password, we receive the message invalid username or password every time :

8102f3115ffa0bee991a9ff33439adf6.png


Now let's try to enter the correct password:

9f8a9e932002293a8a036c196a87cd1e.png


As you can see, the answer has changed: the system blocked access to your account for five minutes. In fact, the blocking occurred during one of the attempts to enter an incorrect password. In addition to the fact that the system does not prohibit searching through account data (although it tries to hide it under the message invalid username or password ), participants also had the opportunity to guess passwords for accounts known to them using dictionaries. For example, in the footer of the main page of an online bank, contacts of administrators (username and email address) were indicated, with whom, according to the legend of the competition, participants could contact. Alternatively, you could try to guess the password of one of the administrators using the rockyou dictionary.

Results of the task at PHDays 11: none of the participants were able to detect this vulnerability.

Brute force CVV​

The lack of protection against password brute force in the system opened up another attack opportunity for participants - CVV brute force on bank cards. To obtain the PAN of cards contained in the system, participants could exploit a card data disclosure vulnerability . To use it, it was necessary to take the card data from the system and use it to log into the online bank:

52ee5eaac4f49b748cf587cea0a77286.png


We receive a standard response about incorrectly entered data, run a CVV search and see how during one of the requests the response code changed from 200 to 302. Let’s take a closer look at this request-response.

3d0989b54ff702e30c2d5e7d1b66e5fc.png


This is how the system behaves in only one of a thousand options, which allows us to conclude that in this way it was possible to select the CVV of bank cards known to us.

PHDays 11 challenge results: none of the participants were able to discover this vulnerability.

Brute force one-time code​

When logging into their personal account, participants could optionally enable two-factor authentication. In this case, when entering the correct login and password, the server asked you to additionally confirm your login using a one-time code (OTP):

10d98fe9b8629210d25e75fe64045b7e.png


A one-time code was sent to participants in the Telegram account they specified during registration.

Account verification and receiving OTP for login:

6072d1e8c49166e5f246ee5eb3afe9d9.png


Having tried to enter an incorrect password, we receive a response from the server that the one-time password is incorrect.

79eba2f54fad73d39c2eaf3ea7190e4f.png


We find out empirically that the OTP is changed by the online bank once every thousand entry attempts.

df3d51efd00cb88382d8da8eb763e13c.png


3a0c0c653da9a12381399e3d74cceb75.png


And at this stage, the competition participants should have been wary: the code consisted of four digits. This gives a non-zero chance of guessing the one-time code required for entering. Note that in real banking systems there are stricter, although not always sufficient from an information security point of view, restrictions on sending one-time passwords.

Let's remember a little university (or school) mathematics course. What is the chance of guessing a four-digit number in ten thousand attempts, given that the number changes every thousand attempts? Answer: 1—(0.9) 10 ~ 0.6513, where 0.9 is the probability that during an iteration, while one number is available, it will not be possible to guess it.

If you don’t want to delve into mathematics or come up with your own scripts in Python (or some other language), but want to immediately start the process of crunching numbers, you can use the popular Burp Suite web vulnerability testing utility. Having studied how the server responds in case of successful verification of login data (login, password or OTP), we set a regular expression for the response in the Intruder parameters and launch a brute-force attack.

49bb1d950ee11e42c937309d7903a185.png


As you can see in the screenshot, in this way we managed to guess the one-time code (without looking at the SMS with the password!) on the eighth try, or on the 7317th attempt.

PHDays 11 challenge results: Two participants discovered this vulnerability and sent us a report about it. Interestingly, we did not notice from the logs that any of the participants subsequently exploited it to gain access to accounts. According to our idea, the participants had to brute force the password of one of the administrators (his password was guessed using the Rockyou password brute-force dictionary), and then try to get into the administrator’s account using this vulnerability.

Disadvantages of business logic in OTP​

One of the stages of linking a Telegram account to receive one-time passwords was its verification. Participants were required to enter a special code confirming their account information in the system. Curious hackers would begin to think like this: “we have two Telegram accounts, if we need to link the second one instead of the first one or simply unlink the first one from a specific personal account, what will happen to it in the system? In theory, it should be removed." But is it? We are trying to link it in another personal account. And - lo and behold! — the system does not require you to verify it, but adds it immediately.

d9d52ccd683d4bbeab58bb7de5a11874.png


82e351f450bb13b05c4cff803b1739d0.png


What could this system flaw lead to? A potential attacker can assign the Telegram account of a legitimate user to his personal account without verification, thereby depriving the latter of the opportunity to re-link his own account to his personal account for two-factor authentication. In addition, this business logic error during a complex attack could result in a bank customer being unable to use two-factor authentication from their trusted account. Also, now attackers do not need to fight with a one-time code, but simply select the victim’s credentials. In addition, this vulnerability gives attackers the opportunity to carry out a CSRF attack and link their “lost” account in the system to the victim’s profile, blocking her access to her own personal account. All this makes the user account vulnerable to attacks by intruders.

PHDays 11 challenge results: Only one participant submitted a report on this vulnerability.

Revealing masked data by username​

Another vulnerability in the online bank was the leak of information about card data. Participants could use the leaked data to brute-force CVV cards and exploit credit-related vulnerabilities.

Money transfers can be made using a bank card number or user name in the system. The first method is familiar to each of us, but the second is rarely used to transfer money. Let's look at it in more detail.

Let's make a transfer to one of the users by name:
  • 5572443375087227 — ruble card number of the user who makes a transfer to another user using his name in the system;
  • 8531606207370870 - dollar card number of the user who makes a transfer to another user using his name in the system.

3d821232881da8645e129f58ee27c801.png

The system completed the transaction successfully:

eaada57bb39eb35d90795ea0daeb9114.png

Having checked what the frontend does to receive this data, we will see that in the request to receive transactions, the hidecard parameter is specified with the value true . In response, the server sends “correct” (from an information security point of view) data with a masked card number.

51ac29ead24f26bf83956b4b1af0d19c.png


We repeat the request, but instead of true in the hidecard parameter we set the value to false:

ab42f08141891a77f36d3758e80220ff.png


The screenshot highlights the information that can be obtained by completing a transfer using the name of one of the users. If this were a real banking system, the ability to obtain a card number would not only be a direct violation of PCI DSS requirements [1], but also a loophole that would allow an attacker to make fraudulent payments with little effort . Also in this assignment, it would help participants implement one of the possible scenarios within a complex attack vector, where several simple vulnerabilities are used together to achieve greater effect.

PHDays 11 challenge results: Four participants submitted reports regarding this vulnerability.

Rounding errors​

Another interesting error, which we are adding to our competition not for the first time , is a rounding error. Let’s say if the dollar to ruble exchange rate is 1:60, then for 60 rubles we will get one dollar. What if we try to convert 36 kopecks into cents? The amount will be less than the cost of one cent, but the bank cannot write off 36 kopecks, charging 0 cents. It will round the amount to the nearest $0.01. Thus, for a lower price you can get the same amount, but in foreign currency. In this case, when transferring back, you can return 0.60 rubles. The amount of simple earnings will be 60 36 = 24 kopecks.

In our online banking, we have made this vulnerability a little easier so that members can notice it and take advantage of it.

The user's ruble card number is 7047169154995669, the user's dollar card number is 9384411725418749.

Exchange rates at the bank:

df15d09c5a487e5c746ca1212ab23fab.png


Initial balance of bank cards:

6f92daf48734aa08ea138fc3b8d407ac.png


Let’s transfer, for example, 100 rubles from a ruble card to a dollar card at the current exchange rate.

4ae2b774ee89e93207e058b02d9a8efd.png


The transfer was successful. Let's pay attention to changes in card balances:

543fea7de00ea58aadcb5badf8ebe819.png

Already at this stage, a vulnerability is noticeable: when transferring 100 rubles at the stated rate, the bank’s processing yielded the following number: 1.257861... However, cents are hundredths of a dollar, not thousandths, which is why the system rounded the result up, as required according to the rules of arithmetic. It turned out - 1.26. Thus, we received an extra as much as $0.003.

Let's demonstrate the seriousness of this vulnerability by trying to make money on it. To do this, we will make a transfer in the opposite direction - to a ruble card:

ef59f440ea7e763e9c8748e240e8890b.png


At the current exchange rate it will be 1.26 x 79.5 = 100.17 rubles! The changed card balance confirms this:

0420f31504919ac57f131591ddb5250e.png


On the dollar card we returned to the original value, but the balance of the ruble card became greater than the original. A couple of simple manipulations allowed me to earn 17 kopecks. Imagine what consequences the bank faces if it leaves such a loophole for attackers in real life.

PHDays 11 task results: five participants discovered this vulnerability. Moreover, one of them provided a script that automates the process of making money by exploiting this vulnerability. Fortunately, the developers of the remote banking system, that is, we, did not interfere with him with various one-time passwords and captchas😁. Through automation, he stole a modest 500 rubles to clearly show us the possibility of exploiting the vulnerability. Although if this was a real banking system and real attackers, the created script would have helped steal millions.

Processing loans​

Disadvantages of business logic when issuing loans to one card​

dc1c3e9f8c6e0b57091bc1baab44478e.png

As can be seen from the server's response, the online bank has a limit on the number of loans issued on one card - no more than three. However, Logger Burp Suite shows that we were still able to get four credits on the same card.

First loan request:

3372e652eea6e4c214410fe9ff18bb5d.png


Last request for a loan:

db670b7343f096b29059f5be7deebcda.png


The screenshots confirm that the online bank does not have the stated limitation on issuing a maximum of three loans.

Results of the task at PHDays 11: none of the participants reported this error, although we saw from the RBS system logs that three of them encountered this flaw.

Insecure direct object reference (IDOR)​

When applying for a loan, you are allowed to specify another user’s card as a debit card. This may result in no money being debited from the attacker’s account. You can obtain a card number by exploiting a vulnerability that leaks user card data .

Available cards:

e5201c42f1ba7d95fdd8e58209ad1ceb.png


Operation to write off funds from another user’s card:

0ba352d45e154c7121e202d288b1abec.png


Results of the PHDays 11 task: two participants submitted reports about this vulnerability.

Bypassing the credit limit​

During the study of the system, participants may have noticed that the details of the same card for writing off a loan can only be specified four times. This means that a user who has two cards can take out a maximum of eight loans (this follows from the business logic error described above). These restrictions can be easily bypassed by exploiting a previous vulnerability in the same service. This is what it looks like:

f7388fffdae001a40e6f17830cd799da.png


The screenshot shows that the number of credits written off on the card has reached its maximum. The same thing happens with the second card.

Now let's try to get around the theoretical limit using IDOR:

afaed07b6c198305eb25ad43059e82b0.png


We managed to bypass the limit on the number of loans by indicating the bank card of another user (we obtained its number by exploiting a vulnerability associated with the disclosure of card data by username). A message from the server confirms that there are nine loan applications open, not eight. Below is a screenshot of one of the latest applications.

bceb78d6b0fbf5ddc180038f6799aae0.png


Results of the task at PHDays 11: participants who discovered the previous vulnerability, unfortunately, did not pay attention to the described limitation and did not try to bypass it. We, for our part, also did not identify those who could exploit this flaw unnoticed by us.

Denial of service​

Another gap in the functionality of loans was DoS attacks (Denial of Service). Participants had access to a loan calculator, which allowed them to calculate the number and time of payments for the selected program. Let's look at how DoS could be detected.

First, we send a standard request with an expectation for the near future:

4f6f2dbf4db7d589654835274eb72105.png


It seems that the response time is normal and there are no signs of trouble. But let's play with the period and end_time parameters . First, we change the end_time parameter from 2023 to 2070.

2039f82af0bc2c64d77569ca55cba78e.png


As you can see, adding years increases the server response time. Now let’s change the period parameter from 1 day to 1 hour.

8e67118f03f3f63acee49cdb2d4317da.png


The server response time also increased multiple times, which allows us to conclude that there is a DoS in this functionality.

Please note that we have provided a limit on the number of requests sent for this functionality, since any participant in the competition during testing could accidentally generate many such requests. This could lead to system overload, which would prevent other participants from freely exploring its other elements and subsystems. Therefore, we set a limit: no more than three requests with further blocking of the user for several minutes.

PHDays 11 challenge results: We received only one report of this vulnerability, although we recorded a high load on the system on the first night of the competition. It was caused by the fact that many participants tried to exploit this vulnerability.

RCE vulnerability (Remote code execution)​

It is difficult to overestimate the danger of arbitrary code execution vulnerabilities in critical systems such as online banking. However, such gaps also occur periodically. We took advantage of one of the sensational vulnerabilities of the end of 2021 - CVE-2021-44228, or Log4Shell, by placing a vulnerable version of the Log4j package as part of the bank.

In pursuit of an elegant scenario for completely compromising a banking system through a web vulnerability, we did not notice some errors when compiling the service. Thus, there were two ways to execute arbitrary code, one of which was available for a limited period of time at the very beginning of the competition (thanks to Apache and its default DEBUG logging within itself 🤬). In both cases, to exploit the vulnerability it was necessary to use a PoC from GitHub .

Official way​

Let's look at a permanent way to get a reverse shell using Log4Shell. To do this, you need to capture one of the administrators' accounts, since through their panel you can remove any user from the system. An account can be seized through one of the combinations of simple attacks on the banking system, and the deletion request itself looks like this:

7703e8acb8c83cdff3ce2534a8aa3281.png


Let's exploit Log4j through the username parameter: insert the payload into the parameter and get:

bd86c73a6bf5d3c636b15b1ea77a68bb.png

Operation was successful:

af748a05699b096f99b2a31f1985caa3.png


7a806f77654a27621691e1614d7f3ced.png


Results of the task at PHDays 11: none of the participants reached the stage of exploiting this vulnerability, since they were unable to take over the administrator account.

Unofficial way​

This method was suggested by one of the participants after the end of the competition, so we could not help but talk about it in our article. He used a scanner that discovered this vulnerability by inserting a payload into the cookies of one of the requests. As it turned out later, this method worked with any request to the system. We were very surprised that during the competition no one found this gap and reported it.

First, let's run the script:

ec6618e24a403545b2afbd3a3e13a0e0.png

In BurpSuite Repeater we send any request that we receive from the frontend. In this case it is /sharedData/admins . We inject a request with our IP address into the cookie, having previously started the server on our own to receive a reverse shell:

803d4c1e88228627fea3cc1e5b94b243.png

Profit! We have a reverse shell in the node from the bank's backend :)

e2392b1d77024de80cb4b3483a1d9550.png

Successful exploitation of the vulnerability:

18c9cd8c45ebe6f4daf903bf1ba20810.png

It is worth noting that this method only works once. Apache logs this event with a note that if it occurs again, it will not be logged again (invalid cookie). That is, participants in the competition could take advantage of this vulnerability only once from the moment the service was launched.

CSRF vulnerabilities​

Another weak point in online banking was the ability to carry out CSRF attacks. Attentive readers have probably already noticed that the previously described requests did not use a CSRF token in any form. So, for example, competition participants could generate a series of requests from any website visited by the user to an online bank in order to receive information about his bank cards on his behalf and transfer money from his cards to himself. The system had many features similar to this.

PHDays 11 challenge results: Only one participant reported this security flaw.

Possible attack scenarios, or What is the usefulness of the competition​

By creating Payment Village at Positive Hack Days, our goal was not only to draw attention to potential vulnerabilities in banking systems, but also to help both attackers and defenders understand the possible consequences of cyber attacks on banking systems. How can attackers take advantage of IDORs found in loans, rounding errors in cross-currency transfers, weak password policies, or poorly implemented two-factor authentication? Attack scenarios could be like this:
  • The ability to brute force login passwords allows attackers to obtain the password of one of the administrators.
  • A business logic vulnerability in OTP allows attackers to guess the one-time password. With its help, they can log into the account of one of the administrators. In the future, attackers may not limit themselves to just deleting users, as we described earlier in the article, but also, for example, use Log4Shell to penetrate the bank’s infrastructure.
  • Proper use of rounding errors, as well as automation of currency transfers between your cards, can make attackers rich (participants in our competition for sure 🤑).
  • An error in the business logic in OTP and a CSRF vulnerability allow attackers to change data during an attack on two-factor authentication and link their Telegram account to the personal account of a legitimate user without any verification. It follows that the victim will not be able to log into his personal account on his own - this can only be done by turning to bank representatives for help.

Conclusion​

Despite the fact that we have been holding the competition for several years, some of this year’s tasks seemed non-standard to the participants, and sometimes not entirely obvious. Many participants were looking for standard web vulnerabilities, not taking into account that our competition was primarily aimed at demonstrating the vulnerabilities of banks. We took note of all this and will definitely use it when preparing the next competition next year to make it even more interesting and attract as many participants as possible!

The competition to find vulnerabilities in online banking is available for re-running, although without awards. In August 2022, the banking platform received two updates, as part of which we added new vulnerabilities. Now anyone can improve their pentesting skills all year round on our site 😊.

You can find out more about Payment Village on Telegram. See you at the next Positive Hack Days forum!

Author on Telegram: @geralt_iz_rivii

Payment card industry data security standard (PCI DSS) is a payment card data security standard established by the international payment systems Visa, MasterCard, American Express, JCB and Discover.
 
Top