SSLv3’s padding oracle vulnerability means attackers can decrypt sensitive data, a problem that became critical with POODLE and BEAST.

openssl s_client -connect example.com:443 -ssl3

If this command connects and shows a certificate, your server still supports SSLv3.

Common Causes & Fixes

1. Apache HTTP Server Configuration

  • Diagnosis: Check your Apache SSL configuration file (e.g., /etc/httpd/conf.d/ssl.conf or /etc/apache2/mods-enabled/ssl.conf).
  • Cause: The SSLProtocol directive includes SSLv3.
  • Fix: Remove SSLv3 from the SSLProtocol directive. A good setting is:
    SSLProtocol -All +TLSv1.2 +TLSv1.1
    
    This explicitly disables all protocols except TLSv1.2 and TLSv1.1, ensuring SSLv3 is off.
  • Why it works: Apache directly controls which SSL/TLS protocols the server will negotiate with clients. Removing SSLv3 from this list prevents any SSLv3 handshake from succeeding.

2. Nginx Configuration

  • Diagnosis: Examine your Nginx server block configuration file (often in /etc/nginx/sites-available/ or /etc/nginx/conf.d/).
  • Cause: The ssl_protocols directive lists SSLv3.
  • Fix: Remove SSLv3 from the ssl_protocols directive. A secure setting is:
    ssl_protocols TLSv1.2 TLSv1.1;
    
    This ensures only TLSv1.2 and TLSv1.1 are offered, excluding SSLv3.
  • Why it works: Nginx uses ssl_protocols to dictate the highest and lowest TLS/SSL versions it will allow for a connection. Removing SSLv3 prevents its use.

3. HAProxy Configuration

  • Diagnosis: Inspect your HAProxy configuration file (usually /etc/haproxy/haproxy.cfg).
  • Cause: The ssl-default-server-options or specific frontend options directive includes ssl-v3.
  • Fix: Remove ssl-v3 from the relevant options line. A secure configuration would look like this:
    frontend my_https_frontend
        bind *:443 ssl crt /etc/ssl/certs/mycert.pem
        option ssl-server-hello
        http-request add-header Strict-Transport-Security "max-age=31536000;"
        default_backend my_backend
        # Ensure SSLv3 is NOT in the options
        # Example of what to REMOVE if present:
        # server-options ssl-v3
        # Example of a secure setting if you were to specify protocols (less common here):
        # ssl-default-server-options no-sslv3
    
    More commonly, you’d ensure your bind directive doesn’t explicitly enable ssl-v3 and rely on the absence of it in the global ssl-default-server-options or specific frontend options. If you do specify, ensure it’s no-sslv3.
  • Why it works: HAProxy acts as a reverse proxy and SSL terminator. The options directive controls its SSL/TLS negotiation behavior, and disabling ssl-v3 prevents it from establishing such connections.

4. Load Balancer or Network Appliance Configuration

  • Diagnosis: Access the management interface of your hardware or cloud load balancer (e.g., AWS ELB, F5 BIG-IP, Cloudflare).
  • Cause: The SSL/TLS profile or policy applied to your listener or virtual server is configured to allow SSLv3.
  • Fix: Navigate to the SSL/TLS settings for your listener or virtual server and explicitly disable SSLv3. Look for options like "SSLv3 Enabled" and set it to "No" or remove it from the list of allowed protocols. For AWS ELB, choose a Security Policy that doesn’t include SSLv3 (e.g., ELBSecurityPolicy-TLS-1-2-2017-01).
  • Why it works: Load balancers often handle SSL termination. They need to be configured to disallow insecure protocols at the point of connection.

5. Application Server (Tomcat, Jetty, etc.) Configuration

  • Diagnosis: Check the server.xml (Tomcat) or equivalent configuration file for your application server.
  • Cause: The sslProtocol or protocols attribute in the SSL/TLS connector is set to include SSLv3.
  • Fix: Remove SSLv3 from the connector’s protocol attribute. For Tomcat:
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLSv1.2,TLSv1.1">
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    </Connector>
    
    This explicitly sets the allowed protocols to TLSv1.2 and TLSv1.1.
  • Why it works: The application server is directly responsible for its own SSL/TLS negotiation when it’s the endpoint. Modifying the connector configuration tells the server’s embedded SSL/TLS engine not to offer or accept SSLv3.

6. Client-Side Libraries or Applications

  • Diagnosis: If you’re seeing this error from an application you control (e.g., a script making API calls), check its underlying SSL/TLS library.
  • Cause: The application is configured to try SSLv3, or its default library settings are outdated. This is less common for direct server configuration but can happen with custom clients.
  • Fix: Update the library (e.g., requests in Python, OpenSSL bindings) or explicitly configure it to use modern TLS versions. For requests in Python, ensure you’re using a recent version which defaults to TLSv1.2. If you need to force it:
    import ssl
    import requests
    
    # Create a TLS context that only allows TLSv1.2
    context = ssl.create_default_context()
    context.minimum_version = ssl.TLSVersion.TLSv1_2
    context.maximum_version = ssl.TLSVersion.TLSv1_2
    
    try:
        response = requests.get('https://example.com', verify=True, ssl_context=context)
        print(response.status_code)
    except requests.exceptions.SSLError as e:
        print(f"SSL Error: {e}")
    
  • Why it works: The client’s SSL/TLS context is being explicitly restricted to only negotiate TLSv1.2, preventing any attempt to fall back to SSLv3.

After disabling SSLv3, you’ll likely encounter errors related to older clients that only support SSLv3 (e.g., Internet Explorer on Windows XP). You’ll need to manage those exceptions or encourage upgrades.

Want structured learning?

Take the full Tls-ssl course →