Secure encryption and masking of credit card information
from django.db import models
class CreditCard(models.Model):
card_number = models.CharField(max_length=16)
card_cvv = models.CharField(max_length=3)
expiry_date = models.CharField(max_length=5)
cardholder_name = models.CharField(max_length=100)
In the above code, we have a Django model
CreditCard
that stores credit card information. The model includes fields for the card number, CVV, expiry date, and cardholder name.
The vulnerability here lies in the fact that the credit card information is stored as plain text in the database. This means that if an attacker gains access to the database, they would be able to view all the sensitive credit card information stored in it.
This is a direct violation of the PCI DSS (Payment Card Industry Data Security Standard), which stipulates that sensitive cardholder data must be encrypted and adequately protected.
To make matters worse, the CVV (Card Verification Value) is also stored in the database. The PCI DSS explicitly prohibits the storage of CVV post-transaction. So, even if the card number is encrypted, the storage of CVV still remains a significant vulnerability.
In conclusion, the code is vulnerable because it stores sensitive credit card information in plain text and also stores the CVV, both of which are against the PCI DSS requirements.
from django.db import models
from cryptography.fernet import Fernet
import base64
import os
class CreditCard(models.Model):
card_number = models.BinaryField()
card_cvv = models.BinaryField()
expiry_date = models.CharField(max_length=5)
cardholder_name = models.CharField(max_length=100)
def save(self, *args, **kwargs):
key = base64.urlsafe_b64encode(os.urandom(32))
cipher_suite = Fernet(key)
self.card_number = cipher_suite.encrypt(self.card_number.encode())
self.card_cvv = cipher_suite.encrypt(self.card_cvv.encode())
super().save(*args, **kwargs)
def __str__(self):
key = base64.urlsafe_b64encode(os.urandom(32))
cipher_suite = Fernet(key)
return '{} - {}'.format(self.cardholder_name, cipher_suite.decrypt(self.card_number)[-4:])
The above code fixes the vulnerability by encrypting the credit card number and CVV before storing them in the database. The
Fernet
class from the
cryptography
library is used for encryption and decryption. A new encryption key is generated each time a credit card is saved or displayed. The key is generated using the
os.urandom
function, which generates a string of random bytes suitable for cryptographic use.
The
save
method is overridden to encrypt the card number and CVV before saving the credit card. The
__str__
method is overridden to decrypt the card number when displaying it, and only the last 4 digits are shown.
The
card_number
and
card_cvv
fields are changed from
CharField
to
BinaryField
to store the encrypted data.
Please note that this is a basic implementation and does not include key management. In a real-world application, you would need to securely store and manage the encryption keys. You would also need to implement access controls to limit who can view and modify the sensitive data.