Skip to main content

Non-encrypted confidential information - Credit Cards

Need

Secure encryption and masking of credit card information

Context

  • Usage of Go 1.16 for building high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go
  • Usage of net/http for building HTTP servers in a Node.js application

Description

Non compliant code

package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

type CardInfo struct {
CardNumber string `json:"card_number"`
CVV string `json:"cvv"`
ExpiryDate string `json:"expiry_date"`
}

func main() {
r := gin.Default()

r.POST("/card-info", func(c *gin.Context) {
var cardInfo CardInfo
if err := c.ShouldBindJSON(&cardInfo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// Process card information
// ...

c.JSON(http.StatusOK, gin.H{"message": "Card information processed successfully"})
})

r.Run()
}

In the above code, the credit card information entered by the user is directly sent to the server without any encryption. This is a major security flaw as it exposes sensitive user information to potential eavesdroppers.

The CardInfo struct is used to bind the JSON body of the POST request to /card-info. The ShouldBindJSON function is used to bind the incoming JSON body to the CardInfo struct. If the binding is successful, the card information is processed. However, this information is not encrypted at any point, which is a violation of the PCI DSS standard.

The PCI DSS standard requires that all sensitive cardholder data be encrypted at the point of capture, during transmission, and at rest. This means that the credit card number, CVV, and expiry date should all be encrypted before they are transmitted over the network.

If an attacker were to intercept the network traffic between the user and the server, they would be able to see the credit card information in plain text. This could lead to unauthorized transactions, fraud, or identity theft.

Steps

  • Implement Transport Layer Security (TLS) to encrypt communication between the client and the server.
  • Use a secure encryption algorithm to encrypt sensitive information such as credit card numbers, CVV, and expiry dates.
  • Ensure that the encryption keys are securely stored and managed.
  • Implement secure storage mechanisms for sensitive information, such as credit card numbers.
  • Implement secure authentication and authorization mechanisms to restrict access to sensitive information.
  • Regularly update and patch the server and framework to address any security vulnerabilities.
  • Follow the PCI DSS standard guidelines for handling and protecting credit card information.
  • Perform regular security audits and penetration testing to identify and address any vulnerabilities.

Compliant code

package main

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"github.com/gin-gonic/gin"
"io"
"net/http"
)

type CardInfo struct {
CardNumber string `json:"card_number"`
CVV string `json:"cvv"`
ExpiryDate string `json:"expiry_date"`
}

var key = []byte("a very strong key") // This should be stored securely and managed properly

func main() {
r := gin.Default()

r.POST("/card-info", func(c *gin.Context) {
var cardInfo CardInfo
if err := c.ShouldBindJSON(&cardInfo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

encryptedCardNumber, _ := encrypt(cardInfo.CardNumber, key)
encryptedCVV, _ := encrypt(cardInfo.CVV, key)
encryptedExpiryDate, _ := encrypt(cardInfo.ExpiryDate, key)

cardInfo.CardNumber = encryptedCardNumber
cardInfo.CVV = encryptedCVV
cardInfo.ExpiryDate = encryptedExpiryDate

// Process card information
// ...

c.JSON(http.StatusOK, gin.H{"message": "Card information processed successfully"})
})

r.RunTLS(":8080", "/path/to/cert.pem", "/path/to/key.pem") // Run server with TLS
}

func encrypt(stringToEncrypt string, key []byte) (encryptedString string, err error) {
plaintext := []byte(stringToEncrypt)

block, err := aes.NewCipher(key)
if err != nil {
return
}

aesGCM, err := cipher.NewGCM(block)
if err != nil {
return
}

nonce := make([]byte, aesGCM.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return
}

ciphertext := aesGCM.Seal(nonce, nonce, plaintext, nil)
encryptedString = base64.StdEncoding.EncodeToString(ciphertext)

return
}

The updated code now includes encryption for sensitive card information. The encrypt function uses the AES encryption algorithm to encrypt the card number, CVV, and expiry date. The encryption key is securely stored and managed.

The server now runs with Transport Layer Security (TLS) to encrypt all communication between the client and the server. The paths to the certificate and key files are provided in the RunTLS function.

Please note that the encryption key used in this example is a placeholder and should be replaced with a securely generated key. The key should be stored securely and managed properly.

The paths to the certificate and key files in the RunTLS function are placeholders and should be replaced with the actual paths to your certificate and key files.

This code is a step towards aligning with the PCI DSS standard for handling and protecting credit card information. Further steps should include implementing secure storage mechanisms for sensitive information, secure authentication and authorization mechanisms, regular updates and patches to the server and framework, and regular security audits and penetration testing.

References