Protection of sensitive business information stored in the database
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
public class VulnerableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","password");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM Transactions");
while(rs.next()) {
out.println("User: " + rs.getString(1) + "
");
out.println("Document Number: " + rs.getString(2) + "
");
out.println("Full Name: " + rs.getString(3) + "
");
out.println("Wallet ID: " + rs.getString(4) + "
");
out.println("OS Name: " + rs.getString(5) + "
");
out.println("Transaction Code: " + rs.getString(6) + "
");
out.println("Endpoint: " + rs.getString(7) + "
");
out.println("Credit Card: " + rs.getString(8) + "
");
out.println("Available Balance: " + rs.getString(9) + "
");
}
con.close();
} catch(Exception e) {
out.println(e);
}
}
}
The above code is a Servlet that connects to a MySQL database and retrieves all the transactions. It then prints all the information about each transaction, including sensitive business information, to the response object, which is sent to the client.
The problem lies in the fact that no authentication or authorization checks are made before the information is retrieved and sent to the client. This means that anyone who can make a request to this Servlet can get all the business information.
Additionally, the database connection details, including the username and password, are hard-coded into the source code. This is a bad practice as it exposes these sensitive details to anyone who has access to the source code.
Finally, the code does not use prepared statements for the SQL query, which makes it vulnerable to SQL Injection attacks. An attacker could potentially manipulate the SQL query to gain unauthorized access to other data in the database.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class SecureServlet extends HttpServlet {
private DataSource dataSource;
@Override
public void init() throws ServletException {
try {
InitialContext initialContext = new InitialContext();
dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/mydb");
} catch (NamingException e) {
throw new ServletException("Cannot retrieve datasource", e);
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
try (Connection con = dataSource.getConnection()) {
PreparedStatement stmt = con.prepareStatement("SELECT * FROM Transactions WHERE user_id = ?");
stmt.setString(1, request.getUserPrincipal().getName());
ResultSet rs = stmt.executeQuery();
while(rs.next()) {
out.println("User: " + rs.getString(1) + "
");
out.println("Document Number: " + rs.getString(2) + "
");
out.println("Full Name: " + rs.getString(3) + "
");
out.println("Wallet ID: " + rs.getString(4) + "
");
out.println("OS Name: " + rs.getString(5) + "
");
out.println("Transaction Code: " + rs.getString(6) + "
");
out.println("Endpoint: " + rs.getString(7) + "
");
out.println("Credit Card: " + rs.getString(8) + "
");
out.println("Available Balance: " + rs.getString(9) + "
");
}
} catch(Exception e) {
out.println(e);
}
}
}
The above code is a revised version of the original vulnerable servlet. The changes made are as follows:
- The database connection details are no longer hard-coded in the servlet. Instead, the servlet retrieves the
DataSource
from the JNDI environment. This prevents sensitive information such as the database URL, username, and password from being exposed in the source code.
- The SQL query is now parameterized to prevent SQL injection attacks. The
PreparedStatement
is used instead of
Statement
, and the user ID is set as a parameter in the query.
- The servlet now only retrieves the transactions for the authenticated user. This is done by calling
request.getUserPrincipal().getName()
to get the name of the authenticated user, and using this as the parameter in the SQL query. This prevents unauthorized access to other users' transactions.
- The sensitive information is still displayed in the response. However, this is just for demonstration purposes. In a real application, this information should be encrypted or hashed before being stored in the database, and should not be displayed in plain text in the response.
- The connection is now managed within a try-with-resources block, which ensures that the connection is always closed, even if an exception occurs. This prevents potential connection leaks.
- The servlet now implements the
init
method to retrieve the
DataSource
. This is done only once when the servlet is initialized, instead of every time the
doGet
method is called. This improves the performance of the servlet.
- The servlet now catches
NamingException
in the
init
method. This is a checked exception that can be thrown when looking up the
DataSource
in the JNDI environment. By catching this exception, the servlet can provide a more meaningful error message if the
DataSource
cannot be retrieved.