Read previous: How to rob an online bank 2
Mitja Kolsek explains limit checks bypassing, HTTP parameter pollution, SQL injection and signature exploiting as e-banking heist methods, based on pen testing.
Next thing – bypassing limit checks. Banks like to impose limits on us. They don’t like us to transfer one million EUR from our account if we don’t have them, and I understand them, I wouldn’t do that either. But due to errors in business logic, you can possibly find ways to bypass that, because maybe there is insufficient validation on the server or any other thing.
Let me just show you what can happen if you find that. You have two accounts: one with 100 EUR, the other one empty. If you can bypass the limitations, and it can be possible because code is written by people and we make errors, this is the case: no extra money is in existence now because the total is the same as before. But you actually have a huge minus on one account and a huge plus on the other account (see image).
Now, if you are an honest guy you would add those two together and say: “Yes, I owe the bank.” You would probably be worse off because you would be paying a lot of interest for the overdraft. But if you are a criminal, you would just take those million EUR and go to Hawaii, and forget about the debt to the bank. That is why the bank does not want you to make larger overdrafts than those that they authorized you. This was actually a case in one of our pen tests.
Next case is HTTP parameter pollution. This is a class of HTTP vulnerabilities discovered by Luca Carettoni and Stefano di Paola. It’s a very good idea actually, let me show what this means in the banking system. So, we have a communication between the user and the online banking server which is running a JSP1 code at this time, and the back-end server running a PHP code. It’s not very usual for back-end servers to run PHP code, but for our example here, let’s suppose it’s so.So, the user wants to transfer 100 EUR from account one to account two. Now, the code on this JSP server reads the arguments from the URL and does some validation. If not user authorized for source account – then error, so I cannot actually provide another person’s account to the server, they would reject that. And also, it makes a test that if I do not have enough disposable funds on my account, I also get an error. This is typical validation of the user data (see image).
Now, the code says: “If those checks were okay, then I am going to forward that request to the back-end server.” And it does that in another POST2 transaction, so it just forwards the same parameters that we used before to the back-end server. The back-end server reads those parameters and does the transaction, that’s it.
The HTTP parameter pollution is this: we add another argument to the URL, it doesn’t have to be a URL; it can be in POST data as well. So, we have two source arguments here. The guys who were researching HTTP parameter pollution analyzed various servers and frameworks in terms of what they do if they encounter two parameters with the same name. It turns out that in JSP it takes the first parameter. So, we have the same situation as before. Now, when the request is forwarded to the back-end, PHP takes the second parameter (see image). This can be used for bypassing validation on the first server.
But of course no one is that silly, so we have another layer of authorization in the back-end. We say if the user is not authorized for the source account, we are not going to complete the transaction. We can still do something else: we can change the amount, so now we have two amount arguments, and all validation will pass correctly, although the back-end will have the amount of 100,000 EUR which I do not have on my account (see image). So, this is a perfect example of a vulnerability that allows you to do some of the things that I mentioned before – bypassing limit checks.
SQL injection – well, it’s pretty boring, but you still have it everywhere, and of course you also have it in online banking systems. It’s funny that when we talk to the banks before the pen test, we always get skeptical looks, and they say: “No, SQL injection will not be possible in our case.” And they have hundreds of reasons. But we always find at least one case where you can do it, so it’s really an important vulnerability in banking systems as well.You are familiar with this, this would be a typical case if someone hacked the SQL query for getting the exchange rate for a specific currency and then replaced the un-validated argument with something like this, this is a classic example (see image). But again, the bank robber is not here to steal data, he is here to steal money. Now, let’s steal money. This is a typical simplified version of what happens when someone transfers money from one account to another (see image). So, we have an actual SQL transaction, which means that either all SQL queries will be successful or none of them, this is the basics of the banking industry. But we have two update queries, so whenever I transfer money from my account to another, the balance on my account has to be changed, and the balance of the other account has to be changed accordingly, so these are the two updates queries. So, my account balance is going to be changed to zero, and the other account balance is going to be changed to 100. But if these arguments are not properly validated, this is a case how it would actually work in a normal case, and this would be an SQL injection. So, even though we have an SQL transaction, the first query will actually set my account balance to zero, but the second one will set the other account and my account balance back to 100. So, we again created money out of nothing (see image).
This is something completely different: banking signatures. When you are using online banking, do your banks provide an option for you to make an online deposit so that you can then digitally sign the deposit’s agreement? You have this in many counties. Banks are really enthusiastic about these digital certificates and digital signatures because we have the laws that we need to make these signatures valid in the court, and we have the technology, and the users already have digital certificates, so why not automate some of these processes?
Let’s see how that works. If the user wants to deposit 100 EUR for 31 days, he makes a request to the banking server. And the server says: “Okay, this is the deposit agreement that you need to sign”, and it’s dynamically generated from the data that user has provided. The server also decides what the interest rate would be for your deposit. This is all the data that you get and you are supposed to sign.
So the user signs the deposit agreement and sends it to the server, and the server countersigns it with the banking certificate which is on the server. This is now a legal document enforceable in court. If you go to the court and take this digitally signed document, the court will say: “You are right. This is true. This is a real agreement between you and the bank”, even though there was no person on the other side.Now, do you see a problem here? Well, a malicious user can modify the agreement, and if the server is not careful, it will sign the modified agreement (see image). The modified agreement can be anything, not just increasing the interest rate from 2% annually to 2,000,000% annually, which would be like a nice way to earn money, but the text of the agreement can also be changed. It may no longer be a deposit agreement, it can be a statement from the bank that all their real estate is now yours, or hypothetically (it would not work), but yes, anything can be changed, not just numbers.
As you can see everything I am talking about here requires zero user interaction. These are attacks against the banking servers, you don’t have to social-engineer anyone. So the server side code execution is nothing special in the banking industry. But the impact – what the attacker would like to do if he manages to execute code on the server – is to change the e-banking application code of course, because that code includes business logic that prevents you from doing some nasty things. And if you can remove that logic from the application, then you can attack the system.
And the Holy Grail for the attacker would be to get the opportunity and credentials to send direct requests to the back-end, because the back-end trusts the online banking server that it has done some validation before. So whatever the online server says to the back-end, the back-end can execute some additional validations, but it essentially has to trust that there was a user behind this request, even though the attacker was actually behind the request.
1 – JSP (JavaServer Pages) is a technology that helps software developers create dynamically generated web pages based on HTML, XML, or other document types. JSP is similar to PHP, but it uses the Java programming language.
2 – POST is one of many request methods supported by the HTTP protocol used by the World Wide Web. The POST request method is used when the client needs to send data to the server as part of the request, such as when uploading a file or submitting a completed form.