- Tram Ho
I repeat: in a recent conference, I said in early 2017 I found a loophole that allowed to steal money from any account of 4-5 banks in Vietnam.
The picture above is a slide in my talk. This is a cyber security lecture, so I use this form to show participants how to think like a hacker. I think this is an effective approach, without having to go into the technical details, because not everyone who looks at the money box can think of "ah, I'll enter negative numbers". .
The flaw that I discovered was real, it did not lie in the negative transfer amount, but in the exchange of the recipient and sender's account. Some readers have questions and doubts about this vulnerability. I suspect it is true that I did not believe my own eyes when I found this flaw.
I can't disclose which bank or product is, for obvious reasons, but I can explain more about this pretty interesting flaw specification. The Zen master gamma95 once said it was hard to convince others that sugar was sweet, if they had never tried it before. Therefore, believe it or not, it is predestined ;-).
A Mobile Banking solution usually consists of a mobile app and an API server that provides functions such as account inquiries and transfers.
Question: If you were tasked with designing the API to transfer money on the server, what would your API look like?
The answer is not difficult, but if it has never been, there are many things to think about. Before you continue reading, try writing down your own answer.
To transfer money, the server needs at least 3 parameters:
1 / Receiving account
2 / Deposit account
3 / Amount
The receiving account and the amount will be entered by the user into the mobile app, then the mobile app transfers to the server. But where does the account come from?
What if I let users choose, what if they enter someone else's account? That is, the server must check whether the user has the right to transfer money out of that account or not (authorization). To do so, the server must first authenticate the user (authentication).
On the web, after the client logs in, the server returns an HTTP cookie, the browser remembers and uses the cookie to authenticate subsequent requests. As popular web-making technologies (such as .NET, Spring, PHP, or Ruby On Rails) already have this part ready, developers don't need to do anything else.
The problem is that on mobile there is no technology available such as HTTP cookies, so developers often have to invent their own authentication methods. Someone using solutions like OAuth or JWT. In this case, the product uses a homemade authentication solution.
Before talking about that solution, available here, I'd like to talk a bit more about solutions like cookies, OAuth, or JWT. By the way, these solutions are the same in that after the customer logs in, the server will issue the mobile app a token representing the customer. The mobile app will attach tokens when sending requests to the server. How the server checks the token is the crux of the problem.
For example, this is easy to understand. Every time you send a motorbike, the garage gives you a voucher. This card has the same role as the token I mentioned above. To get your car back, you have to give it back and the garage will have to check the following:
1 / The vote is still valid. How is it valid, depending on the place, usually they will rely on the date, seal, signature on the slip. For example, if the place did not park the vehicle overnight, you gave the voucher yesterday, which means that the voucher is problematic.
2 / The voucher is given to the vehicle you are trying to remove. This is important, because if not, I can send in a bicycle, use the ticket of the bike to steal a good motorbike. To cover this gap, the garage often put the votes on the saddle. When you pull the car out, they will check to see if the number on the ticket and the seat number are the same. Anyone who thinks like a hacker will immediately see the flaw: what if someone deleted the number on the saddle, recorded another number? The common solution is to write the car number on the parking card. When you take the car out, the garage will check whether the number of cars on the ticket matches the number of cars on the license plate or not.
Back to the money transfer API design story. In addition to the 3 parameters of the recipient's account, the sender's account and the amount, the mobile app needs to attach the customer's token. The server will have to check the following:
1 / Token is valid. Similar to the parking ticket, a valid token will have, for example, a valid electronic signature, expiry date, has not been revoked, etc. Many places use stateless solutions like OAuth or JWT. , but these solutions have many problems. No matter what, I want to save homework for readers.
2 / Token is owned by a user and he or she is allowed to transfer money from the sending account. In case each customer has only one account, the account number can be recorded on the token (like on the parking ticket with the vehicle number written on it). In case each customer can have multiple accounts, on the token can write a user ID (a phone number for example). From this user ID, you can retrieve (from core banking, for example) a list of accounts that users can transfer money to. The server will have to check to make sure the number of sending accounts is on this list.
I found out that the server did not perform the second step. In other words, I used a token of my own to pass the first check, but I changed the number of the sending account by the victim's account number. I want to steal money. Before transferring money, the server requires OTP authentication via SMS. But, instead of sending OTP to the phone number of the sending account, the server sends OTP to the phone number in the token, which is my phone number.
I write "understand" because this product is not authenticated by token, but using a solution "growers" is quite confusing, but can summarize like this:
1 / The solution uses electronic signatures to authenticate customers.
2 / The server generates an RSA key set for each client.
3 / Mobile app uses the private key (private key) of the customer to sign all requests sent to the server, including authentication requests.
The obvious question is: how does a mobile app have a customer's private key? Because the key set is created on the server (this is another vulnerability), the mobile app will have to download the private key from the server. Anyone who thinks like a hacker will immediately see a chicken and egg problem here: to authenticate you need a private key, but to have a private key you need to authenticate first!
The "solution" they use is to add an API that allows the mobile app to download any customer's private key, just by knowing that customer's phone number. In other words, this is an unauthenticated API where I can get my private key and thereby impersonate any account.
In short, this solution is only safe when people do not understand the protocol between the server and the mobile app. This is a violation of the Kerckhoff principle when designing security protocols.
A security system is an open system, everyone knows how it works, but no one can break it. If the security of the system depends on the assumption that no one knows how it works, sooner or later the system will be attacked. Tampering with the code or hiding the way the software works does not mean that it does not work to enhance the security of the system, but they cannot be the only protection. Translating software code is difficult, but a lot of people can do it.
The design of the system needs to be open because it only protects against vandalism, intrusion from the inside, which is the biggest threat to the banking system. Many bankers understand the protocol between a mobile app and a server, if these people want to steal money, how to stop them? They are still employees today, but what if they think about it later? This question can only be answered by building the system assuming that the attacker already knows the source code and design documentation.
Update : I would like to write a bit more about designing security solutions (security engineering) because this topic is related to the main article on situation and network security policy in Vietnam.
Designing and building authentication solutions for a mobile banking product is a hybrid of applied security and product security. This is neither easy nor difficult, but I think there are few people in Vietnam who do. The majority of security professionals in Vietnam focus on finding vulnerabilities, or network security, very few people can build solutions to solve common security issues such as identity access management including authentication, authorization and auditing, key / secret management or data protection.
What I wrote above, the questions I ask contain many suggestions for beginners in this area. If there is a confusing place, leave the jar, I will try to explain, but I recommend reading carefully, ponder, then design an authentic solution, try to break it and repeat. This is the best way to learn.
Source : Techtalk