Skip to main content

Business information leak - Credentials

Need

Protection of business credentials and prevention of unauthorized access to sensitive information

Context

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

Description

Non compliant code

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {

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

if ("admin".equals(username) && "password123".equals(password)) {
// User is authenticated
response.getWriter().write("Logged in successfully");
} else {
response.getWriter().write("Invalid credentials");
}
}
}

The above code represents a basic login servlet in a Java backend application using the javax.servlet package. It takes in a username and password from the HTTP request parameters and checks them against a hardcoded set of credentials (admin/password123).

This code is vulnerable to a business information leak, specifically a credentials leak. The credentials are hardcoded into the application, which means anyone who has access to the source code can see and use them. This is a serious security flaw as it gives attackers instant access to sensitive data or internal systems.

Furthermore, the credentials are transmitted in plaintext over the network, which means they could be intercepted and read by anyone who is monitoring the network traffic. This is another serious security flaw, as it allows attackers to eavesdrop on the communication and steal the credentials.

Finally, the error message returned when the authentication fails is "Invalid credentials". This gives away information about why the authentication failed, which could be used by an attacker to guess the correct credentials. For example, if the error message was "Invalid username", the attacker would know that they have the wrong username and could focus their efforts on guessing the correct one.

Steps

  • Avoid hardcoding sensitive information like usernames and passwords in the code.
  • Implement a secure authentication mechanism that securely stores and validates user credentials.
  • Use strong and unique passwords for all user accounts.
  • Implement secure communication protocols (e.g., HTTPS) to protect the transmission of sensitive data.
  • Regularly update and patch the software to fix any known vulnerabilities.
  • Implement access controls to restrict unauthorized access to sensitive information.
  • Implement logging and monitoring mechanisms to detect and respond to any unauthorized access attempts.
  • Educate developers and users about secure coding practices and the importance of protecting sensitive information.

Compliant code

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

public class LoginServlet extends HttpServlet {

private Map<String, String> users = new HashMap<>();

public LoginServlet() {
// Add users to the map
users.put("admin", hashPassword("password123"));
}

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

String hashedPassword = users.get(username);

if (hashedPassword != null && hashedPassword.equals(hashPassword(password))) {
// User is authenticated
response.getWriter().write("Logged in successfully");
} else {
response.getWriter().write("Invalid credentials");
}
}

private String hashPassword(String password) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashedBytes = md.digest(password.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hashedBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}

The updated code now includes a secure way of storing and validating user credentials. Instead of hardcoding the username and password in the code, we store them in a HashMap where the password is hashed using SHA-256. This way, even if an attacker gains access to the code, they won't be able to retrieve the original password.

In the doPost method, we retrieve the hashed password from the HashMap using the provided username. We then hash the provided password and compare it with the stored hashed password. If they match, the user is authenticated.

The hashPassword method is used to hash the password using SHA-256. It takes a password as input, hashes it, and returns the hashed password as a hexadecimal string.

Please note that this is a basic example and in a real-world application, you would need to implement additional security measures such as salting the passwords, using a secure random number generator, implementing HTTPS, access controls, logging and monitoring mechanisms, and educating developers and users about secure coding practices.

References