Selection of Less-Secure Algorithm During Negotiation (Algorithm Downgrade)
Description
Selection of Less-Secure Algorithm During Negotiation, also known as Algorithm Downgrade, is a vulnerability that occurs when a security protocol or product negotiates which algorithm to use between multiple parties but does not select the strongest available option. Instead, the negotiation process allows or can be forced to select a weaker algorithm. This enables attackers to bypass security controls by forcing the use of algorithms with known weaknesses, such as forcing encrypted communications to use weaker ciphers or even cleartext transmission.
Risk
Algorithm downgrade attacks undermine security by forcing the use of weaker cryptographic options. If an attacker can force communications to use cleartext instead of encryption, they can passively sniff traffic without the effort of cryptanalysis. Forcing use of deprecated algorithms like DES, RC4, or MD5 makes brute-force or cryptanalytic attacks feasible. TLS/SSL downgrade attacks can force use of vulnerable protocol versions with known exploits. Authentication mechanisms that allow weaker methods can be exploited to bypass strong authentication. The risk is especially severe in man-in-the-middle positions where attackers can modify negotiation messages.
Solution
Configure systems to only accept strong algorithms and reject weak ones. Implement minimum algorithm strength requirements. Use protocol extensions that prevent downgrade attacks (like TLS_FALLBACK_SCSV for TLS). Avoid supporting legacy weak algorithms even for backward compatibility unless absolutely required. Regularly audit and update minimum security requirements as algorithms become deprecated. Monitor for downgrade attempts as they may indicate active attacks. Use authenticated negotiation mechanisms that detect tampering with algorithm selection messages.
Common Consequences
| Impact | Details |
|---|---|
| Access Control | Scope: Access Control Bypass Protection Mechanism - Downgrade allows bypassing intended security algorithms. |
| Confidentiality | Scope: Confidentiality Read Application Data - Weaker algorithms may be broken to expose encrypted data. |
| Integrity | Scope: Integrity Modify Application Data - Weak integrity algorithms may allow undetected modification. |
Example Code
Vulnerable Code
// Vulnerable: Server accepts any SSL/TLS version including weak ones
import javax.net.ssl.*;
public class VulnerableSSLServer {
public void vulnerableServerSocket() throws Exception {
SSLServerSocketFactory factory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket =
(SSLServerSocket) factory.createServerSocket(8443);
// Vulnerable: Accepts SSLv3, TLS 1.0, 1.1 - all have known weaknesses
// Default enables all protocol versions
// Attacker can force downgrade to SSLv3 (POODLE attack)
SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
// Connection may use vulnerable protocol version
}
}
// Vulnerable: Cipher suite includes weak algorithms
public class VulnerableCipherConfig {
public void configureWeakCiphers(SSLSocket socket) {
String[] weakCiphers = {
"TLS_RSA_WITH_AES_256_CBC_SHA256", // OK
"TLS_RSA_WITH_AES_128_CBC_SHA", // OK but old
"SSL_RSA_WITH_3DES_EDE_CBC_SHA", // Weak: 3DES
"SSL_RSA_WITH_RC4_128_SHA", // Weak: RC4
"SSL_RSA_WITH_DES_CBC_SHA", // Weak: DES
"SSL_RSA_EXPORT_WITH_RC4_40_MD5", // Export-grade: Very weak!
"TLS_RSA_WITH_NULL_SHA" // No encryption!
};
// Vulnerable: Allows weak and null ciphers
socket.setEnabledCipherSuites(weakCiphers);
}
}
# Vulnerable: Python SSL context allowing old protocols
import ssl
import socket
def vulnerable_ssl_connection(host, port):
# Vulnerable: Using SSLv23 allows downgrade to any version
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
# Vulnerable: Not disabling weak protocols
# SSLv2, SSLv3, TLS 1.0, TLS 1.1 all potentially enabled
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(sock, server_hostname=host)
ssl_sock.connect((host, port))
return ssl_sock
# Vulnerable: OpenSSL cipher string includes weak options
def vulnerable_cipher_config():
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
# Vulnerable: Cipher string includes weak algorithms
context.set_ciphers('ALL:!aNULL') # Includes RC4, DES, export ciphers
return context
// Vulnerable: OpenSSL configuration allowing downgrade
#include <openssl/ssl.h>
SSL_CTX* vulnerable_ssl_context() {
// Vulnerable: Uses method that allows version negotiation to weak versions
SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
// Vulnerable: No minimum version set
// Attacker can force SSLv3 or TLS 1.0
// Vulnerable: Weak cipher suites enabled
SSL_CTX_set_cipher_list(ctx, "ALL:!aNULL:!eNULL");
// Includes RC4, DES, 3DES, export ciphers
return ctx;
}
// Vulnerable: SSH allowing weak key exchange
/*
* SSH configuration allowing downgrade:
* KexAlgorithms diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,...
* Ciphers 3des-cbc,aes128-cbc,...
* MACs hmac-md5,hmac-sha1,...
*/
<!-- Vulnerable: IIS configuration allowing weak protocols -->
<system.webServer>
<security>
<access sslFlags="Ssl"/>
<!-- Vulnerable: No minimum TLS version enforced -->
<!-- Server accepts TLS 1.0, 1.1 which have known vulnerabilities -->
</security>
</system.webServer>
<!-- Vulnerable: Apache configuration -->
<!--
SSLProtocol all
# Vulnerable: 'all' includes SSLv3, TLS 1.0, TLS 1.1
SSLCipherSuite HIGH:MEDIUM:LOW
# Vulnerable: Includes MEDIUM and LOW strength ciphers
-->
Fixed Code
// Fixed: Server only accepts strong TLS versions
import javax.net.ssl.*;
public class SecureSSLServer {
public void secureServerSocket() throws Exception {
SSLServerSocketFactory factory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket =
(SSLServerSocket) factory.createServerSocket(8443);
// Fixed: Only enable TLS 1.2 and 1.3
serverSocket.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"});
// Fixed: Only strong cipher suites
serverSocket.setEnabledCipherSuites(getSecureCipherSuites());
SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
// Connection will use only strong protocols
}
private String[] getSecureCipherSuites() {
return new String[]{
// TLS 1.3 cipher suites
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256",
// TLS 1.2 cipher suites with AEAD
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
// No CBC mode, no RSA key exchange, no weak algorithms
};
}
}
// Fixed: Java system-wide configuration (Java 8+)
public class SecureJavaConfig {
static {
// Disable weak algorithms globally
java.security.Security.setProperty("jdk.tls.disabledAlgorithms",
"SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, " +
"DH keySize < 2048, EC keySize < 224, 3DES_EDE_CBC, anon, NULL");
}
}
# Fixed: Python SSL context with strong settings
import ssl
import socket
def secure_ssl_connection(host, port):
# Fixed: Create default context with strong settings
context = ssl.create_default_context()
# Fixed: Set minimum TLS version
context.minimum_version = ssl.TLSVersion.TLSv1_2
# Fixed: Only strong ciphers
context.set_ciphers(
'ECDHE+AESGCM:DHE+AESGCM:ECDHE+CHACHA20:DHE+CHACHA20:!aNULL:!MD5:!DSS'
)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(sock, server_hostname=host)
ssl_sock.connect((host, port))
return ssl_sock
# Fixed: Strict SSL context
def secure_strict_context():
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Fixed: TLS 1.2 minimum
context.minimum_version = ssl.TLSVersion.TLSv1_2
# Fixed: Verify certificates
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
# Fixed: Strong ciphers only
context.set_ciphers('ECDHE+AESGCM:DHE+AESGCM')
return context
// Fixed: OpenSSL configuration with strong settings
#include <openssl/ssl.h>
SSL_CTX* secure_ssl_context() {
// Fixed: Use TLS method (not SSLv23)
SSL_CTX* ctx = SSL_CTX_new(TLS_method());
// Fixed: Set minimum version to TLS 1.2
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
// Fixed: Strong cipher suites only
SSL_CTX_set_cipher_list(ctx,
"ECDHE+AESGCM:DHE+AESGCM:!aNULL:!MD5:!DSS:!RC4:!DES:!3DES:!EXPORT");
// Fixed: Prefer server cipher order
SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
// Fixed: Disable compression (CRIME attack)
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
return ctx;
}
# Fixed: Apache configuration with strong TLS
SSLEngine on
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off
# Fixed: Nginx configuration
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# ssl_prefer_server_ciphers on;
CVE Examples
- CVE-2005-2969: SSL/TLS implementation allowed downgrade to weaker protocol versions.
- CVE-2006-4302: Version downgrade vulnerability in protocol negotiation.
- CVE-2006-4407: Weak cipher selection allowed during negotiation.
- CVE-2001-1444: Telnet allowed authentication and encryption downgrade.
- CVE-2002-1646: SSH configuration could be overridden to use weaker schemes.
References
- MITRE Corporation. "CWE-757: Selection of Less-Secure Algorithm During Negotiation ('Algorithm Downgrade')." https://cwe.mitre.org/data/definitions/757.html
- CAPEC-220: Client-Server Protocol Manipulation.
- NIST Guidelines on TLS Implementations.