Skip to main content
All fixes

SSL, TLS, security headers

Disable weak SSL ciphers and enforce modern TLS suites

Your server still negotiates RC4, 3DES, or CBC ciphers that fail PCI scans and SSL Labs grades B or below. Enforce ECDHE-AES-GCM and ChaCha20-Poly1305 only.

What's happening

Weak ciphers are TLS cipher suites whose primitives — block cipher, mode of operation, MAC, or key exchange — are known to be broken or to provide insufficient security margin in 2026. RC4 is broken. 3DES is meet-in-the-middle attackable and fails the SWEET32 birthday bound. Static RSA key exchange has no forward secrecy. CBC modes paired with HMAC are vulnerable to Lucky13 and padding oracle attacks if not implemented in constant time.

When a server advertises these suites in its ServerHello, scanners (Qualys SSL Labs, Mozilla Observatory, internal PCI scanners) flag the configuration. The connection itself usually works because the client picks the strongest mutually supported suite, but a misconfigured client or a downgrade attack can still land on the weak option.

The fix is to restrict the server's cipher list to suites built on ECDHE key exchange, AEAD modes (GCM or ChaCha20-Poly1305), and SHA-256 or better. On TLS 1.3 this is automatic — every TLS 1.3 suite is AEAD with forward secrecy. On TLS 1.2 you must explicitly remove the weak suites.

Why it matters

Failed PCI-DSS scans block your card-processing certification. Trustwave, SecurityMetrics, and Qualys ASV scanners all reject 3DES and RC4 outright since 2018; the scan report lists every site as non-compliant and the merchant cannot transact until fixed.

SSL Labs grades drop to B or below, which is publicly visible to anyone who runs the test. Bug-bounty hunters and security-conscious customers use this as a smell test.

Weak suites enable downgrade attacks (FREAK, Logjam, BEAST). A nation-state or coffee-shop attacker who can MITM the handshake can force the connection onto the weak suite and break it offline.

Common causes

  • Default OS cipher lists from older Linux distributions still include 3DES and RC4.
  • Custom ssl_ciphers line copied from a 2014 blog post and never reviewed.
  • TLS 1.2 enabled with no explicit cipher restriction, defaulting to OpenSSL's HIGH list which includes weak options.
  • Hardware load balancers running firmware older than the cipher's deprecation date.
  • Java application servers (Tomcat, Jetty) with default JSSE cipher lists.

Detect this on your site

Run a quick scan with the SSL Checker. The tool surfaces this exact issue with the records and context needed to apply the fix below.

Open SSL Checker

How to fix it

  1. 1

    Enumerate negotiable cipher suites

    Run nmap --script ssl-enum-ciphers -p 443 example.com. The output groups suites by TLS version and grades each one. Anything graded C, D, or E should be removed. Alternatively use testssl.sh example.com for a more detailed report.

  2. 2

    Adopt the Mozilla intermediate profile

    Mozilla publishes maintained TLS configurations at ssl-config.mozilla.org. Pick the 'intermediate' profile unless you have a specific reason for 'modern' (which drops TLS 1.2 entirely). The generator outputs nginx, Apache, HAProxy, and AWS configurations directly.

  3. 3

    Apply the cipher list to nginx

    Set ssl_protocols TLSv1.2 TLSv1.3; and ssl_ciphers to the Mozilla intermediate list. Also set ssl_prefer_server_ciphers off; — modern advice flipped on this; with TLS 1.3 client preference is fine because every suite is strong.

  4. 4

    Apply the cipher list to Apache

    In Apache use SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 and SSLCipherSuite set to the Mozilla intermediate string. Add SSLHonorCipherOrder off for the same reason. Reload with sudo apachectl -t && sudo systemctl reload apache2.

  5. 5

    Restart and re-scan

    Reload the server and re-run the nmap or testssl.sh scan. Confirm only TLS 1.2 and TLS 1.3 are negotiable, with AEAD suites only. PCI scanners will need a fresh run; SSL Labs caches its grade for 24 hours but you can force a refresh from the test page.

  6. 6

    Lock the configuration in version control

    Commit the cipher line into your infrastructure repo and add a CI check that fails if the line drifts. Cipher recommendations evolve — set a calendar reminder to re-review against Mozilla's profile every 12 months.

Example

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;

Mozilla intermediate cipher profile for nginx

Frequently asked

Yes with a strict AEAD-only cipher list and no static RSA key exchange. Mozilla's intermediate profile keeps TLS 1.2 specifically because some payment terminals and IoT devices have not migrated. Drop to TLS 1.3-only when your client telemetry shows you can.

Renegotiation has been deprecated; OpenSSL since 1.0.2 only allows secure renegotiation per RFC 5746. There is no separate switch needed. If you see scanner findings about renegotiation they are usually about TLS 1.0 — disabling 1.0 fixes both.

Related fixes