How to Disable Weak Ciphers in Apache

How to disable weak ciphers in Apache

Every time I run a security audit on a client’s server, weak SSL/TLS ciphers are one of the first things I check for. They’re an easy win for attackers and an easy fix for administrators — yet I still find outdated cipher suites enabled on production servers more often than I’d like. If you’ve landed here because a penetration test flagged “weak ciphers” or you just want to harden your Apache server proactively, I’ll walk you through exactly how I disable them.

What Are Weak Ciphers, and Why Do They Matter?

A cipher suite defines how data gets encrypted during an SSL/TLS handshake. Older cipher suites — things like RC4, DES, 3DES, export-grade ciphers, and anything using MD5 for integrity checks — have known cryptographic weaknesses. Attacks like BEAST, POODLE, SWEET32, and FREAK all exploit weak ciphers or protocols that shouldn’t be in use anymore.

Leaving weak ciphers enabled means:

  • Your server may still negotiate a connection using compromised encryption if a client requests it.
  • Compliance frameworks like PCI-DSS, HIPAA, and SOC 2 will flag your configuration during audits.
  • Automated vulnerability scanners (Qualys SSL Labs, Nessus, OpenVAS) will downgrade your security rating.

Real-World Impact

I once worked with a client whose SSL Labs grade was stuck at a “C” purely because of legacy RC4 and 3DES ciphers left over from an old load balancer migration. Disabling them took fifteen minutes and pushed the grade to an “A” instantly — no other changes needed.

Prerequisites

  • Apache 2.4+ with mod_ssl enabled.
  • Root/sudo access to edit Apache configuration files.
  • OpenSSL installed for testing (usually bundled by default).
  • A valid SSL certificate already installed (if you haven’t set this up yet, that’s a separate step from disabling ciphers).

Step 1: Locate Your SSL Configuration File

Depending on your distro, this is typically:

  • Debian/Ubuntu: /etc/apache2/mods-available/ssl.conf or inside your virtual host’s SSL block.
  • CentOS/RHEL: /etc/httpd/conf.d/ssl.conf.

I always make a backup before touching it:

sudo cp /etc/apache2/mods-available/ssl.conf /etc/apache2/mods-available/ssl.conf.bak

Step 2: Check Your Current Cipher Configuration

I run this to see what’s currently negotiable on the server:

nmap --script ssl-enum-ciphers -p 443 yourdomain.com

Or with testssl.sh, which I prefer for a more detailed breakdown:

./testssl.sh yourdomain.com

This tells me exactly which weak ciphers are currently accepted so I know what I’m fixing.

Step 3: Define a Strong Cipher Suite

Inside the SSL configuration block (or your <VirtualHost> for port 443), I set the SSLCipherSuite and SSLProtocol directives. Here’s a configuration I commonly deploy that balances strong security with broad compatibility:

SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          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
SSLHonorCipherOrder     on
SSLCompression          off
SSLSessionTickets       off

If you want a much stricter, modern-only configuration (dropping support for older clients), I use:

SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
SSLCipherSuite          TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
SSLHonorCipherOrder     on

That second block is TLS 1.3-only, which drops compatibility with a lot of older browsers and clients — I only use it when I know exactly who’s connecting (internal APIs, modern-browser-only sites).

Breaking Down What Changed

  • SSLProtocol — disables SSLv3, TLS 1.0, and TLS 1.1, all of which have known vulnerabilities (POODLE, BEAST).
  • SSLCipherSuite — explicitly lists only strong, forward-secrecy-capable ciphers using AES-GCM or ChaCha20-Poly1305.
  • SSLHonorCipherOrder on — forces the server (not the client) to pick the cipher order, preventing a malicious client from forcing a weak cipher.
  • SSLCompression off — mitigates the CRIME attack.
  • SSLSessionTickets off — reduces some forward-secrecy risks associated with session ticket reuse.

Step 4: Apply Changes to All Virtual Hosts

If you run multiple <VirtualHost> blocks for port 443, make sure each one either includes the same directives or references a shared SSL configuration file with an Include directive:

<VirtualHost *:443>
    ServerName example.com
    Include /etc/apache2/ssl-hardening.conf
    ...
</VirtualHost>

I like centralizing this in one include file so I only need to update cipher policy in one place.

Step 5: Test the Configuration

Always test syntax before reloading:

sudo apachectl configtest

Then reload Apache:

sudo systemctl reload apache2

Understanding Which Ciphers to Avoid

Over the years I’ve built a mental blacklist of cipher components that should never appear in a modern SSLCipherSuite directive:

  • NULL ciphers — provide no encryption at all; somehow still show up in default OpenSSL builds occasionally.
  • EXPORT ciphers — deliberately weakened for old export regulations; trivially breakable today.
  • RC4 — has known statistical biases that make it feasible to recover plaintext given enough traffic.
  • DES and 3DES — vulnerable to the SWEET32 birthday attack due to a 64-bit block size.
  • MD5-based MACs — MD5 is cryptographically broken for collision resistance.
  • Anonymous Diffie-Hellman (ADH) — provides encryption without authentication, making it trivially vulnerable to man-in-the-middle attacks.

I explicitly exclude these using a negative cipher string if I want a shorter directive, though I still prefer an explicit allow-list for clarity:

SSLCipherSuite HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4

That said, I generally trust the explicit allow-list approach shown earlier more than a deny-list, since new weak ciphers occasionally get added to OpenSSL’s HIGH category over time, and a deny-list has to keep chasing them.

Step 6: Verify Weak Ciphers Are Gone

I re-run the same scan from Step 2 and confirm the weak ciphers no longer appear:

nmap --script ssl-enum-ciphers -p 443 yourdomain.com

I also check with the SSL Labs Server Test for an independent, publicly trusted grade — it’s the tool I most often send to clients as proof of remediation.

Common Mistakes I See

  • Disabling TLS 1.2 too aggressively — a surprising number of enterprise clients and older mobile devices still rely on TLS 1.2; don’t drop it unless you’re certain.
  • Forgetting SSLHonorCipherOrder on — without this, a client can still request a weaker cipher from your allowed list even if you’ve trimmed it down.
  • Not restarting/reloading after config changes — Apache won’t apply new SSL settings until reloaded.
  • Only fixing the default site and forgetting cipher settings need to apply to every SSL-enabled virtual host.

Security Best Practices

  • Disable SSLv2, SSLv3, TLS 1.0, and TLS 1.1 entirely — none of them are considered secure anymore.
  • Prioritize AEAD ciphers (AES-GCM, ChaCha20-Poly1305) over CBC-mode ciphers.
  • Enable SSLHonorCipherOrder on so the server dictates cipher negotiation.
  • Periodically re-scan your server — cipher recommendations evolve as new vulnerabilities are discovered.
  • Pair cipher hardening with HSTS (Strict-Transport-Security) to prevent protocol downgrade attacks entirely.
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

Performance Optimization Tips

Modern AEAD ciphers like AES-GCM and ChaCha20-Poly1305 aren’t just more secure — they’re also faster than older CBC-mode ciphers on hardware with AES-NI support. So hardening your cipher suite often improves performance as a side effect, not just security.

I also recommend enabling OCSP stapling alongside cipher hardening to reduce TLS handshake latency (I cover this in a separate, dedicated guide on OCSP stapling).

Keeping Cipher Policy Current Over Time

Cipher hardening isn’t a one-time task. I schedule a recurring reminder (quarterly, at minimum) to:

  1. Re-run an SSL Labs or testssl.sh scan against every production domain.
  2. Check for newly disclosed vulnerabilities affecting cipher suites I currently allow.
  3. Compare my configuration against the latest Mozilla SSL Configuration Generator recommendations for “Intermediate” or “Modern” compatibility profiles.
  4. Review access logs for any clients still connecting with protocols I’m considering deprecating, so I can gauge the real-world impact before making a change.

I’ve found that automating this check with a simple cron job that emails me the testssl.sh output saves a lot of manual effort and catches configuration drift after unrelated changes (like a package upgrade resetting a config file).

Troubleshooting

Problem: Older clients can’t connect anymore This usually means you’ve dropped TLS 1.0/1.1 or a cipher an old client depends on. Check your access logs for handshake failures and weigh compatibility against security needs.

Problem: apachectl configtest fails after editing SSLCipherSuite Double-check for typos or stray colons in the cipher list — a single malformed entry breaks the whole directive.

Problem: SSL Labs still shows weak ciphers after reload Clear any CDN or reverse proxy cache in front of your server, since it might be terminating TLS itself with its own cipher policy.

FAQs

Will disabling weak ciphers break my website for users? For the vast majority of modern users on updated browsers, no. It’s a small percentage of users on very old software who might be affected, and honestly, they’re the ones most at risk from weak encryption anyway.

How often should I review my cipher suite? I recommend reviewing it at least once a year, or immediately after any major TLS-related vulnerability disclosure.

Should I disable TLS 1.2? Not unless you have a specific reason to require TLS 1.3 only. TLS 1.2 with strong ciphers is still considered secure.

Summary and Key Takeaways

Disabling weak ciphers in Apache is one of the highest-value, lowest-effort security improvements you can make. By explicitly defining a strong SSLCipherSuite, disabling outdated protocols, and enforcing server-side cipher order, you close off a whole category of downgrade and eavesdropping attacks.

Key takeaways:

  • Disable SSLv3, TLS 1.0, and TLS 1.1 — none are secure.
  • Use an explicit SSLCipherSuite with only AEAD ciphers.
  • Set SSLHonorCipherOrder on to prevent client-forced downgrades.
  • Test with testssl.sh or SSL Labs after every change.

References

Total
1
Shares

Leave a Reply

Previous Post
How to configure Apache for Perfect Forward Secrecy (PFS)

How to Configure Apache for Perfect Forward Secrecy (PFS)

Next Post
How to set up load balancing with Apache using mod_proxy

How to Set Up Load Balancing with Apache Using mod_proxy

Related Posts