Lucene search

K
nessusThis script is Copyright (C) 2015-2020 and is owned by Tenable, Inc. or an Affiliate thereof.POLARSSL_CVE-2014-8627.NASL
HistoryJan 07, 2015 - 12:00 a.m.

PolarSSL Weak Signature Algorithm Negotiation

2015-01-0700:00:00
This script is Copyright (C) 2015-2020 and is owned by Tenable, Inc. or an Affiliate thereof.
www.tenable.com
17

PolarSSL 1.3.8 does not properly negotiate the signature algorithm to use, allowing remote attackers to conduct downgrade attacks.

This plugin sends a list of hash algorithms (SHA512, SHA384, SHA256, SHA224, SHA1, and MD5) in descending order, and checks if the server selects MD5.

#TRUSTED a63b12c204006332a94c61c2224e273777ee6b31edf738a967c8ccb44ce08fdf64628ba81906666bdc4985ad20eaf27c85d610a43114d978ff2f316582f0e14ccb30f9be94bcaf7bbccead8d07b8482f1dfe0c4389f2784e91b0d87e3da8012b930a31077e35a81d9658b06f62ea093d3ecfab127129c1ab23754a3e7d158dc4ed590e4205185fc30c58dbedf6da51fef8d3849ba475b4f31981ac0fe85370da45c6184ee0e64fbb9fdf736a8e85885b05b124aacd864dec7da5b0a6c4fa8c31006ea8a0a801b3b85b514dee71ce19824ec583f49d4842c091951849486dd745c9dcd4662072d0797587b7cd3f1506dafbc02b7113247ce831212d2f1f917ca8a1f6aa63f56e759bd5b3ade94c5611b027ce1394e2b1512e6d1ac6735b177eb6215531db9076b585c45899ea6b62ae7da1fe21db859c751d7f797464ae42752d4f1bef01af87ed1ffdc979f487fa9fd6c7c48bfdc76ccf24fa0126b2964e3e8a0b8135b62804de128954f500b645f16e61f986c55914d7913a65dd27a3370304fe75e4d4b73b7456e20f982bea01a9b08546f3ff3ce982ae457202f99e8aa74e27fda9da695000c51c4ecab9ee7357eb60c05ff4f84abf11f40c45a1dcfe3f5c6c245c9f1066aa47334432756373a4a08278c4eb2f8177f079d24fb48dd5c2f56b8a60f9b3f552b5b26f5b003b3ba43ba24fc280526004d5deabb30cf22ac07f
#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(80399);
  script_version("1.12");
  script_set_attribute(attribute:"plugin_modification_date", value:"2020/06/12");

  script_cve_id("CVE-2014-8627");
  script_bugtraq_id(70902);

  script_name(english:"PolarSSL Weak Signature Algorithm Negotiation");
  script_summary(english:"Attempts to negotiate a weak signature algorithm.");

  script_set_attribute(attribute:"synopsis", value:
"The remote TLS server negotiates a weaker signature algorithm.");
  script_set_attribute(attribute:"description", value:
"PolarSSL 1.3.8 does not properly negotiate the signature algorithm to
use, allowing remote attackers to conduct downgrade attacks.

This plugin sends a list of hash algorithms (SHA512, SHA384, SHA256,
SHA224, SHA1, and MD5) in descending order, and checks if the server
selects MD5.");
  script_set_attribute(attribute:"see_also", value:"https://tls.mbed.org/tech-updates/releases/polarssl-1.3.9-released");
  script_set_attribute(attribute:"see_also", value:"https://bugzilla.redhat.com/show_bug.cgi?id=1159845");
  script_set_attribute(attribute:"solution", value:
"Use a PolarSSL version other than 1.3.8.");
  script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:N/I:P/A:N");
  script_set_cvss_temporal_vector("CVSS2#E:U/RL:OF/RC:C");
  script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N");
  script_set_cvss3_temporal_vector("CVSS:3.0/E:U/RL:O/RC:C");
  script_set_attribute(attribute:"cvss_score_source", value:"CVE-2014-8627");

  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/11/22");
  script_set_attribute(attribute:"patch_publication_date", value:"2014/11/22");
  script_set_attribute(attribute:"plugin_publication_date", value:"2015/01/07");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:polarssl:polarssl");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"General");

  script_copyright(english:"This script is Copyright (C) 2015-2020 and is owned by Tenable, Inc. or an Affiliate thereof.");

  script_dependencies("ssl_supported_versions.nasl");
  script_require_keys("SSL/Supported");

  exit(0);
}

include("byte_func.inc");
include("ftp_func.inc");
include("global_settings.inc");
include("kerberos_func.inc");
include("ldap_func.inc");
include("misc_func.inc");
include("nntp_func.inc");
include("smtp_func.inc");
include("ssl_funcs.inc");
include("telnet2_func.inc");
include("audit.inc");


##
# Negotiate hash algorithm part of SignatureAndHashAlgorithm
#
# @param port TLS server port
# @param sighash client supported list of SignatureAndHashAlgorithms (encoded)
# @remark script exits on function failure
##
function get_hash_alg(port, sighash)
{
  local_var ec_list, exts, exts_len, i, soc, version;
  local_var cipher, cipher_desc, cipherspec, cspeclen, chello;
  local_var data, hellodone, name, rec, shello, skex;
  local_var alert;

  # Create a socket for SSL handshake
  soc = open_sock_ssl(port);
  if ( ! soc ) exit(1, "Failed to open an SSL socket on port "+port+".");

  # We need to include EC extensions because it seems PolarSSL server
  # will abort the handshake if a EC-based cipher suite is negotiated
  # but a EC extension is not offered by the client.
  #
  # PolarSSL as of 1.3.9 does not seem to support
  # explicit_prime and explicit_char2 curve types
  ec_list = make_list(
                        1, 2, 3, 4, 5, 6, 7, 8,
                        9, 10, 11, 12, 13, 14, 15, 16,
                        17, 18, 19, 20, 21, 22, 23, 24,
                        25, 26, 27, 28
                      );

  data = ssl_vldata_put(data:sighash, len:2);
  exts = tls_ext(type:13, data:data) + tls_ext_ec(ec_list) + tls_ext_ec_pt_fmt();
  exts_len  = mkword(strlen(exts));

  # Signature algorithms extension is only available
  # in TLS version 1.2
  version = TLS_12;

  # Use ciphersuites that do ephemeral key exchange.
  # This is to force the server to send a ServerKeyExchange
  # in which DH/EC parameters are signed with negotiated
  # SignatureAndHashAlgorithms.
  cipherspec = NULL;
  foreach cipher (keys(ciphers))
  {
    if(strlen(ciphers[cipher]) == 2 && 'DHE' >< cipher)
    {
      cipherspec +=  ciphers[cipher];
    }
  }
  cspeclen = mkword(strlen(cipherspec));

  # Send ClientHello
  chello = client_hello(v2hello:FALSE, version: mkword(version),
                        extensions:exts,extensionslen:exts_len,
                        cipherspec : cipherspec,
                        cspeclen   : cspeclen
                        );
  send(socket:soc, data: chello);

  hellodone = shello = skex = NULL;
  i = 0;
  while (! hellodone)
  {
    # Receive a record from the server.
    data = recv_ssl(socket:soc, timeout:30);
    if (isnull(data)) break;

    # ServerHello
    if(! shello)
    {
      shello = ssl_find(
        blob:data,
        'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
        'handshake_type', SSL3_HANDSHAKE_TYPE_SERVER_HELLO
      );

      if (shello)
      {
        # Check handshake version returned by the server
        # signtuare_alorithms extension first supported in TLS 1.2
        if (shello['handshake_version'] != TLS_12)
        {
            close(soc);
            exit(0, 'The service listening on port ' + port + ' does not support TLS 1.2.');
        }
        name = cipher_name(id:shello['cipher_spec']);
        cipher_desc = ciphers_desc[name];
        if(! cipher_desc)
        {
          close(soc);
          exit(1, 'Failed to get info about the negotiated cipher suite.');
        }
      }
      else
      {
        alert = ssl_find(
          blob:data,
          'content_type', SSL3_CONTENT_TYPE_ALERT
        );
        if(alert)
        {
          close(soc);
          exit(1, 'Alert received from service listening on port '+ port +': level '+ alert['level'] + ', description code ' + alert['description'] + '.');
        }
      }
    }

    # Server Key Exchange.
    if(! skex)
    {
      rec = ssl_find(
        blob:data,
        'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
        'handshake_type', SSL3_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE
      );

      if (rec['data'])
      {
        skex = ssl_parse_srv_kex(blob:rec['data'], cipher:cipher_desc, version: version);
        if(!skex)
        {
          close(soc);
          exit(1, 'Failed to parse ServerKeyExchange received from service listening on port '+ port +'.');
        }
      }
    }

    # Server Hello Done.
    if(! hellodone)
    {
      hellodone = ssl_find(
        blob:data,
        'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
        'handshake_type', SSL3_HANDSHAKE_TYPE_SERVER_HELLO_DONE
      );

      if(hellodone) break;
    }

    # ServerHelloDone not seen after a higher number of TLS records
    # Something is very wrong
    if(i++ > 16)  break;
  }

  close(soc);
  # Make sure we got a ServerHelloDone
  if(! hellodone)
  {
    exit(1, 'ServerHelloDone not received from service listening on port '+ port +'.');
  }

  # Make sure we got a ServerKeyExchange
  # Server uses the negotiated SignatureAndHashAlgorithms
  # to sign the DH parameters
  if(! skex)
  {
    exit(1, 'ServerKeyExchange not received from service listening on port '+ port +'.');
  }

  if(isnull(skex['hash_alg']))
  {
    exit(1, 'Failed to get the hash algorithm in ServerKeyExchange received from service listening on port '+ port +'.');
  }

  return skex['hash_alg'];
}

#
# MAIN
#

# Get an SSL port
port = get_ssl_ports(fork:TRUE);
if (isnull(port))
  exit(0, "The host does not appear to have any SSL-based services.");

# TLS signature extension is first supported in TLS 1.2
# Make sure remote TLS server supports TLS 1.2
#
tls12 = FALSE;
list = get_kb_list('SSL/Transport/'+port);
if(! isnull(list))
{
  list = make_list(list);
  foreach encap (list)
  {
    if (encap == COMPAT_ENCAPS_TLSv12)
    {
      tls12 = TRUE;
      break;
    }
  }
}
if(! tls12)
   exit(0, 'The SSL-based service listening on port '+port+' does not appear to support TLS 1.2.');



sighash_sha = raw_string(
6, 1, # sha512/rsa
5, 1, # sha384/rsa
4, 1, # sha256/rsa
3, 1, # sha224/rsa
2, 1, # sha1/rsa

6, 2, # sha512/dsa
5, 2, # sha384/dsa
4, 2, # sha256/dsa
3, 2, # sha224/dsa
2, 2, # sha1/dsa

6, 3, # sha512/ecdsa
5, 3, # sha384/ecdsa
4, 3, # sha256/ecdsa
3, 3, # sha224/ecdsa
2, 3  # sha1/ecdsa
);

# Check if server supports any of SHA hash algoritms
hash_alg =  get_hash_alg(port:port, sighash: sighash_sha);

# If so, check if server selects MD5 even higher hash algoirthms are available
if(hash_alg)
{
  # SignatureAndHashAlgorithm list is in descending order.
  # PolarSSL only uses the Hash part to select the SignatureAndHashAlgorithm.
  # Vulnerable PolarSSL (1.3.8) will select MD5.
  # Correct TLS implementations will select highest common hash algorithm
  sighash = raw_string(
  6, 1, # sha512/rsa
  5, 1, # sha384/rsa
  4, 1, # sha256/rsa
  3, 1, # sha224/rsa
  2, 1, # sha1/rsa

  6, 2, # sha512/dsa
  5, 2, # sha384/dsa
  4, 2, # sha256/dsa
  3, 2, # sha224/dsa
  2, 2, # sha1/dsa

  6, 3, # sha512/ecdsa
  5, 3, # sha384/ecdsa
  4, 3, # sha256/ecdsa
  3, 3, # sha224/ecdsa
  2, 3, # sha1/ecdsa

  1, 3,  # md5/ecdsa
  1, 2,  # md5/dsa
  1, 1   # md5/rsa
  );

  hash_alg =  get_hash_alg(port:port, sighash: sighash);
  # PolarSSL only negotiates the hash algorithm part
  # in SignatureAndHashAlgorithms.
  #
  # Vulnerable server selects the lowest common hash alg (MD5)
  if(hash_alg == 1)
    security_warning(port:port);
  else
    exit(0, 'The TLS service listening on port ' + port + ' is not affected.');
}
# never reached
VendorProductVersionCPE
polarsslpolarsslcpe:/a:polarssl:polarssl