OTP and security aspects need to be ensured

Tram Ho

0. Prologue

OTP or One Time Password is commonly used in many applications today as a second layer of authentication to verify users. The concept is simple: the OTP is sent to a predefined ‘address’ (email, phone number, etc.), this OTP is used only once and is valid for a short period of time. specified, usually <=5 minutes.

Although the concept is simple, around it there are many security aspects that both Pentester and Developer need to know. From personal experience, many projects are carefully invested in terms of processes, documents, people, time, etc.; but when it comes to testing, touching OTP still “leaks” out some significant vulnerabilities.

Maybe the more I take something lightly, the easier it is to do wrong!

1. Mistakes to avoid

Somehow they still exist!

1.1. Return OTP right in HTTP response

Maybe because the dev wants to be more convenient in the development process, so it’s always like this for fast (!?). But absolutely must be avoided when putting the application in production environment.

1.2. OTP only makes sense at Front-End

The application has several steps in transferring money as follows:

Step 1: The user sends a request to the back-end to check the “validity” of the sender and receiver, as well as some related information.

Step 2: In the background there is a rule-based system and ‘a few other things’ to decide if the payment is valid and the user needs to enter an OTP.

Step 3: Back-end sends a message to the front-end, the front-end relies on this message to decide the next step. The assumption here is that the user is required to enter an OTP, the message will be “REQUIRE_OTP”.

Step 4: The application displays a prompt and asks the user to enter the OTP there.

Step 5: If the user enters the correct OTP, the application will send another submit payment request to the back-end.

It sounds logical and flows right, but here’s the problem: At step “4.5”, when the user enters the correct OTP, the app doesn’t return any secret value/ nonce value or anything else. Verify that the user has entered the correct OTP. Leading up to step 5, the user submits the payment freely without any additional value other than the session token as usual, the application does not determine if the actor submitting the payment is the correct actor with the correct OTP. The display of the OTP input promp only makes sense at the Front end. This is the first one.

The second is that in Step 3, the user can easily change the HTTP response from “REQUIRE_OTP” to some valid value, for example “ACCEPT_PAYMENT”, and so the application automatically sends a submit payment request. . That’s it!

This problem is in the design.

This error often occurs in mobile applications

1.3. Do not disable previous OTP or OTP with no specific expiration time/too long

Easy to understand and test, make sure with 1 action at a time only 1 valid OTP, no matter how many times the user has requested to resend the OTP. At the same time, make sure the OTP’s expired time is only measured in units of x minutes (x elementary).

1.4. There is no rate limit

1.4.1. No rate limit when entering OTP

Easy to understand and check, this error easily leads to a problem of brute-forcing OTP, with 6 digit OTP, there are 1,000,000 OTPs available, brute-force will eventually go away but Pentester will usually get the correct OTP code , run a few hundred requests to prove the error quickly.

With correct OTP code, HTTP response length will be different, correct code here is 4383 (4 digit OTP). The HTTP response length is 449, which is different from 466 when the OTP is entered incorrectly.

1.4.2 No rate limit when requesting to send OTP

Easy to understand and test, make sure you set a rate limit for users when they request a new OTP (and be careful to put it on the back-end, not just the front-end). Usually the appropriate time is 30s – 3 minutes depending on the application.

This error 1.4.2, if combined with error 1.3, is a disaster

1.5. There is a rate limit but it leads to a User Enumeration vulnerability

Some applications allow you to login via an identifier or phone number, they will send SMS OTP to your device, they have implemented everything beautifully, rate limit properly, 2 minutes you can only 1 time OTP request. But rate-limit only applies to…users that already exist in the system.

Roughly, in both cases (the phone number exists and does not exist in the system), the app very intelligently responded to a “general message” as follows: We have sent OTP to your phone number, please abcxyz.

But when the user clicks “Resend OTP” shortly after, with the user not existing, the app responds to the “general message” above again. As for existing users, a message about rate limit appears: “You can only request OTP every 2 minutes …”.

So the attacker easily knows which user/phone number already exists in the system!

1.6. Do not double check the nonce value

The back end returns a nonce value to the client when the correct OTP is entered, the client uses that nonce value to enter the next request and then send it. But unexpectedly, the back end does not care (doesn’t check) the nonce value is correct or not and accepts the request, continuing to process the user’s request.

2. Common OTP implementation methods

  1. Generate and assign the user a new access token after the user provides the correct OTP, this is often seen in the first step of the Authentication Scheme (e.g. login to the application, login via IdP in OpenID, etc.).
  2. Send the OTP along with the action that needs the OTP (eg money transfer).
  3. Send OTP, if OTP is correct, you will receive a nonce value, assign that nonce value to a parameter in the next request.

3. Summary

Some suggestions for implementing OTP:

  1. The length should be from 6 characters, sent via channels confirmed by the user in advance such as Email/Phone
  2. Expired time of OTP should only be <= 5 minutes
  3. There is only one valid OTP for an action at a time (disable previous OTP).
  4. Apply appropriate rate limite at both input step, request to resend OTP and also response message when user violates rate limit

For example, when the user enters the wrong OTP more than 5 times, the OTP for that action will be expired immediately, and the response message is always the same and generic in the style: The OTP you entered is incorrect, please abcxyz. Then even if you submit the correct OTP, the message will still be the same because the OTP has already expired.

Regarding the response message when the user requests to send the OTP back, both existing users and non-existing users in the system should have the same response message.

  1. Design the application so that the back-end server must know for sure that the actor actually has a valid OTP, most things on the front-end to limit the user’s action are meaningless.

4. References

This article is drawn from working experience after many OTP related errors!

Share the news now

Source : Viblo