Skip to main content

Non-encrypted confidential information

Need

Secure storage of confidential information

Context

  • Usage of Java 1.8 for developing applications
  • Usage of java.io.* for input and output operations in Java
  • Usage of javax.servlet.* for Java Servlet development
  • Usage of javax.servlet.http.* for handling HTTP requests and responses in Java Servlets

Description

Non compliant code

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class StoreServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

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

// Storing the username and password in plain text
FileWriter fileWriter = new FileWriter("credentials.txt", true);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("Username: " + username + ", Password: " + password);
bufferedWriter.newLine();
bufferedWriter.close();
}
}

In this servlet, the doPost() method retrieves the username and password from the request parameters. These values are then written directly to a file named credentials.txt in plain text using a BufferedWriter.

This is a serious security vulnerability because anyone who gains access to this file can read the usernames and passwords without any difficulty. They are stored in plain text with no encryption or hashing, making them easily readable.

Moreover, if an attacker somehow gains access to the server file system, they can easily read all the stored credentials. Also, if this file is accidentally included in a backup or shared with others, the confidential information would be exposed.

This vulnerability can be exploited in various ways. For instance, an attacker could use the stolen credentials to impersonate users and gain unauthorized access to their accounts. This could lead to a variety of harmful outcomes, such as data theft, data manipulation, or even total system compromise in certain cases.

Therefore, confidential information like usernames and passwords should never be stored in plain text. They should be encrypted or hashed before being stored to prevent attackers from easily reading them.

Steps

  • Use encryption to protect the confidential information.
  • Avoid storing sensitive information in plain text.
  • Implement secure storage mechanisms such as hashing or encryption algorithms.
  • Use secure protocols (e.g., HTTPS) for transmitting sensitive data.
  • Follow best practices for secure coding and data handling.
  • Regularly update and patch the software to address any security vulnerabilities.

Compliant code

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.security.*;

public class StoreServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String secretKey = "mySuperSecretKey"; // This should be stored securely and not in plain text

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

// Encrypt the username and password
String encryptedUsername = encrypt(username);
String encryptedPassword = encrypt(password);

// Storing the encrypted username and password
FileWriter fileWriter = new FileWriter("credentials.txt", true);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("Username: " + encryptedUsername + ", Password: " + encryptedPassword);
bufferedWriter.newLine();
bufferedWriter.close();
}

private String encrypt(String data) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

The above code fixes the vulnerability by encrypting the username and password before storing them. The encryption is done using the AES (Advanced Encryption Standard) algorithm with a secret key. The secret key is used to initialize the cipher for encryption. The data is then encrypted using the doFinal method of the Cipher class. The encrypted data is then encoded into a string using Base64 encoding before being written to the file.

Please note that the secret key is currently stored as a plain text string within the code, which is not secure. In a real-world application, this key should be securely stored and retrieved, not hardcoded into the application.

The encrypt method throws a RuntimeException if any exception occurs during the encryption process. This is a simple way to handle exceptions for this example, but in a real-world application, more sophisticated error handling should be implemented.

This code should be used over a secure protocol like HTTPS to ensure that the data is securely transmitted over the network. Regular updates and patches should also be applied to the software to address any security vulnerabilities.

References