Cleartext Storage of Sensitive Information
Description
Cleartext Storage of Sensitive Information occurs when a product stores sensitive information in cleartext within a resource that might be accessible to another control sphere. Sensitive data such as passwords, personal identification numbers, cryptographic keys, credit card numbers, and personal health information must be protected when stored. When this data is stored without encryption or hashing, it becomes accessible to anyone who gains read access to the storage medium—whether through legitimate access to backups, log files, configuration files, databases, or through unauthorized access via exploitation of other vulnerabilities.
Risk
Cleartext storage vulnerabilities have contributed to massive data breaches exposing millions of records. When attackers compromise a system, finding plaintext credentials enables immediate lateral movement and privilege escalation. Database dumps containing unencrypted passwords expose all users to credential stuffing attacks across other services. Schneider Electric's CVE-2024-8070 exposed test credentials in firmware binaries. Jenkins OpenShift Pipeline plugin and Microsoft PC Manager both had cleartext storage issues in 2025. Cloud orchestration tools like Canonical Juju have exposed private keys. These vulnerabilities violate compliance requirements (PCI-DSS, HIPAA, GDPR) and result in regulatory penalties.
Solution
Encrypt sensitive information at rest using strong, industry-standard algorithms (AES-256). Use proper key management with hardware security modules (HSM) for key storage. Hash passwords with modern algorithms (Argon2, bcrypt, scrypt) rather than encrypting them. Implement proper access controls on storage locations. Avoid logging sensitive information. Encrypt database columns containing PII. Encrypt backups and configure proper access controls. Use secrets management solutions (HashiCorp Vault, AWS Secrets Manager) for credentials. Conduct regular audits to identify cleartext storage.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Data Exposure Sensitive information stored in cleartext is directly readable by attackers who gain access to storage. |
| Authentication | Scope: Credential Theft Plaintext passwords enable immediate account compromise and lateral movement. |
| Compliance | Scope: Regulatory Violations Cleartext storage of PII or cardholder data violates PCI-DSS, HIPAA, and GDPR requirements. |
Example Code + Solution Code
Vulnerable Code
# VULNERABLE: Storing passwords in plaintext
import sqlite3
def create_user(username, password):
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Password stored as plaintext - anyone with DB access can read it!
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)",
(username, password))
conn.commit()
# VULNERABLE: Credentials in configuration file
config = {
'database_host': 'localhost',
'database_user': 'admin',
'database_password': 'SuperSecret123!', # Plaintext in config!
'api_key': 'sk-1234567890abcdef' # API key exposed!
}
// VULNERABLE: Logging sensitive information
import java.util.logging.Logger;
public class UserService {
private static final Logger logger = Logger.getLogger(UserService.class.getName());
public void login(String username, String password) {
// Passwords logged in cleartext!
logger.info("Login attempt for user: " + username + " with password: " + password);
// Password stored in plaintext session
session.setAttribute("password", password);
}
}
// VULNERABLE: Storing tokens in localStorage without encryption
function saveAuthToken(token) {
// Token stored as plaintext - XSS can steal it
localStorage.setItem('authToken', token);
localStorage.setItem('refreshToken', refreshToken);
}
// VULNERABLE: Credentials in environment/config
const config = {
awsSecretKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
stripeApiKey: 'sk_live_1234567890abcdef'
};
Fixed Code
# SAFE: Password hashing with Argon2
from argon2 import PasswordHasher
from cryptography.fernet import Fernet
import os
ph = PasswordHasher()
def create_user_safe(username, password):
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Hash the password - cannot be reversed
password_hash = ph.hash(password)
cursor.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)",
(username, password_hash))
conn.commit()
def verify_password_safe(stored_hash, provided_password):
try:
return ph.verify(stored_hash, provided_password)
except:
return False
# SAFE: Encrypt sensitive configuration
def load_encrypted_config():
key = os.environ.get('CONFIG_ENCRYPTION_KEY') # Key from secure source
fernet = Fernet(key)
with open('config.encrypted', 'rb') as f:
encrypted_data = f.read()
decrypted_config = fernet.decrypt(encrypted_data)
return json.loads(decrypted_config)
// SAFE: No sensitive data in logs, encrypted session data
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
private final SecretKey encryptionKey;
public void login(String username, String password) {
// Never log passwords
logger.info("Login attempt for user: {}", username);
// Hash password for storage, encrypt for session if needed
String passwordHash = BCrypt.hashpw(password, BCrypt.gensalt(12));
// Clear password from memory as soon as possible
Arrays.fill(password.toCharArray(), '\0');
}
private byte[] encryptSessionData(String data) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
}
}
// SAFE: Encrypted storage with secure key management
const crypto = require('crypto');
class SecureStorage {
constructor(encryptionKey) {
this.key = Buffer.from(encryptionKey, 'hex');
}
encrypt(plaintext) {
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', this.key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
}
decrypt(ciphertext) {
const [ivHex, authTagHex, encrypted] = ciphertext.split(':');
const iv = Buffer.from(ivHex, 'hex');
const authTag = Buffer.from(authTagHex, 'hex');
const decipher = crypto.createDecipheriv('aes-256-gcm', this.key, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
// Use environment variables for credentials (loaded from secure secrets manager)
const config = {
awsSecretKey: process.env.AWS_SECRET_KEY, // From secrets manager
stripeApiKey: process.env.STRIPE_API_KEY
};
Exploited in the Wild
Schneider Electric Firmware (Schneider Electric, 2024)
CVE-2024-8070 in Schneider Electric products exposed test credentials stored in cleartext within firmware binaries, allowing attackers with access to firmware to extract authentication credentials.
Canonical Juju Private Keys (Canonical, 2025)
CVE-2025-6224 in Canonical Juju utils exposed private keys inadequately protected during storage and transmission, enabling attackers to extract cryptographic keys and gain unauthorized access to cloud services.
Jenkins OpenShift Pipeline Plugin (Jenkins, 2025)
Cleartext storage of sensitive information vulnerability in Jenkins OpenShift Pipeline plugin exposed credentials that could be accessed by users with access to Jenkins configuration files.
Tools to test/exploit
-
TruffleHog — scan for secrets in code repositories.
-
GitLeaks — detect hardcoded secrets in git repos.
-
Secrets Scanner — detect secrets in codebases.
CVE Examples
-
CVE-2024-8070 — Schneider Electric cleartext credentials in firmware.
-
CVE-2025-6224 — Canonical Juju cleartext private key storage.
-
CVE-2019-13945 — Siemens S7-1200 CPU password storage in cleartext.
References
-
MITRE. "CWE-312: Cleartext Storage of Sensitive Information." https://cwe.mitre.org/data/definitions/312.html
-
OWASP. "Password Storage Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html