CVSS2
Attack Vector
NETWORK
Attack Complexity
LOW
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:N/I:N/A:P
EPSS
Percentile
95.5%
The remote libssh server contains a double-free memory flaw in the ssh_packet_kexinit() function in kex.c. A remote attacker, with a specially crafted SSH_MSG_KEXINIT packet, can cause a denial of service.
#
# (C) Tenable Network Security, Inc.
#
include("compat.inc");
if (description)
{
script_id(80556);
script_version("1.6");
script_set_attribute(attribute:"plugin_modification_date", value:"2022/06/21");
script_cve_id("CVE-2014-8132");
script_bugtraq_id(71865);
script_name(english:"Libssh ssh_packet_kexinit() Double-free Memory DoS");
script_summary(english:"Checks the response from libssh server.");
script_set_attribute(attribute:"synopsis", value:
"The remote SSH service is affected by a remote denial of service
vulnerability.");
script_set_attribute(attribute:"description", value:
"The remote libssh server contains a double-free memory flaw in the
ssh_packet_kexinit() function in kex.c. A remote attacker, with a
specially crafted SSH_MSG_KEXINIT packet, can cause a denial of
service.");
# https://www.libssh.org/2014/12/19/libssh-0-6-4-security-and-bugfix-release/
script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?54cafa11");
script_set_attribute(attribute:"see_also", value:"https://bugzilla.redhat.com/show_bug.cgi?id=1158089");
script_set_attribute(attribute:"solution", value:"Upgrade to libssh 0.6.4 or later.");
script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:N/I:N/A:P");
script_set_cvss_temporal_vector("CVSS2#E:U/RL:OF/RC:C");
script_set_attribute(attribute:"exploitability_ease", value:"No known exploits are available");
script_set_attribute(attribute:"exploit_available", value:"false");
script_set_attribute(attribute:"vuln_publication_date", value:"2014/12/19");
script_set_attribute(attribute:"patch_publication_date", value:"2014/12/19");
script_set_attribute(attribute:"plugin_publication_date", value:"2015/01/16");
script_set_attribute(attribute:"plugin_type", value:"remote");
script_set_attribute(attribute:"cpe", value:"cpe:/a:libssh:libssh");
script_end_attributes();
script_category(ACT_GATHER_INFO);
script_family(english:"Denial of Service");
script_copyright(english:"This script is Copyright (C) 2015-2022 Tenable Network Security, Inc.");
script_dependencies("ssh_detect.nasl");
script_require_ports("Services/ssh", 22);
exit(0);
}
include('audit.inc');
include("global_settings.inc");
include("misc_func.inc");
include('ssh_lib.inc');
enable_ssh_wrappers();
function ssh_errexit()
{
local_var code, error, msg;
code = _FCT_ANON_ARGS[0];
msg = _FCT_ANON_ARGS[1];
error = get_ssh_error();
if(error) error = ': ' + error;
ssh_close_connection();
exit(code, msg + error + '.');
}
#
# MAIN
#
# Get SSH port
port = get_service(svc:'ssh', exit_on_fail:TRUE, default:22);
# Get SSH banner
banner = get_kb_item_or_exit("SSH/banner/"+port);
# Make sure the SSH server uses libssh
if('libssh' >!< banner)
exit(0, 'The service listening on port ' + port + ' does not appear to use libssh.');
# SSH network functions use _ssh_socket
_ssh_socket = open_sock_tcp(port);
if(! _ssh_socket)
audit(AUDIT_SOCK_FAIL, port);
# Init some global variables
init();
# Exchange protocol version identification strings with the server.
server_version = ssh_exchange_identification();
if (!server_version)
{
ssh_errexit(1,'Failed to exchange SSH identification string.');
}
# Vulnerable function ssh_packet_kexinit() seems to be invoked
# only when SSH 2 is in use.
if (_ssh_protocol != 2)
ssh_errexit(1, 'This plugin does not support SSH protocol version ' + _ssh_protocol + '.');
### Algorithms Setup ###
#
# libssh as of 0.6.4 is known to support one of the algorithms in each
# algorithm group.
#
#
key_exchange_algo = "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1";
server_host_key_algo = "ssh-rsa,ssh-dss";
enc_alg_client_to_server = "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,blowfish,3des-cbc";
mac_alg_client_to_server = "hmac-sha1";
cmp_alg_client_to_server = "none,zlib,[email protected]";
# We support the same algorithms in both directions.
enc_alg_server_to_client = enc_alg_client_to_server;
mac_alg_server_to_client = mac_alg_client_to_server;
cmp_alg_server_to_client = cmp_alg_client_to_server;
### Key Exchange Message from Server ###
# Read server SSH_MSG_KEXINIT
res = sshlib::_compat_session.sshrecv(length:2000);
if (isnull(res) || ord(res[0]) != SSH_MSG_KEXINIT)
{
ssh_errexit(1,"Failed to receive server SSH_MSG_KEXINIT.");
}
# Handle 'kex_algorithms' field of SSH_MSG_KEXINIT.
kex_algo_supported = FALSE;
var kex_handler = new("sshlib::kex_handler", sshlib::_compat_session);
var server_algos = kex_handler.kex_pkt_parse_namelists(sshlib::_compat_session.last_packet);
foreach var kex_algo (split(key_exchange_algo, sep:',', keep:FALSE))
{
foreach var server_kex(split(server_algos["kex_algorithms"], sep:',', keep:FALSE))
{
if(kex_algo == server_kex)
{
kex_algo_supported = TRUE;
break;
}
}
if(kex_algo_supported)
break;
}
if (!kex_algo_supported)
{
server_kex_algo_len = ntol(buffer:res, begin:17);
server_kex_algo = substr(res, 21, 21 + server_kex_algo_len - 1);
ssh_errexit(1, "Unsupported key exchange algorithm : " + server_kex_algo);
}
# Handle 'server_host_key_algorithms' field of SSH_MSG_KEXINIT.
var match = preg(string:server_algos["server_host_key_algorithms"], pattern:"ssh-rsa");
if (!match)
{
match = preg(string:server_algos["server_host_key_algorithms"], pattern:"ssh-dss");
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support DSA or RSA as a host key algorithm." );
}
}
# Look for an encryption algorithm shared by the client and the
# server for client-to-server communication.
algs = split(enc_alg_client_to_server, sep:",", keep:FALSE);
match = FALSE;
foreach var alg (algs)
{
match = preg(string:server_algos["encryption_algorithms_client_to_server"], pattern:alg);
if (match)
{
_crypto_algo = alg;
break;
}
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following encryption algorithms for client-to-server communication : " + enc_alg_client_to_server);
}
# Look for an encryption algorithm shared by the client and the
# server for server-to-client communication.
algs = split(enc_alg_server_to_client, sep:",", keep:FALSE);
match = FALSE;
foreach alg (algs)
{
match = preg(string:server_algos["encryption_algorithms_server_to_client"], pattern:alg);
if (match)
break;
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following encryption algorithms for server-to-client communication : " + enc_alg_server_to_client);
}
# Look for a MAC algorithm shared by the client and the server for
# client-to-server communication.
algs = split(mac_alg_client_to_server, sep:",", keep:FALSE);
match = FALSE;
foreach alg (algs)
{
alg_regex = alg + "($|,)";
match = preg(string:server_algos["mac_algorithms_client_to_server"], pattern:alg_regex);
if (match)
break;
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following MAC algorithms for client-to-server communication : " + mac_alg_client_to_server);
}
# Look for a MAC algorithm shared by the client and the server for
# server-to-client communication.
algs = split(mac_alg_server_to_client, sep:",", keep:FALSE);
match = FALSE;
foreach alg (algs)
{
match = preg(string:server_algos["mac_algorithms_server_to_client"], pattern:alg);
if (match)
break;
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following MAC algorithms for server-to-client communication : " + mac_alg_server_to_client);
}
# Look for a compression algorithm shared by the client and the server for
# client-to-server communication.
algs = split(cmp_alg_client_to_server, sep:",", keep:FALSE);
match = FALSE;
foreach alg (algs)
{
match = preg(string:server_algos["compression_algorithms_client_to_server"], pattern:alg);
if (match)
break;
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following compression algorithms for client-to-server communication : " + cmp_alg_client_to_server);
}
# Look for a compression algorithm shared by the client and the server for
# server-to-client communication.
algs = split(cmp_alg_server_to_client, sep:",", keep:FALSE);
match = FALSE;
foreach alg (algs)
{
match = preg(string:server_algos["compression_algorithms_server_to_client"], pattern:alg);
if (match)
break;
}
if (!match)
{
ssh_errexit(1, "The remote SSH server does not support any of the following compression algorithms for server-to-client communication : " + cmp_alg_server_to_client);
}
### Key Exchange Message from Client ###
ccookie = "";
for (i = 0; i < 16; i++)
ccookie = ccookie + raw_int8(rand() % 256);
# Create and send a malformed client SSH_MSG_KEXINIT.
cinit =
ccookie + # cookie
putstring(key_exchange_algo) + # kex_algorithms
putstring(server_host_key_algo) + # server_host_key_algorithms
putstring(enc_alg_client_to_server) + # encryption_algorithms_client_to_server
putstring(enc_alg_server_to_client) + # encryption_algorithms_server_to_client
putstring(mac_alg_client_to_server) + # mac_algorithms_client_to_server
putstring(mac_alg_server_to_client) + # mac_algorithms_server_to_client
putstring(cmp_alg_client_to_server) + # compression_algorithms_client_to_server
putstring(cmp_alg_server_to_client) + # compression_algorithms_server_to_client
raw_int32(0) + # languages_client_to_server
#
# !!!!! INVALID length for languages_server_to_client !!!!!
#
raw_int32(0x7fffffff) + # languages_server_to_client
crap(data:raw_string(0x00), length:5); # payload
sshlib::_compat_session.sshsend(data:cinit, code:sshlib::PROTO_SSH_MSG_KEXINIT);
# Send SSH_MSG_KEXDH_INIT
if (kex_algo == 'diffie-hellman-group1-sha1')
{
# RFC2409 section 6.2 (Second Oakley Group)
# As RFC4253 notes in section 8.1, even though the method has the phrase "group1",
# it actually uses Oakley Group 2
p = raw_string(
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
);
g = raw_int8(2);
}
else if (kex_algo == 'diffie-hellman-group14-sha1')
{
# RFC3526 section 3 (2048-bit MODP Group)
p = raw_string(
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
);
g = raw_int8(2);
}
# Init crypto data
# Some global variables are used by dh_gen_key()
init_crypto_data ();
# generate public and private keys
ret = dh_gen_key(p:p, g:g);
if (ret != 0)
{
ssh_errexit(1, "Failed to generate DH keys.");
}
payload = sshlib::mk_ssh_mpint(dh_pub);
sshlib::_compat_session.sshsend(data:payload, code:sshlib::PROTO_SSH_MSG_KEXDH_INIT);
# Try to read SSH_MSG_KEXDH_REPLY
res = sshlib::_compat_session.sshrecv(length:2000);
ssh_close_connection();
# Non-affected SSH server will NOT send an SSH_MSG_KEXDH_REPLY
if (isnull(res))
{
audit(AUDIT_LISTEN_NOT_VULN, 'SSH', port);
}
# Vulnerable SSH server will send an SSH_MSG_KEXDH_REPLY
else if (ord(res[5]) == SSH_MSG_KEXDH_REPLY)
{
security_warning(port:port);
}
else
{
audit(AUDIT_RESP_BAD, port, 'an SSH_MSG_KEXDH_INIT');
}