Skip to main content

Business information leak - Credit Cards

Need

Protection of sensitive business information and customer credit card data

Context

  • Usage of Scala for building scalable and functional applications
  • Usage of play.api.mvc for handling HTTP requests and building web applications in Play Framework
  • Usage of play.api.libs.json for JSON parsing and manipulation in Play Framework

Description

Non compliant code

import play.api.mvc._
import play.api.libs.json._

class CreditCardController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

def getCreditCardDetails(creditCardId: String) = Action { implicit request: Request[AnyContent] =>
val creditCardDetails = getCreditCardDetailsFromDatabase(creditCardId)
Ok(Json.toJson(creditCardDetails))
}

private def getCreditCardDetailsFromDatabase(creditCardId: String): CreditCard = {
// Fetch credit card details from the database
// This is just a placeholder. Replace this with actual database fetching logic.
CreditCard(creditCardId, "1234-5678-9012-3456", "John Doe", "12/23", "123")
}
}

case class CreditCard(creditCardId: String, cardNumber: String, cardHolderName: String, expiryDate: String, cvv: String)

The above code shows a controller named CreditCardController in a Scala Play Framework application. The controller has a method getCreditCardDetails which takes a creditCardId as a parameter. This method is responsible for fetching credit card details from the database and returning them as a response to the client.

The vulnerability lies in the getCreditCardDetails method. This method fetches all the details of a credit card including the card number, card holder's name, expiry date, and CVV. These details are then converted to JSON format and sent as a response to the client.

The problem is that sensitive information such as the card number, card holder's name, expiry date, and CVV should never be exposed. Even if the client needs to display some of these details, they should be masked or encrypted. For example, instead of sending the full card number, only the last 4 digits should be sent. The CVV should never be stored or transmitted.

This vulnerability can lead to serious consequences such as identity theft, fraudulent transactions, and violation of PCI DSS (Payment Card Industry Data Security Standard) compliance.

Steps

  • Avoid returning sensitive information in the response.
  • Implement proper access control mechanisms to restrict access to sensitive data.
  • Ensure that credit card details are properly encrypted and stored securely.
  • Implement input validation and sanitization to prevent any potential injection attacks.
  • Regularly update and patch the application and its dependencies to address any known security vulnerabilities.
  • Conduct regular security audits and penetration testing to identify and address any potential vulnerabilities.
  • Follow secure coding practices and guidelines to minimize the risk of introducing security vulnerabilities.

Compliant code

import play.api.mvc._
import play.api.libs.json._

class CreditCardController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

def getCreditCardDetails(creditCardId: String) = Action { implicit request: Request[AnyContent] =>
val creditCardDetails = getCreditCardDetailsFromDatabase(creditCardId)
Ok(Json.toJson(creditCardDetails.copy(cardNumber = "", cvv = ""))) // Do not return sensitive data
}

private def getCreditCardDetailsFromDatabase(creditCardId: String): CreditCard = {
// Fetch credit card details from the database
// This is just a placeholder. Replace this with actual database fetching logic.
CreditCard(creditCardId, "1234-5678-9012-3456", "John Doe", "12/23", "123")
}
}

case class CreditCard(creditCardId: String, cardNumber: String, cardHolderName: String, expiryDate: String, cvv: String)

The vulnerability in the code was that it was returning sensitive credit card information in the response. This could potentially lead to a data leak and unauthorized access to sensitive customer information.

The fix for this vulnerability is to avoid returning sensitive information in the response. In the getCreditCardDetails method, we are now creating a copy of the creditCardDetails object and setting the cardNumber and cvv fields to an empty string before returning it in the response. This ensures that the sensitive credit card information is not leaked in the response.

In addition to this, it is recommended to implement proper access control mechanisms to restrict access to sensitive data. This could include authentication and authorization checks to ensure that only authorized users can access the credit card details.

Furthermore, credit card details should be properly encrypted and stored securely in the database. This can help prevent data leaks in case the database is compromised.

Input validation and sanitization should also be implemented to prevent any potential injection attacks. This can help ensure that only valid and safe inputs are processed by the application.

Regular updates and patches should be applied to the application and its dependencies to address any known security vulnerabilities. Regular security audits and penetration testing should also be conducted to identify and address any potential vulnerabilities.

Finally, secure coding practices and guidelines should be followed to minimize the risk of introducing security vulnerabilities. This includes following the principle of least privilege, using secure APIs, and avoiding the use of known vulnerable components.

References