Dictionary Attack with Mutual Tls
How Dictionary Attack Manifests in Mutual TLS
In a Mutual TLS (mTLS) handshake both parties present certificates, and the security of the exchange relies on the entropy of the private keys protecting those certificates. If a private key is stored encrypted with a low‑entropy passphrase, an attacker who obtains the key file can launch an offline dictionary attack: they guess passphrases, decrypt the key, and then impersonate the legitimate client or server. The same risk appears when a pre‑shared key (PSK) is used for TLS‑PSK (a variant of mTLS) and the PSK is derived from a weak password or short random value.
Attack flow:
- The adversary passively records a TLS handshake (possible because mTLS still encrypts application data, but the handshake messages are visible).
- If the handshake uses RSA key exchange, the encrypted pre‑master secret is captured; with a weak server private key the attacker can attempt to decrypt it by guessing the key’s passphrase.
- For TLS‑PSK, the server derives the master secret directly from the PSK; a low‑entropy PSK enables an offline dictionary attack on the handshake messages to recover the key and subsequently decrypt traffic.
- Once the key is recovered, the attacker can authenticate as either party, bypassing the mutual authentication that mTLS is meant to provide.
Mutual TLS-Specific Detection
middleBrick’s unauthenticated black‑box scan includes checks that reveal conditions favorable to dictionary attacks:
- Weak TLS configuration: scanning for disabled TLS 1.3, presence of RSA key exchange with export‑grade or small‑size RSA keys, and weak DH parameters (Logjam‑prone).
- Certificate validation gaps: verifying that the server requests and validates client certificates (
requestCert: truein Node.js,ClientAuth: tls.RequireAndVerifyClientCertin Go). Missing validation means an attacker can present a self‑signed cert after cracking the key. - PSK entropy assessment: when TLS‑PSK is detected, middleBrick estimates the key space size based on observed handshake lengths and flags values below 128 bits of entropy as susceptible to dictionary attacks.
- Private key protection hints: while middleBrick cannot read files, it can infer weak protection from the use of self‑signed certificates with short validity periods or from the presence of known weak cipher suites that often accompany legacy key storage practices.
The scan completes in 5–15 seconds and returns a finding with severity, a short description, and remediation guidance. For example, a finding might read: "Server accepts RSA key exchange with a 1024‑bit key; private key may be vulnerable to offline dictionary attack if protected by a weak passphrase."
Mutual TLS-Specific Remediation
Mitigate dictionary attack risk by strengthening the secrets that protect mTLS credentials and by configuring the TLS stack to resist low‑entropy key exchange.
1. Use strong, randomly generated passphrases or hardware protection
If you store private keys in PEM files, encrypt them with a high‑entropy passphrase (≥ 20 random characters) or, better yet, use a hardware security module (HSM) or cloud KMS that never exposes the raw key.
# Generate a 4096‑bit RSA key encrypted with AES‑256 and a strong passphrase
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -aes256 -out server_key.pem
# The command will prompt for a passphrase; use a password manager to store it.
2. Prefer elliptic curve Diffie‑Hellman (ECDHE) and TLS 1.3
TLS 1.3 removes RSA key exchange and mandates (EC)DHE with forward secrecy, eliminating the static RSA‑encrypted pre‑master secret that could be attacked offline.
// Go tls.Config example
conf := &tls.Config{
MinVersion: tls.VersionTLS13,
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool, // load trusted client CAs
}
3. If using TLS‑PSK, ensure sufficient entropy
Generate a PSK with at least 256 bits of randomness (32 bytes) and store it securely; never derive it from a user‑chosen password.
# Generate a 256‑bit base64‑encoded PSK
openssl rand -base64 32 > psk.txt
When configuring the server (e.g., with NGINX Plus or a custom Go TLS listener), load the PSK and set PreferServerCiphers to a suite that uses TLS‑PSK with AES‑256‑GCM.
4. Enforce strict client certificate validation
Always verify the client certificate chain, check revocation (OCSP stapling or CRL), and enforce hostname matching if applicable.
// Node.js tls.createServer example
const options = {
key: fs.readFileSync('server_key.pem'),
cert: fs.readFileSync('server_cert.pem'),
ca: fs.readFileSync('client_ca.pem'),
requestCert: true,
rejectUnauthorized: true, // abort if client cert fails validation
};
const server = tls.createServer(options, (socket) => {
// socket.authorized is true only if client cert validated
socket.write('welcome\n');
socket.end();
});
server.listen(8443);
By applying these controls, the entropy of the secret material rises well beyond the reach of offline dictionary attacks, and middleBrick’s subsequent scans will no longer emit findings related to weak mTLS secrets.