Non-encrypted confidential information - DB - Java

Non-encrypted confidential information - DB - Java

Need

Secure storage of confidential information in the database

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for developing Java Servlet applications
  • Usage of mysql-connector-java for connecting to a MySQL database in Java

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;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserServlet extends HttpServlet {

    private Connection connection;

    public UserServlet() {
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost/testdb", "user", "pass");
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        try {
            PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users VALUES (?, ?)");
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, password);
            preparedStatement.execute();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}
        
        

The above code is a simple example of a servlet that handles user registration. It gets the username and password from the request parameters and then inserts them into the database.

The vulnerability here lies in the fact that the password is being stored in the database in plain text. This means that if an attacker gains access to the database, they can easily read the passwords of all the users. This is a severe security risk.

In addition, the connection to the database is not encrypted. This means that if an attacker is able to intercept the communication between the application and the database, they can read all the data that is being sent. This includes the usernames and passwords that are being inserted into the database.

Furthermore, the database credentials are hard-coded into the application. If an attacker gains access to the application code, they can use these credentials to connect to the database directly.

Finally, the code does not use prepared statements correctly. The parameters for the INSERT statement are being set manually, which opens up the possibility for SQL injection attacks.

Steps

  • Use encryption to protect the confidential information before storing it in the database.
  • Implement secure communication protocols (e.g., HTTPS) to protect data transmission between the client and the server.
  • Implement proper access controls to restrict unauthorized access to the database.
  • Regularly update and patch the database software to address any security vulnerabilities.
  • Implement strong authentication mechanisms to prevent unauthorized access to the application and database.
  • Implement input validation and parameterized queries to prevent SQL injection attacks.
  • Implement secure coding practices to minimize the risk of other vulnerabilities.
  • Regularly monitor and log database activities to detect any unauthorized access or suspicious activities.
  • Regularly backup the database and test the restoration process to ensure data integrity and availability.

Compliant code

        import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
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.Key;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Base64;

public class UserServlet extends HttpServlet {

    private Connection connection;
    private static final String ALGORITHM = "AES";
    private static final byte[] keyValue = 
        new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };

    public UserServlet() {
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost/testdb", "user", "pass");
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        try {
            String encryptedPassword = encrypt(password);
            PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users VALUES (?, ?)");
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, encryptedPassword);
            preparedStatement.execute();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
    }

    public static String encrypt(String valueToEnc) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        String encryptedValue = Base64.getEncoder().encodeToString(encValue);
        return encryptedValue;
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGORITHM);
        return key;
    }
}
        
        

The updated code now includes encryption for the password before it is stored in the database. This is done using the AES encryption algorithm. The encrypt method is used to encrypt the password, and the generateKey method is used to generate a secret key for the AES encryption.

The doPost method now calls the encrypt method to encrypt the password before storing it in the database. This ensures that even if an attacker gains access to the database, they will not be able to read the password as it is encrypted.

This code also follows secure coding practices such as using parameterized queries to prevent SQL injection attacks. It is also recommended to implement secure communication protocols (e.g., HTTPS), proper access controls, strong authentication mechanisms, regular updates and patches, input validation, regular monitoring and logging, and regular backups and restoration tests to further enhance the security of the application and database.

References