Insecure functionality - Password management - Java

Insecure functionality - Password management - Java

Need

Secure password management

Context

  • Usage of Java 1.8 for developing applications
  • Usage of javax.servlet for building Java web applications
  • Usage of javax.servlet.http for handling HTTP requests and responses in Java web applications
  • Usage of java.io for Input and Output operations in Java

Description

Non compliant code

        import javax.servlet.*;
import javax.servlet.http.*;

public class ChangePasswordServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String newPassword = request.getParameter("newPassword");
        
        User user = UserDAO.find(username);
        if (user != null) {
            user.setPassword(newPassword);
            UserDAO.update(user);
        }
    }
}
        
        

The above code is a servlet that handles password change requests. It reads the username and the new password from the request parameters, finds the corresponding user, and updates the user's password.

The vulnerability lies in the fact that the servlet does not check the session to see if the logged-in user is the same as the user whose password is being changed. This means that if an attacker can guess or obtain a username, they can change that user's password just by sending a POST request to this servlet with the correct parameters.

Here's how an attack might look:

1. The attacker logs into their own account. 2. The attacker sends a POST request to the ChangePasswordServlet, with the username parameter set to the victim's username and the newPassword parameter set to a password of the attacker's choosing. 3. The servlet updates the victim's password. 4. The attacker can now log into the victim's account with the new password.

This is a serious security vulnerability. It is crucial to always verify that the user making a change is authorized to make that change. In this case, the servlet should check that the username from the session matches the username from the request parameters before changing the password.

Steps

  • Implement proper authentication and authorization mechanisms to ensure that only authorized users can access the change password functionality.
  • Use secure password storage techniques such as hashing and salting to protect user passwords.
  • Implement session management to ensure that each user has their own session and cannot modify the password of another user.
  • Validate user input to prevent any malicious input or injection attacks.
  • Implement secure communication protocols (e.g., HTTPS) to protect the transmission of sensitive data, including passwords.
  • Regularly update and patch the application to address any known security vulnerabilities.
  • Conduct security testing and code reviews to identify and fix any potential vulnerabilities in the password management functionality.

Compliant code

        import javax.servlet.*;
import javax.servlet.http.*;

public class ChangePasswordServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        User sessionUser = (User) session.getAttribute("authenticatedUser");

        String username = request.getParameter("username");
        String newPassword = request.getParameter("newPassword");

        if (sessionUser != null && sessionUser.getUsername().equals(username)) {
            User user = UserDAO.find(username);
            if (user != null) {
                String hashedPassword = PasswordUtils.hashPassword(newPassword);
                user.setPassword(hashedPassword);
                UserDAO.update(user);
            }
        } else {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized access");
        }
    }
}
        
        

The updated code now includes session management to ensure that the user trying to change the password is the authenticated user for the session. This is done by getting the authenticated user from the session and comparing it with the username provided in the request.

If the session user is null or the username does not match the session user's username, an HTTP 401 Unauthorized error is returned.

If the session user and the username match, the code proceeds to find the user in the database and update the password. The password is hashed before being stored in the database, providing an additional layer of security.

This code assumes the existence of a PasswordUtils class with a hashPassword method for hashing the password, and that the User object has a getUsername method for retrieving the username. If these do not exist in your application, you will need to implement them.

This code also assumes that the user is authenticated at the start of the session and the User object representing the authenticated user is stored in the session with the key "authenticatedUser". If your application uses a different method for authentication and session management, you will need to adjust the code accordingly.

References