logo

Database

Non-encrypted confidential information

Need

Secure storage, transmission, and encryption of confidential information and credentials

Context

• Usage of Java for building robust and scalable applications

• Usage of Scala for building scalable and high-performance applications

• Usage of Scala for functional and object-oriented programming

• Usage of java.io.File for file input/output operations

• Usage of java.io.BufferedWriter for efficient writing of character streams in Java

• Usage of java.io.FileWriter for writing data to a file

• Usage of play.api.mvc for handling HTTP requests and building web applications in Play Framework

• Usage of play.api.db for database access in Play Framework

• Usage of Anorm for type-safe SQL queries in Scala

• Usage of javax.naming for accessing and managing naming and directory services in Java

• Usage of javax.naming.directory for accessing and manipulating directory services in Java

• Usage of java.util.Hashtable for storing key-value pairs in Java

• Usage of com.sun.jndi.ldap.LdapCtxFactory for LDAP (Lightweight Directory Access Protocol) connection and operations

• Usage of javax.naming.Context for accessing and managing naming and directory services in Java

• Usage of javax.naming.directory.InitialDirContext for accessing and manipulating directory services

• Usage of play.api.libs.json.Json for JSON parsing and serialization in Play Framework

• Usage of play.api.libs.json.JsValue for handling JSON data in Play Framework

• Usage of global execution context for concurrent programming in Scala

Description

1. Non compliant code

import java.io._
import play.api.mvc._

val file = new File("confidential.txt")
val bw = new BufferedWriter(new FileWriter(file))
bw.write("Confidential Information")
bw.close()
...

**Confidential file data and hardcoded application credentials.** The `java.io._` package is used to write the string `"Confidential Information"` straight to a file named `confidential.txt` via a `BufferedWriter`, with no encryption at all. Separately, a Play Framework `Controller` object hardcodes a `userName` and `password` as plain `String` literals. Anyone who gains access to the filesystem or the source code (including through version control) can read this data directly, and there is no hashing or encryption protecting any of it. **Credit card details processed without encryption.** The `submitPayment` method of `PaymentApplication` retrieves credit card details (card number, expiry date, and CVV) from the request body without any encryption or masking, then passes them to `processPayment` as plain text, in violation of the PCI DSS standard. This is a serious risk since the credit card information could be intercepted during transmission or logged in server logs, and would be exposed in the clear if the server itself were ever compromised. **Plain-text user queries stored in the database.** Using the Play Framework's Anorm library, `storeUserQuery` takes a user query as a string and inserts it directly into the `user_queries` table with no encryption. If an attacker gains access to the database, they can read every stored query in plain text — a serious risk if the queries contain sensitive information. **LDAP service credentials hardcoded in plain text.** `Context.SECURITY_PRINCIPAL` and `Context.SECURITY_CREDENTIALS` are set to a hardcoded username and password, which are then used to establish an `InitialDirContext` connection to the LDAP server. Anyone with access to the source code can read the password directly, and it cannot be rotated without changing and redeploying the code. **Base64-encoded credentials treated as if encrypted.** `CredentialsController.storeCredentials` reads a `base64Credentials` field from the JSON request body and stores it as-is. Base64 is only an encoding scheme, not an encryption method — it is trivially reversible, so anyone who obtains the stored value can decode it back to the original credentials. **Confidential data returned as hexadecimal encoding.** `HomeController.index` converts the string `"Confidential Information"` to its hexadecimal representation and returns it directly in the response with `Ok(hexData)`. Hexadecimal is only an encoding, not encryption, so anyone eavesdropping on the network traffic can trivially decode it back to plain text.

2. Steps

• Use a secure encryption algorithm to encrypt the confidential information before storing it.

• Generate a strong encryption key to ensure the security of the encrypted data.

• Store the encryption key securely, such as in a separate configuration file or using a key management system.

• Do not hardcode passwords or other credentials in the source code; use environment variables or a configuration file instead.

• Store passwords using a strong hashing algorithm rather than reversible encryption.

• Avoid using Base64 or hexadecimal encoding as a substitute for encryption — encoding is trivially reversible and provides no confidentiality.

• Enable encryption for the database connection, and use parameterized queries to prevent SQL injection.

• Remove hard-coded LDAP (or other directory service) credentials from the code, and use a secure connection (LDAPS) when connecting to the server.

• Follow PCI DSS standards and guidelines for handling and storing sensitive payment card information.

• Implement secure transmission of confidential information using HTTPS or another secure protocol between the client and the server.

• Implement proper access controls to restrict unauthorized access to the encrypted data, including who can decrypt it.

• Consider using a secure storage mechanism, such as a database with built-in encryption capabilities, to store the encrypted data.

• Implement secure authentication mechanisms such as OAuth or JWT, along with secure password reset and recovery processes.

• Regularly review, update, and patch the application, its dependencies, and its encryption mechanisms to stay up-to-date with the latest security practices.

• Perform regular security audits and penetration testing, and monitor and log access to sensitive information to detect unauthorized activity.

• Consider implementing additional security measures, such as data masking or tokenization, to further protect the confidential information.

3. Secure code example

import java.io._
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.spec.SecretKeySpec
import java.util.Base64
import play.api.mvc._
import play.api.libs.crypto.CookieSignerProvider...

**Confidential file data and application credentials.** The code now generates a secure AES encryption key, encrypts the confidential information with it, Base64-encodes the result, and only then writes it to the file. The `password` is now hashed using Play Framework's built-in `CookieSignerProvider`, injected via dependency injection, so the source code no longer contains the plaintext password. The encryption key and the `userName` should still come from a secure source, such as a key management system, environment variable, or database, rather than being hardcoded. **Credit card details.** The Play framework's `CSRFTokenSigner`, injected into `PaymentApplication`, is now used to encrypt the card number, expiry date, and CVV before they are passed to `processPayment`, which should decrypt them using securely stored and managed keys. Secure transmission (HTTPS) and PCI DSS-compliant storage of the encrypted details should also be implemented. **Database-stored user queries.** A top-level `encrypt` function using AES encryption (with a securely managed `dbSecretKey`) now encrypts the user query before it is stored in the database, so an attacker who gains access to the database cannot read the queries in plain text. **LDAP service credentials.** The hardcoded credentials are replaced with values loaded from a Typesafe `Configuration` file (`application.conf`), with the password itself coming from the `LDAP_PASSWORD` environment variable rather than being stored in the file — and the connection now uses secure LDAPS. **Base64-encoded credentials.** `CredentialsController` now encrypts the credentials with AES (via a private `encrypt` method, using a key loaded from the application's configuration rather than hardcoded) before storing them, instead of storing the reversible Base64 encoding directly. **Hexadecimal-encoded confidential data.** `HomeController` now encrypts the confidential data with AES and returns the Base64-encoded ciphertext, instead of returning a bare hexadecimal encoding of the plain text. The encryption key shown here is hardcoded for simplicity but should be securely stored and retrieved (e.g. from a key vault) in a real application. Across all six scenarios: use a strong, salted hashing algorithm for passwords, transmit confidential information only over HTTPS, implement secure authentication mechanisms such as OAuth or JWT, and regularly review and patch the encryption and authentication mechanisms in use.