Skip to content

Commit

Permalink
Add flag to set cipher suite preferences on a TLS session (#1020)
Browse files Browse the repository at this point in the history
* Add the definitions to set preferences which can't be set via the priority string

* Extend open_stream_conenction_ext() to receive the new bit flag variable for setting cipher suite preferences on a TLS session

* Forward the flag variable to set the TLS preferences or use NO_PRIORITY_FLAGS, as required for each case.

* Catch the GNUTLS_E_DH_PRIME_UNACCEPTABLE error during
the handshake and return -2 to allow caller functions to handle this especial case.

* Handle the case GNUTLS_E_DH_PRIME_UNACCEPTABLE error. Retry with a lower prime bits number. For this, use the new bit flag variable.

What:
Currently, when the scanner opens a TLS session, cipher suite preferences can be set only via the priority string. Other preferences can be set via functions. This PR extends the open_stream_connection_ext() function to accept a flag which allows to set other preferences (e.g. the number of bits, for use in a Diffie-Hellman key exchange)

Jira: SC-441

Why:
nasl_builtin_find_service.c fails to detect SSL/TLS service because, in this particular case, the server sends a prime of 512 bits, and the client limit is 1008 (set with the NORMAL priority). This PR handles this error and set a new minimum (128) and retries to open the TLS connection.

How:
sudo openvas-nasl -X -B -d -i $PLUGINSPATH -t TARGET find_service.nasl --kb="Ports/tcp/443=1" --debug-tls=9

[19893] (1) FFDHE groups advertised, but server didn't support it; falling back to server's choice
[19893] (2) Received a prime of 512 bits, limit is 1008
lib  misc-Message: 03:36:31.165: replace key FindService/CnxTime1000/443 -> 45
lib  misc-Message: 03:36:31.166: set key Transports/TCP/443 -> 1
lib  misc-Message: 03:36:51.279: set key Services/unknown -> 443
With the PR:

[19263] (1) FFDHE groups advertised, but server didn't support it; falling back to server's choice
[19263] (2) Received a prime of 512 bits, limit is 1008
lib  misc-Message: 03:19:20.218: [19263] gnutls_handshake: The Diffie-Hellman prime sent by the server is not acceptable (not long enough).
[19263] (1) Note that the security level of the Diffie-Hellman key exchange has been lowered to 128 bits and this may allow decryption of the session data
lib  misc-Message: 03:37:38.525: replace key FindService/RwTime1000/443 -> 101
lib  misc-Message: 03:37:38.525: replace key FindService/tcp/443/get_http -> HTTP/1.0 200 OK
Date: Sat, 01 Jan 2011 00:00:53 GMT
Server: Embedded HTTP Server.
Connection: close
Content-Length: 107
Last-Modified: Fri, 28 Feb 2014 14:53:02 GMT
Content-Type: text/html

<HTML><HEAD><meta http-equiv="refresh" content="0; URL=/scgi-bin/platform.cgi"></HEAD><BODY></BODY></HTML>

lib  misc-Message: 03:37:38.525: set key Services/www -> 443
lib  misc-Message: 03:37:38.525: replace key Known/tcp/443 -> www
lib  misc-Message: 03:37:38.525: replace key www/banner/443 -> HTTP/1.0 200 OK
Date: Sat, 01 Jan 2011 00:00:53 GMT
Server: Embedded HTTP Server.
Connection: close
Content-Length: 107
Last-Modified: Fri, 28 Feb 2014 14:53:02 GMT
Content-Type: text/html

<HTML><HEAD><meta http-equiv="refresh" content="0; URL=/scgi-bin/platform.cgi"></HEAD><BODY></BODY></HTML>

(cherry picked from commit 8186bb6)
  • Loading branch information
jjnicola authored and mergify-bot committed Feb 8, 2022
1 parent 5c98cb2 commit 1a10675
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 19 deletions.
69 changes: 54 additions & 15 deletions misc/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ ovas_get_tlssession_from_connection (int fd)
*/
static int
set_gnutls_protocol (gnutls_session_t session, openvas_encaps_t encaps,
const char *priority)
const char *priority, unsigned int flags)
{
const char *priorities;
const char *errloc;
Expand Down Expand Up @@ -445,6 +445,11 @@ set_gnutls_protocol (gnutls_session_t session, openvas_encaps_t encaps,
return -1;
}

/* Set extra priorities from flags.
Only for encaps == OPENVAS_ENCAPS_TLScustom. */
if (encaps == OPENVAS_ENCAPS_TLScustom && flags & INSECURE_DH_PRIME_BITS)
gnutls_dh_set_prime_bits (session, 128);

return 0;
}

Expand Down Expand Up @@ -560,10 +565,28 @@ is_ip_address (const char *str)
return inet_pton (AF_INET6, str, &(sa6.sin6_addr)) == 1;
}

/**
* @brief Open an TLS/SSL connection.
*
* @param fp File structure for a the openvas connection
* @param cert The certificate.
* @param key The key
* @param passwd The password
* @param cafile The CA file
* @param hostname Targets hostname
* @param flags Extra options which can not be set via the priority string
* Supported flags are:
* - NO_PRIORITY_FLAGS
* - INSECURE_DH_PRIME_BITS
*
* @return 1 on success. -1 on general error or timeout. -2 if DH prime bits on
* server side are lower than minimum allowed.
*
*/
static int
open_SSL_connection (openvas_connection *fp, const char *cert, const char *key,
const char *passwd, const char *cafile,
const char *hostname)
const char *hostname, unsigned int flags)
{
int ret, err, d;
time_t tictac;
Expand All @@ -584,7 +607,8 @@ open_SSL_connection (openvas_connection *fp, const char *cert, const char *key,
* OPENVAS_ENCAPS_SSLv2, so it should never end up calling
* open_SSL_connection with OPENVAS_ENCAPS_SSLv2.
*/
if (set_gnutls_protocol (fp->tls_session, fp->transport, fp->priority) < 0)
if (set_gnutls_protocol (fp->tls_session, fp->transport, fp->priority, flags)
< 0)
return -1;

if (hostname && !is_ip_address (hostname))
Expand Down Expand Up @@ -636,8 +660,17 @@ open_SSL_connection (openvas_connection *fp, const char *cert, const char *key,
if (err == 0)
return 1;

if (err != GNUTLS_E_INTERRUPTED && err != GNUTLS_E_AGAIN
&& err != GNUTLS_E_WARNING_ALERT_RECEIVED)
/* Set min number of bits for Deffie-Hellman prime
to force a connection to a legacy server. */
if (err == GNUTLS_E_DH_PRIME_UNACCEPTABLE
&& fp->transport == OPENVAS_ENCAPS_TLScustom)
{
g_message ("[%d] gnutls_handshake: %s", getpid (),
gnutls_strerror (err));
return -2;
}
else if (err != GNUTLS_E_INTERRUPTED && err != GNUTLS_E_AGAIN
&& err != GNUTLS_E_WARNING_ALERT_RECEIVED)
{
g_debug ("[%d] gnutls_handshake: %s", getpid (),
gnutls_strerror (err));
Expand Down Expand Up @@ -811,7 +844,9 @@ socket_negotiate_ssl (int fd, openvas_encaps_t transport,

fp->transport = transport;
fp->priority = NULL;
if (open_SSL_connection (fp, cert, key, passwd, cafile, hostname) <= 0)
if (open_SSL_connection (fp, cert, key, passwd, cafile, hostname,
NO_PRIORITY_FLAGS)
<= 0)
{
g_free (hostname);
g_free (cert);
Expand Down Expand Up @@ -1002,14 +1037,16 @@ socket_get_ssl_ciphersuite (int fd)
}

/* Extended version of open_stream_connection to allow passing a
priority string.
priority string and a bit flag variable for setting extra options
which can't be set via the priority string.
ABI_BREAK_NOTE: Merge this with open_stream_connection. */
int
open_stream_connection_ext (struct script_infos *args, unsigned int port,
int transport, int timeout, const char *priority)
int transport, int timeout, const char *priority,
int flags)
{
int fd;
int fd, ret;
openvas_connection *fp;
char *cert = NULL;
char *key = NULL;
Expand All @@ -1032,6 +1069,7 @@ open_stream_connection_ext (struct script_infos *args, unsigned int port,
if (timeout == -2)
timeout = TIMEOUT;

ret = -1;
switch (transport)
{
case OPENVAS_ENCAPS_IP:
Expand All @@ -1053,13 +1091,13 @@ open_stream_connection_ext (struct script_infos *args, unsigned int port,
errno = EINVAL;

g_free (hostname_aux);
return -1;
return ret;
}

if ((fd = get_connection_fd ()) < 0)
{
g_free (hostname_aux);
return -1;
return ret;
}
fp = OVAS_CONNECTION_FROM_FD (fd);

Expand All @@ -1080,7 +1118,6 @@ open_stream_connection_ext (struct script_infos *args, unsigned int port,
kb_t kb = plug_get_kb (args);
switch (transport)
{
int ret;
char buf[1024];

case OPENVAS_ENCAPS_IP:
Expand All @@ -1106,7 +1143,8 @@ open_stream_connection_ext (struct script_infos *args, unsigned int port,
if (kb_item_get_int (kb, buf) <= 0)
hostname = hostname_aux;

ret = open_SSL_connection (fp, cert, key, passwd, cafile, hostname);
ret =
open_SSL_connection (fp, cert, key, passwd, cafile, hostname, flags);
g_free (cert);
g_free (key);
g_free (passwd);
Expand All @@ -1122,15 +1160,16 @@ open_stream_connection_ext (struct script_infos *args, unsigned int port,

failed:
release_connection_fd (fd, 0);
return -1;
return ret;
}

int
open_stream_connection (struct script_infos *args, unsigned int port,
int transport, int timeout)
{
return open_stream_connection_ext (args, port, transport, timeout,
"NORMAL:+ARCFOUR-128:%COMPAT");
"NORMAL:+ARCFOUR-128:%COMPAT",
NO_PRIORITY_FLAGS);
}

/* Same as open_stream_auto_encaps but allows to force auto detection
Expand Down
7 changes: 6 additions & 1 deletion misc/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ typedef enum openvas_encaps
#define IS_ENCAPS_SSL(x) \
((x) >= OPENVAS_ENCAPS_SSLv23 && (x) <= OPENVAS_ENCAPS_TLScustom)

/* Define FLAGS for setting other priorities in
open_stream_connection_ext */
#define NO_PRIORITY_FLAGS 0
#define INSECURE_DH_PRIME_BITS (1 << 0) // 1

/* Plugin specific network functions */
int
open_sock_tcp (struct script_infos *, unsigned int, int);
Expand Down Expand Up @@ -84,7 +89,7 @@ open_stream_connection (struct script_infos *, unsigned int, int, int);

int
open_stream_connection_ext (struct script_infos *, unsigned int, int, int,
const char *);
const char *, int);

int
open_stream_auto_encaps_ext (struct script_infos *, unsigned int port,
Expand Down
11 changes: 10 additions & 1 deletion nasl/nasl_builtin_find_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -1608,7 +1608,16 @@ plugin_do_run (struct script_infos *desc, GSList *h, int test_ssl)
trp = OPENVAS_ENCAPS_IP;
gettimeofday (&tv1, NULL);
cnx = open_stream_connection (desc, port, trp, cnx_timeout);
if (cnx < 0 && test_ssl)
if (cnx == -2 && test_ssl)
{
unsigned int flags = INSECURE_DH_PRIME_BITS;

gettimeofday (&tv1, NULL);
cnx = open_stream_connection_ext (
desc, port, trp, cnx_timeout, "NORMAL:+ARCFOUR-128:%COMPAT",
flags);
}
else if (cnx < 0 && test_ssl)
{
trp = OPENVAS_ENCAPS_IP;
gettimeofday (&tv1, NULL);
Expand Down
4 changes: 2 additions & 2 deletions nasl/nasl_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,8 @@ nasl_open_sock_tcp_bufsz (lex_ctxt *lexic, int bufsz)
else if (transport == 0)
soc = open_stream_auto_encaps_ext (script_infos, port, to, 1);
else
soc =
open_stream_connection_ext (script_infos, port, transport, to, priority);
soc = open_stream_connection_ext (script_infos, port, transport, to,
priority, NO_PRIORITY_FLAGS);
if (bufsz > 0 && soc >= 0)
{
if (stream_set_buffer (soc, bufsz) < 0)
Expand Down

0 comments on commit 1a10675

Please sign in to comment.