1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-08-05 20:55:47 +03:00

1.8 Security fixes (#314)

* fixed possible integer overflow in packet_length

CVE https://www.libssh2.org/CVE-2019-3861.html

* fixed possible interger overflow with userauth_keyboard_interactive

CVE https://www.libssh2.org/CVE-2019-3856.html

* fixed possible out zero byte/incorrect bounds allocation

CVE https://www.libssh2.org/CVE-2019-3857.html

* bounds checks for response packets

* fixed integer overflow in userauth_keyboard_interactive

CVE https://www.libssh2.org/CVE-2019-3863.html

* 1.8.1 release notes
This commit is contained in:
Will Cosgrove
2019-03-14 13:14:28 -07:00
committed by GitHub
parent 30e9c1347e
commit c286e4d82f
8 changed files with 148 additions and 39 deletions

View File

@@ -1,31 +1,29 @@
libssh2 1.8.0
This release includes the following changes:
o added a basic dockerised test suite
o crypto: add support for the mbedTLS backend
libssh2 1.8.1
This release includes the following bugfixes:
o libgcrypt: fixed a NULL pointer dereference on OOM
o VMS: can't use %zd for off_t format
o VMS: update vms/libssh2_config.h
o windows: link with crypt32.lib
o libssh2_channel_open: speeling error fixed in channel error message
o msvc: fixed 14 compilation warnings
o tests: HAVE_NETINET_IN_H was not defined correctly
o openssl: add OpenSSL 1.1.0 compatibility
o cmake: Add CLEAR_MEMORY option, analogously to that for autoconf
o configure: make the --with-* options override the OpenSSL default
o libssh2_wait_socket: set err_msg on errors
o libssh2_wait_socket: Fix comparison with api_timeout to use milliseconds
o fixed possible integer overflow when reading a specially crafted packet
(https://www.libssh2.org/CVE-2019-3855.html)
o fixed possible integer overflow in userauth_keyboard_interactive with a
number of extremely long prompt strings
(https://www.libssh2.org/CVE-2019-3863.html)
o fixed possible integer overflow if the server sent an extremely large number
of keyboard prompts (https://www.libssh2.org/CVE-2019-3856.html)
o fixed possible out of bounds read when processing a specially crafted packet
(https://www.libssh2.org/CVE-2019-3861.html)
o fixed possible integer overflow when receiving a specially crafted exit
signal message channel packet (https://www.libssh2.org/CVE-2019-3857.html)
o fixed possible out of bounds read when receiving a specially crafted exit
status message channel packet (https://www.libssh2.org/CVE-2019-3862.html)
o fixed possible zero byte allocation when reading a specially crafted SFTP
packet (https://www.libssh2.org/CVE-2019-3858.html)
o fixed possible out of bounds reads when processing specially crafted SFTP
packets (https://www.libssh2.org/CVE-2019-3860.html)
o fixed possible out of bounds reads in _libssh2_packet_require(v)
(https://www.libssh2.org/CVE-2019-3859.html)
This release would not have looked like this without help, code, reports and
advice from friends like these:
Alexander Lamaison, Antenore Gatta, Brad Harder, Charles Collicutt,
Craig A. Berry, Dan Fandrich, Daniel Stenberg, Kamil Dudka, Keno Fischer,
Taylor Holberton, Viktor Szakats, Will Cosgrove, Zenju
(12 contributors)
Thanks! (and sorry if I forgot to mention someone)
Chris Coulson, Michael Buckley, Will Cosgrove, Daniel Stenberg
(4 contributors)

View File

@@ -145,6 +145,18 @@ typedef int libssh2_socket_t;
#define LIBSSH2_INVALID_SOCKET -1
#endif /* WIN32 */
#ifndef SIZE_MAX
#if _WIN64
#define SIZE_MAX 0xFFFFFFFFFFFFFFFF
#else
#define SIZE_MAX 0xFFFFFFFF
#endif
#endif
#ifndef UINT_MAX
#define UINT_MAX 0xFFFFFFFF
#endif
/*
* Determine whether there is small or large file support on windows.
*/

View File

@@ -238,7 +238,20 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
goto channel_error;
}
if(session->open_data_len < 1) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
goto channel_error;
}
if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
if(session->open_data_len < 17) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
goto channel_error;
}
session->open_channel->remote.id =
_libssh2_ntohu32(session->open_data + 5);
session->open_channel->local.window_size =
@@ -518,7 +531,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
return NULL;
} else if (rc) {
} else if (rc || data_len < 1) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
session->fwdLstn_state = libssh2_NB_state_idle;
return NULL;
@@ -855,6 +868,11 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
channel->setenv_state = libssh2_NB_state_idle;
return rc;
}
else if(data_len < 1) {
channel->setenv_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
}
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
LIBSSH2_FREE(session, data);
@@ -971,7 +989,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
&channel->reqPTY_packet_requirev_state);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
} else if (rc || data_len < 1) {
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Failed to require the PTY package");
@@ -1197,7 +1215,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
&channel->reqX11_packet_requirev_state);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
} else if (rc || data_len < 1) {
channel->reqX11_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"waiting for x11-req response packet");
@@ -1324,7 +1342,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
&channel->process_packet_requirev_state);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
} else if (rc || data_len < 1) {
channel->process_state = libssh2_NB_state_end;
return _libssh2_error(session, rc,
"Failed waiting for channel success");

View File

@@ -228,11 +228,23 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
/* Parse KEXDH_REPLY */
if(exchange_state->s_packet_len < 5) {
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet length");
goto clean_exit;
}
exchange_state->s = exchange_state->s_packet + 1;
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
exchange_state->s += 4;
if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Host key length out of bounds");
goto clean_exit;
}
if (session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
@@ -848,11 +860,23 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
}
/* Parse KEXDH_REPLY */
if(exchange_state->s_packet_len < 5) {
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet length");
goto clean_exit;
}
exchange_state->s = exchange_state->s_packet + 1;
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
exchange_state->s += 4;
if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Host key length out of bounds");
goto clean_exit;
}
if (session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);

View File

@@ -815,8 +815,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* set signal name (without SIG prefix) */
uint32_t namelen =
_libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
if(namelen <= UINT_MAX - 1) {
channelp->exit_signal =
LIBSSH2_ALLOC(session, namelen + 1);
}
else {
channelp->exit_signal = NULL;
}
if (!channelp->exit_signal)
rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"memory for signal name");

View File

@@ -765,6 +765,11 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
if (rc)
return rc;
if(session->startup_data_len < 5) {
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet length");
}
session->startup_service_length =
_libssh2_ntohu32(session->startup_data + 1);

View File

@@ -438,6 +438,12 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
return LIBSSH2_ERROR_DECRYPT;
p->padding_length = block[4];
if(p->packet_length < 1) {
return LIBSSH2_ERROR_DECRYPT;
}
else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
/* total_num is the number of bytes following the initial
(5 bytes) packet length and padding length fields */

View File

@@ -107,7 +107,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
if (rc) {
if (rc || (session->userauth_list_data_len < 1)) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-none request");
session->userauth_list_state = libssh2_NB_state_idle;
@@ -143,8 +143,20 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
return NULL;
}
methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
if(session->userauth_list_data_len < 5) {
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
return NULL;
}
methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
if(methods_len >= session->userauth_list_data_len - 5) {
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Unexpected userauth list size");
return NULL;
}
/* Do note that the memory areas overlap! */
memmove(session->userauth_list_data, session->userauth_list_data + 5,
methods_len);
@@ -285,6 +297,11 @@ userauth_password(LIBSSH2_SESSION *session,
return _libssh2_error(session, rc,
"Waiting for password response");
}
else if(session->userauth_pswd_data_len < 1) {
session->userauth_pswd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
}
if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
@@ -312,6 +329,12 @@ userauth_password(LIBSSH2_SESSION *session,
session->userauth_pswd_state = libssh2_NB_state_sent1;
}
if(session->userauth_pswd_data_len < 1) {
session->userauth_pswd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
}
if ((session->userauth_pswd_data[0] ==
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
|| (session->userauth_pswd_data0 ==
@@ -976,7 +999,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
}
session->userauth_host_state = libssh2_NB_state_idle;
if (rc) {
if (rc || data_len < 1) {
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Auth failed");
}
@@ -1149,7 +1172,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN)
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
else if (rc) {
else if (rc || (session->userauth_pblc_data_len < 1)) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_method);
@@ -1332,7 +1355,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
} else if (rc) {
} else if (rc || session->userauth_pblc_data_len < 1) {
session->userauth_pblc_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Waiting for publickey USERAUTH response");
@@ -1654,7 +1677,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block");
} else if (rc) {
} else if (rc || session->userauth_kybd_data_len < 1) {
session->userauth_kybd_state = libssh2_NB_state_idle;
return _libssh2_error(session,
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
@@ -1734,6 +1757,13 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
/* int num-prompts */
session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
s += 4;
if(session->userauth_kybd_num_prompts &&
session->userauth_kybd_num_prompts > 100) {
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Too many replies for "
"keyboard-interactive prompts");
goto cleanup;
}
if(session->userauth_kybd_num_prompts) {
session->userauth_kybd_prompts =
@@ -1801,9 +1831,18 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
/* string response[1] (ISO-10646 UTF-8) */
if(session->userauth_kybd_responses[i].length <=
(SIZE_MAX - 4 - session->userauth_kybd_packet_len) ) {
session->userauth_kybd_packet_len +=
4 + session->userauth_kybd_responses[i].length;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for keyboard-"
"interactive response packet");
goto cleanup;
}
}
/* A new userauth_kybd_data area is to be allocated, free the
former one. */