In Russian: https://blog.deteact.com/ru/common-flaws-of-sms-auth/
Many online services use SMS to authenticate users. But subtle implementation mistakes may lead to major problems. This is what we will talk about in this article.
Intro
This authentication protocol is popular among b2c services, as it increases the conversion, because the users do not need to remember passwords, invent logins, and simply enter their phone number instead, receiving an SMS code to confirm registration and authentication.
Moreover, some typical threats, such as simple passwords, password database leaks, simple phishing, are excluded.
Threats
Based on our experience in penetration testing projects, as well as in bug bounty programs, we have identified a number of major threats specific to SMS authentication mechanism.
Account Takeover
This most critical threat is that an attacker steals an arbitrary user’s account, knowing or even not knowing their phone number in advance.
User Impersonation
The threat of impersonation is not so critical, but the damage depends on the specific service. Usually, if Impersonation is possible, it is also possible to steal an already registered account, as the confirmation mechanism is the same.
SMS Flood
SMS flood can target the customers or any other people. The authentication interface of the vulnerable web application is used to send messages. For the web service itself, flood can lead to the loss of customer loyalty and reputation damage.
Resource Exhaustion
To send messages, web services are connected to various SMS messaging providers, who charge fee for each message. Thus, in during the SMS flood, both the resource pool of the server itself (network capacity, memory, queue, disk space) and simply the account balance in the SMS gateway can be exhausted.
Weaknesses and attacks
We have discovered examples of vulnerabilities of all the described classes in security analysis projects as well as in bug bounty programs (see profile https://hackerone.com/r0hack).
Lack of Rate Limit
This is a general class of SMS authentication weaknesses, and the exploitation of such vulnerability is obvious: the authorization code can be simply brute forced as there are no sufficient limits on the number of attempts.
Typically, the confirmation code consists of 4-6 digits, so the maximum number of requests required to search is up to 1 million, which is not much for the modern web.
Rate Limit linked to Cookie
Sometimes the number of login attempts is linked to a cookie identifier, and the attacker may simply omit the corresponding cookie identifier so that login attempts are not counted.
Same Code for Different Actions
The vulnerability is that the confirmation code sent by one interface (e.g. on the registration page) can also be used for another action (e.g. for logging into the account).
An example of such a vulnerability from bug bounty: upon authentication attempt, a user received an SMS code, and it could not be brute forced, because the number of attempts was limited, however, if an attacker sends the same code to the API for registration, the application would return the following response for the correct code:
1 |
{"message":"Such user has already been registered","type":"already_registered"},"field_errors":null} |
There were no rate limiting restrictions in the registration interface, which means that it was possible to hack any account by brute forcing a registration code and sending it as a confirmation code for authentication.
Lack of Auth Code Age
It happens that there are no limits on the number of attempts, but the code has a short life span and it is difficult to brute force.
During bug hunting, a vulnerability was found in such a mechanism in one of the popular services: despite the fact that the lifetime of a 6-digit code was only 3 minutes (and sending 1 million requests in 3 minutes is quite difficult), in reality there was no lifetime at all, because the application sent the same code when issuing the code again.
Apparently, developers thought that there is no need to generate random code again if nobody has entered the previous code. Thus, to try 1 million combinations, a “new” code and new cookies have to be requested and received approximately every 2.5-3 minutes.
SMS Flood
Rate limit should limit not only the number of attempts to login with a single phone number, but also the number of requests to the application as a whole, as an attacker may try to perform flood not on a particular user, but on a massive scale, in order to damage the service itself (trigger DoS or drain the funds).
Unsafe Random Numbers
Naturally, the confirmation code must be random, because if it can be predicted (for example, if its value depends only on the current second by Unix time), any account can be stolen.
One of the bugs we found was that it was not the predictability of the confirmation code itself that caused the vulnerability, but its identifier. In one of the services each confirmation code was assigned a number, which, as it turned out, was a global identifier and was incremented for each next code issued to a user.
When the user entered the code, the following JSON request was sent to the server:
1 |
{"code":"1111","verification_code_id":6717620}} |
It turned out that this identifier was not linked to the session, so the attacker could send incorrect confirmation codes on behalf of other users who are trying to login or register at that time. Knowing the current value of verification_code_id, it was possible to send lots of confirmation requests by adding different numbers to the current value and thus blocking other users and causing a denial of service.
User Blocking
The previously described vulnerability and the corresponding attack are a special case of a DoS attack.
If a user account is blocked when the rate limit is exceeded, a mass denial of service is possible: an attacker can simply make several unsuccessful auth attempts for each client, thus blocking all accounts. Of course, to do this, he needs to know their phone numbers or logins.
SMS Sniffing
It is no secret that sending data through SMS is unsafe. There’s a number of ways to intercept messages, including attacks at the level of the SS7 signaling network, attacks on the subscriber on the GSM layer, compromising the SMS provider’s gateway, compromising the customer’s personal account on the cellular operator’s website, etc.
The described SMS interception methods are usually not caused by a weakness of the web service itself, but it is necessary to take a risk of such attacks into account when developing an application.
Recommendations
In order to reduce the risk level, we recommend the following tips:
- Use 6-digit confirmation codes
- Limit the number and frequency of auth attempts from one IP address
- Take into account the number of attempts both in the current session and the total for the phone number
- Do not block user account after several unsuccessful attempts
- For each login attempt, generate a new unique code
- Use a separate code to confirm each action
- Do not use predictable identifiers and confirmation codes
- For highly sensitive actions do not use SMS confirmations, implement a proper 2FA, or at least push notifications or calls.
If you need to assess security of your web service, contact us at [email protected].