Secure access control for financial information
import javax.servlet.http.*;
import javax.crypto.Cipher;
import java.util.Base64;
public class CreditCardController extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String encryptedCardNumber = request.getParameter("cardNumber");
String decryptedCardNumber = decryptCardNumber(encryptedCardNumber);
CreditCard card = CreditCardService.getCardByNumber(decryptedCardNumber);
List transactions = TransactionService.getTransactionsForCard(card);
request.setAttribute("transactions", transactions);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/views/transactions.jsp");
dispatcher.forward(request, response);
}
private String decryptCardNumber(String encryptedCardNumber) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedCardNumber);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
The above code represents a Servlet which handles HTTP GET requests to fetch transaction history for a given credit card number.
The 'doGet' method retrieves the encrypted card number from the request parameters and decrypts it using the 'decryptCardNumber' method. The decrypted card number is then used to fetch the CreditCard object from the CreditCardService. Once the card object is retrieved, the TransactionService is used to fetch all transactions associated with the card. These transactions are then set as an attribute on the request and forwarded to a JSP page for display.
The vulnerability here lies in the fact that there is no validation to check if the account making the request is the one associated with the credit card. This means that a user can potentially make a request for transaction history of a card that they do not own, leading to unauthorized access to sensitive financial information. This is an example of an Insecure Direct Object Reference (IDOR) vulnerability.
import javax.servlet.http.*;
import javax.crypto.Cipher;
import java.util.Base64;
public class CreditCardController extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
String encryptedCardNumber = request.getParameter("cardNumber");
String decryptedCardNumber = decryptCardNumber(encryptedCardNumber);
CreditCard card = CreditCardService.getCardByNumber(decryptedCardNumber);
if (card == null || !card.getUser().equals(user)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
List transactions = TransactionService.getTransactionsForCard(card);
request.setAttribute("transactions", transactions);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/views/transactions.jsp");
dispatcher.forward(request, response);
}
private String decryptCardNumber(String encryptedCardNumber) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedCardNumber);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
The updated code now includes a check to ensure that the user making the request is the owner of the credit card. This is done by retrieving the user from the session and comparing it with the user associated with the credit card. If the users do not match, a 403 Forbidden error is returned.
The
doGet
method now starts by retrieving the
HttpSession
and the
User
object from it. This
User
object should be set when the user logs in. Then, it retrieves the encrypted card number from the request parameters and decrypts it.
Next, it retrieves the
CreditCard
object associated with the decrypted card number. If no such card exists or if the user associated with the card does not match the user from the session, it sends a 403 Forbidden error and returns.
If the user is authorized, it retrieves the transactions associated with the card, sets them as a request attribute, and forwards the request to the transactions view.
The
decryptCardNumber
method remains unchanged. It decrypts the encrypted card number using AES encryption with CBC mode and PKCS5 padding. If an error occurs during decryption, it throws a
RuntimeException
.
This code ensures that only the authorized user can access the credit card information, thus fixing the insecure direct object reference vulnerability.