Non-encrypted confidential information - Base 64 - Java

Non-encrypted confidential information - Base 64 - Java

Need

Secure storage of confidential information

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for Java Servlet development

Description

Non compliant code

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

public class LoginServlet extends HttpServlet {
    private static final String USERNAME = "admin";
    private static final String PASSWORD = "YWRtaW4="; // "admin" in Base64

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (USERNAME.equals(username) && PASSWORD.equals(Base64.getEncoder().encodeToString(password.getBytes()))) {
            // User is authenticated
        } else {
            // User is not authenticated
        }
    }
}
        
        

The above code shows a simple servlet in Java that handles login requests. The servlet takes a username and password from the request parameters and compares them to a hardcoded username and password. The password is encoded in Base64, which is a form of encoding that is easily reversible.

The vulnerability here is that the password is stored in the source code in Base64 encoding. This is a problem because Base64 is not a secure form of encryption. It is a type of encoding that is designed to be easily reversible, so anyone who has access to the code can easily decode the password.

Furthermore, storing passwords in the source code is a bad practice in general. If the source code is ever exposed, the password will be immediately visible to anyone who sees it. This could potentially allow unauthorized users to gain access to the system.

The correct way to store passwords is to use a secure form of hashing, such as bcrypt or scrypt, and to store the hashed password in a secure database. The application should then compare the hashed password from the database with the hashed version of the password provided by the user. This ensures that even if the database is compromised, the passwords will not be immediately usable by an attacker.

Steps

  • Remove the hardcoded credentials from the source code.
  • Store the credentials securely, such as in a configuration file or a secure database.
  • Use encryption to protect the confidentiality of the credentials.
  • Implement a secure authentication mechanism, such as hashing the password and comparing the hashed values.
  • Implement secure communication protocols, such as HTTPS, to protect the transmission of sensitive information.

Compliant code

        import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class LoginServlet extends HttpServlet {
    private static final String USERNAME = "admin"; // This should be removed and stored securely
    private static final String PASSWORD = "YWRtaW4="; // This should be removed and stored securely

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // Hash the password
        String hashedPassword = hashPassword(password);

        if (USERNAME.equals(username) && PASSWORD.equals(hashedPassword)) {
            // User is authenticated
        } else {
            // User is not authenticated
        }
    }

    private String hashPassword(String password) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(password.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(hash);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}
        
        

The original code had a vulnerability where the credentials were stored in the source code in Base64 format. This is insecure as anyone with access to the source code can easily decode the Base64 string to get the original credentials.

The updated code removes the hardcoded credentials and instead, it is suggested to store them securely in a configuration file or a secure database. The password is hashed using SHA-256 and then encoded in Base64. This way, even if someone gets access to the hashed password, they cannot reverse-engineer it to get the original password.

The hashPassword method is used to hash the password. It uses the MessageDigest class from the java.security package to create a SHA-256 hash of the password. The hashed password is then encoded in Base64 using the Base64.getEncoder().encodeToString method.

The doPost method retrieves the username and password from the request parameters, hashes the password, and then compares the hashed password and username with the stored values. If they match, the user is authenticated. Otherwise, the user is not authenticated.

Note: The code still contains hardcoded credentials for demonstration purposes. In a real-world application, these should be removed and stored securely. Also, secure communication protocols such as HTTPS should be used to protect the transmission of sensitive information.

References