Back to Web Vulnerabilities: SQLi, XSS, CSRF, SSRF
Q3Question 3 of 7

Sensitive Data Exposure and How to Prevent It

Key Concepts
  • Sensitive data exposure is the failure to protect confidential data at rest, in transit, and in logs.
  • Passwords must be hashed with slow algorithms (bcrypt, Argon2) and never stored recoverable.
  • Data in transit must be encrypted with TLS: enforce HTTPS everywhere and enable HSTS.
  • Logs must never contain passwords, full card numbers, tokens, or raw PII: mask sensitive fields.
  • Recoverable sensitive data (account numbers, PII) should be encrypted at rest or tokenized.
  • Encryption key management: rotation and separation of keys from data is as important as the encryption itself.

Definition

Protect data at rest, in transit, and in logs: hash passwords, force TLS, and mask sensitive fields.
  • Sensitive data exposure – the failure to adequately protect confidential data at rest, in transit, and in logs, so it can be read by unauthorized parties.
  • At rest – passwords stored in plaintext or weak hashes, unencrypted PII in databases.
  • In transit – data sent over unencrypted HTTP instead of HTTPS/TLS.
  • In logs – PII, tokens, card numbers, or passwords written to log files accessible to unauthorized staff.
  • Defenses – bcrypt/Argon2 for passwords, TLS/HTTPS/HSTS everywhere, encryption at rest, masking in logs, secrets in a vault.

Sensitive data exposure is like National Bank of India writing customers' PINs on a public notice board (plaintext storage), shouting account details across the lobby (HTTP instead of HTTPS), and photocopying full card numbers into the daily diary that cleaners can read (PII in logs). The fixes are to store PINs only as scrambled irreversible codes, speak through a private sealed tube (TLS), and in any diary write only the last four digits of a card with the rest blacked out (masking).

Understanding the Concepts

What is sensitive data exposure?

Sensitive data exposure is the failure to adequately protect confidential data in its three states: at rest (stored), in transit (transmitted), and in logs (recorded). It lets unauthorized parties read data they should never see.

In banking, the exposed data is money, identity, and card details, making this especially dangerous.

TEXT
Three states of data:
  At rest:    passwords, card numbers, PII in databases
  In transit: data traveling over the network (HTTP vs HTTPS)
  In logs:    information written to log files, monitoring systems

Each state needs its own protection:
  At rest:    hash (passwords) or encrypt (PII, cards)
  In transit: TLS/HTTPS everywhere
  In logs:    mask, redact, or omit sensitive fields

How do you protect passwords at rest?

Passwords must never be stored recoverably. Use a slow, salted hash like bcrypt, scrypt, or Argon2. These are one-way: even a database breach does not reveal passwords. Never use MD5, SHA-1, or plaintext.

JAVA
package com.bank.security;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

public class PasswordProtection {

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder(12);

    public static void main(String[] args) {
        String raw = "Rajesh@SecurePass2024";

        // Store only the hash
        String hash = ENCODER.encode(raw);
        System.out.println("Stored: " + hash);
        // $2a$12$... (irreversible)

        // Verify on login
        System.out.println("Matches: " + ENCODER.matches(raw, hash)); // true
        System.out.println("Wrong:   " + ENCODER.matches("wrong", hash)); // false
    }
}
TEXT
Stored: $2a$12$kR7xP2qM9nTvWz3Y...bcrypt_hash
Matches: true
Wrong:   false

Even with full database access, attacker sees only irreversible hashes.

How do you protect data in transit?

Enforce TLS (HTTPS) everywhere. Redirect HTTP to HTTPS. Enable HSTS (Strict-Transport-Security) so browsers refuse plain HTTP. Use strong cipher suites. Internal service-to-service traffic should also use TLS.

JAVA
package com.bank.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class TlsConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .requiresChannel(channel -> channel
                .anyRequest().requiresSecure() // redirect HTTP to HTTPS
            )
            .headers(headers -> headers
                .httpStrictTransportSecurity(hsts -> hsts
                    .includeSubDomains(true)
                    .maxAgeInSeconds(31536000) // 1 year
                )
            );
        return http.build();
    }
}
TEXT
Response header:
Strict-Transport-Security: max-age=31536000; includeSubDomains

Result: browser refuses plain HTTP for 1 year.
All data encrypted in transit with TLS.

How do you protect sensitive data in logs?

Never log passwords, full card numbers, tokens, or raw PII. Mask fields so only the last few characters show.

JAVA
package com.bank.security;

public class LogMasker {

    public static String maskCardNumber(String cardNumber) {
        if (cardNumber == null || cardNumber.length() < 4) return "****";
        return "****-****-****-" + cardNumber.substring(cardNumber.length() - 4);
    }

    public static String maskAccount(String accountId) {
        if (accountId == null || accountId.length() < 4) return "****";
        return "****" + accountId.substring(accountId.length() - 4);
    }

    public static String maskToken(String token) {
        return "[REDACTED]";
    }

    public static void main(String[] args) {
        System.out.println("Card: " + maskCardNumber("4532123456789012"));
        System.out.println("Account: " + maskAccount("SAV2001"));
        System.out.println("Token: " + maskToken("eyJhbGciOi..."));
    }
}
TEXT
Card: ****-****-****-9012
Account: ****2001
Token: [REDACTED]

Safe to write to logs. No sensitive data exposed.

How do you protect recoverable sensitive data at rest?

For data that must be read back (unlike passwords), use encryption at rest. Account numbers and PII can be encrypted with AES at the application level or with database-level transparent data encryption. Highly sensitive values like full card numbers should be tokenized.

JAVA
package com.bank.security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.util.Base64;

public class DataEncryption {

    public static void main(String[] args) throws Exception {
        SecretKey key = KeyGenerator.getInstance("AES").generateKey();

        // Encrypt
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encrypted = cipher.doFinal("SAV2001-Rajesh-Kumar".getBytes());
        String stored = Base64.getEncoder().encodeToString(encrypted);
        System.out.println("Encrypted: " + stored);

        // Decrypt
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(stored));
        System.out.println("Decrypted: " + new String(decrypted));
    }
}
TEXT
Encrypted: kR7xP2qM9nTvWz3Y+5bC... (unreadable without key)
Decrypted: SAV2001-Rajesh-Kumar

Where should secrets be stored?

API keys, database passwords, and encryption keys must live in a secrets manager (Vault, AWS Secrets Manager, Azure Key Vault), not in source code or config files checked into version control.

TEXT
WRONG:
  application.yml: db.password=plaintext_password  (in Git!)
  Source code:     String apiKey = "ABC123";        (in Git!)

CORRECT:
  Environment variable: DB_PASSWORD (injected at deploy time)
  Secrets manager: vault.read("secret/db-password")
  Spring property: ${DB_PASSWORD} (resolved from env/vault)

What are common mistakes?

The most common mistake is logging full request bodies that contain passwords or tokens.

JAVA
// WRONG: logging request body (contains password!)
log.info("Login request: " + requestBody);
// Output: Login request: {"username":"rajesh","password":"SecurePass2024"}

// CORRECT: log only safe fields
log.info("Login attempt for user: " + username);
// Output: Login attempt for user: rajesh

Another mistake is returning detailed error messages that leak internal information.

JAVA
// WRONG: detailed error
return "Error: table 'accounts' column 'balance' not found at line 42";
// Leaks internal schema!

// CORRECT: generic error
return "An error occurred. Please try again.";
// Internal details logged server-side only

What about key management?

Encryption is only as strong as its key management. Keys must be rotated regularly, stored separately from the data they encrypt, and access-controlled. A compromised key compromises all data encrypted with it.

TEXT
Key management best practices:
  - Store keys in HSM or secrets manager, never alongside data
  - Rotate keys on a schedule (e.g., every 90 days)
  - Support key versioning: new data uses new key, old data decrypted with old key
  - Audit key access
  - Separate encryption keys from signing keys

What should a senior engineer know?

Senior engineers classify data into sensitivity levels and apply the appropriate control per level. They know that encryption without proper key management is security theater. They minimize data collection, set retention limits, and ensure that data at rest, in transit, and in logs all receive the right treatment.

Visual Overview

DIAGRAM
  Three States of Data Protection:
  ┌──────────────────────────────────────────────┐
  │              AT REST                          │
  │  Passwords ──► bcrypt/Argon2 hash             │
  │  PII/Cards ──► AES encryption or tokenization │
  │  Secrets   ──► Vault / secrets manager        │
  ├──────────────────────────────────────────────┤
  │              IN TRANSIT                        │
  │  All traffic ──► TLS/HTTPS                    │
  │  Browser    ──► HSTS header                   │
  │  Internal   ──► Mutual TLS                    │
  ├──────────────────────────────────────────────┤
  │              IN LOGS                           │
  │  Cards      ──► ****-****-****-9012           │
  │  Accounts   ──► ****2001                      │
  │  Tokens     ──► [REDACTED]                    │
  │  Passwords  ──► NEVER logged                  │
  └──────────────────────────────────────────────┘

Key Takeaway

Sensitive data exposure is the failure to adequately protect confidential data in its three states: at rest, in transit, and in logs. The common causes are storing passwords in plaintext or weak hashes, sending data over plain HTTP instead of HTTPS, logging personally identifiable information or secrets, weak encryption of stored data, and leaking data in error messages. In a bank this is especially serious because the exposed data is money, identity, and card details.

The approach is to apply the right control to each state. For passwords and credentials at rest, use a slow, salted, one-way hash like bcrypt or Argon2, so even a full database breach yields hashes that cannot be reversed. For recoverable sensitive data like account numbers, use encryption at rest, and for the most sensitive values like full card numbers, use tokenization so the real number never sits in the main datastore. Secrets like API keys live in a vault, not in code, and are rotated.

For data in transit, enforce TLS everywhere, redirect HTTP to HTTPS, enable HSTS so browsers refuse plain HTTP, and use mutual TLS between internal services. For logs, which are a frequent leak point, mask sensitive fields so only the last four digits of an account or card show and redact tokens entirely.

The nuances to stress are classifying data so you know what is sensitive, minimizing what is collected and setting retention limits, returning generic error messages that do not leak internal details, and treating key management: rotation and separation of keys from data, as being just as important as the encryption itself.

Remember one sentence: protect data in all three states: hash passwords at rest, encrypt everything in transit with TLS, and mask sensitive fields in logs.

---

Share
Use ← → arrow keys to navigate