Insecurely generated token - OTP - Java

Insecurely generated token - OTP - Java

Need

Secure generation and transmission of OTP tokens

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for building Java web applications with Servlets

Description

Non compliant code

        import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class OTPServlet extends HttpServlet {
    
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        String phoneNumber = request.getParameter("phoneNumber");
        String otp = generateOTP();
        
        // send OTP to the client
        response.getWriter().write("OTP: " + otp);
    }
    
    private String generateOTP() {
        // insecure OTP generation
        return String.valueOf((int)(Math.random() * 1000000));
    }
}
        
        

The above Java servlet generates an OTP (One-Time Password) when the doGet method is called. The doGet method takes in a HttpServletRequest and a HttpServletResponse as parameters.

In the doGet method, it retrieves a phone number from the request parameters and generates an OTP using the generateOTP method. The generated OTP is then sent back to the client through the response writer.

The generateOTP method generates a random number between 0 and 999999, converts it to a string and returns it.

This code is vulnerable because the OTP is generated on the client-side and sent to the server. An attacker can intercept the request and access the OTP, allowing them to continue the application flow without needing access to the phone number used. This can lead to unauthorized access and potential data breaches.

Steps

  • Generate the OTP server-side instead of client-side
  • Use a cryptographically secure random number generator to generate the OTP
  • Ensure that the OTP is securely transmitted to the client, such as using HTTPS
  • Implement additional security measures, such as rate limiting or throttling, to prevent brute force attacks on the OTP

Compliant code

        import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.SecureRandom;

public class OTPServlet extends HttpServlet {
    
    private static final SecureRandom secureRandom = new SecureRandom(); // Cryptographically secure random
    
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        String phoneNumber = request.getParameter("phoneNumber");
        String otp = generateOTP();
        
        // send OTP to the client
        response.getWriter().write("OTP: " + otp);
    }
    
    private String generateOTP() {
        // Secure OTP generation
        return String.format("%06d", secureRandom.nextInt(1000000));
    }
}
        
        

The original code was vulnerable because it was generating the OTP (One-Time Password) on the client-side, which could be intercepted by an attacker. The OTP was also generated using Math.random(), which is not cryptographically secure.

The fixed code generates the OTP on the server-side, which is more secure because it's harder for an attacker to intercept. The OTP is generated using SecureRandom, which is a cryptographically secure random number generator. This makes it much harder for an attacker to guess the OTP.

The OTP is then sent to the client. To ensure this transmission is secure, it should be sent over HTTPS, which encrypts the data in transit.

Additional security measures, such as rate limiting or throttling, should also be implemented to prevent brute force attacks. These measures limit the number of attempts that can be made to guess the OTP, making such attacks impractical.

References