Non-encrypted confidential information
Need
Secure storage, transmission, and encryption of confidential information and credentials
Context
• Usage of C# 7.0 for modern language features and enhancements
• Usage of Microsoft.AspNetCore.Mvc for building web applications using the ASP.NET Core MVC framework
• Usage of Microsoft.EntityFrameworkCore for working with databases in .NET applications
• Usage of Microsoft.AspNetCore.Mvc.ViewFeatures for rendering views and managing view data in ASP.NET Core MVC
• Usage of System.DirectoryServices.Protocols for interacting with directory services
• Usage of Firebase.Database for real-time data storage and synchronization
• Usage of System.Text for string manipulation and encoding/decoding
Description
1. Non compliant code
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
public class UserController : Controller
{...**Plain-text password storage and comparison.** The `UserController`'s `Create` method stores the user's password directly into the database via `UserContext`, and the `Login` method compares the submitted username and password against a hardcoded value. The password is stored and compared in plain text, so anyone with access to the database or source code can see or determine the user's credentials. **Unencrypted credit card details.** The `PaymentController`'s `ProcessPayment` method receives `cardNumber`, `expiryDate`, and `cvv` without applying any encryption or masking, in violation of the PCI DSS standards that require sensitive cardholder data to be encrypted during transmission. **LDAP service credentials in plain text.** The `LdapService` class hard-codes `ldapUsername` and `ldapPassword` directly in the source code and uses them to authenticate an `LdapConnection`. **Non-encrypted confidential data on local devices.** The `FirebaseService`'s `StoreDataLocally` method writes confidential Firebase data to a local text file using `File.WriteAllText` in plain text format. **Base64-encoded secret key.** The `AppSettings` class stores a secret key using Base64 encoding (`SecretKey = "VGVzdFNlY3JldEtleQ=="`), which is easily decoded back to the original value and is not a secure method of storing confidential information. **Hexadecimal encoding mistaken for encryption.** The `ConfidentialDataController`'s `GetConfidentialData` method converts confidential data into a hexadecimal string using `BitConverter.ToString`, which only changes the representation of the data without encrypting it. In every case, anyone with access to the database, source code, or network traffic can trivially recover the confidential information and credentials, which can lead to unauthorized access, data leaks, or PCI DSS violations.
2. Steps
• Implement encryption for storing confidential information, using a secure algorithm such as AES or RSA.
• Generate a unique encryption key for each user or context, and ensure it is securely stored and not accessible to unauthorized users.
• Implement decryption logic to retrieve and display the confidential information when needed, using the same securely stored key.
• Store passwords securely using a strong, salted hashing algorithm, never in plain text, and avoid hardcoding or comparing credentials in plain text in the source code.
• Use a secure password storage and verification mechanism such as ASP.NET Core Identity, and implement secure authentication mechanisms such as multi-factor authentication.
• Use secure protocols (e.g., HTTPS) to transmit confidential data such as payment card details, and mask sensitive information on the client side before sending it to the server.
• Follow the PCI DSS standard guidelines for handling and storing payment card information, including server-side validation of received data.
• Remove hard-coded credentials and secret keys from the source code and store them securely, such as in `appsettings.json`, a secure key vault, or environment variables.
• Encrypt confidential information before storing it, whether on local devices, in a database, or in a configuration file.
• Ensure connections to external services such as LDAP are established over SSL/TLS and that their credentials are retrieved from secure storage at runtime.
• Do not rely on Base64 or hexadecimal encoding as a substitute for encryption; use a proper encryption algorithm such as AES instead.
• Regularly review and update the encryption mechanism, and update and patch the application and its dependencies to address any security vulnerabilities.
3. Secure code example
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
public class UserController : Controller
{...**Plain-text password storage and comparison.** An `IEncryptionService` encrypts the user's password before it is stored, and `UserManager<User>`/`SignInManager<User>` from ASP.NET Core Identity are used for `PasswordSignInAsync` instead of comparing plain-text values. **Unencrypted credit card details.** The `IDataProtector` interface from `Microsoft.AspNetCore.DataProtection` is used to encrypt the card number, expiry date, and CVV before the payment is processed; HTTPS, client-side masking, and PCI DSS-compliant storage should also be applied. **LDAP service credentials in plain text.** The hard-coded LDAP credentials are removed and retrieved from `IConfiguration` at runtime, using keys such as "Ldap:Username" and "Ldap:Password", which should in turn be sourced from a secured, encrypted configuration or a secrets vault. **Non-encrypted confidential data on local devices.** An `EncryptData` method uses AES via `Rfc2898DeriveBytes` to derive a key and IV and encrypt the data before it is written to local storage. **Base64-encoded secret key.** The hardcoded secret key is removed from `AppSettings` and instead retrieved from the `appsettings.json` configuration (or, in production, a secure store such as Azure Key Vault or AWS Secrets Manager) at runtime. **Hexadecimal encoding mistaken for encryption.** An `EncryptData` method uses the AES encryption algorithm with a generated IV to encrypt the confidential data before it is returned, instead of merely hex-encoding it. In every case, encryption and decryption keys should be securely generated, stored, and rotated, and the encryption and authentication mechanisms should be regularly reviewed and updated to use the latest security standards.
References
• 020. Non-encrypted confidential information