Lucene search

K
nessusThis script is Copyright (C) 2016-2020 and is owned by Tenable, Inc. or an Affiliate thereof.OPENSSL_AES_NI_PADDING_ORACLE.NASL
HistoryJun 13, 2016 - 12:00 a.m.

OpenSSL AES-NI Padding Oracle MitM Information Disclosure

2016-06-1300:00:00
This script is Copyright (C) 2016-2020 and is owned by Tenable, Inc. or an Affiliate thereof.
www.tenable.com
2529

CVSS2

2.6

Attack Vector

NETWORK

Attack Complexity

HIGH

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

NONE

AV:N/AC:H/Au:N/C:P/I:N/A:N

CVSS3

5.9

Attack Vector

NETWORK

Attack Complexity

HIGH

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N

EPSS

0.969

Percentile

99.7%

The remote host is affected by a man-in-the-middle (MitM) information disclosure vulnerability due to an error in the implementation of ciphersuites that use AES in CBC mode with HMAC-SHA1 or HMAC-SHA256.
The implementation is specially written to use the AES acceleration available in x86/amd64 processors (AES-NI). The error messages returned by the server allow allow a man-in-the-middle attacker to conduct a padding oracle attack, resulting in the ability to decrypt network traffic.

#TRUSTED 76b21af400c4603cb8683db911ae129d4ddd4eb2146ad7bf8c39d1478eb4e34cb3ae7f3ddbd50f9847732819d7457b77f80ad058a55019d287c372b9a4911cc4808bf27b8a5aac7f5adecad7b80abfeb0ac2f984ac2182aad5465507290d823ec87d04699c611431273de3fda000125a5dd341b6b31871d2ebf963ebcdabd1044705af8edc36dad48d5f7eb067dba82b66e56d805d75a1f9d91550f8dbff60aa0e4c2353fc5bab080a04e153e108106f172833f774e39cc7ba6f908f30ca13009f8cd6c33bdb53c3dd1e885d1b6c0c7ee4e6f323b34e7590fd3dc8af075230308d34e64cfe52eaaa21df13e9277231598ca27fac64404e574b3e8c6b9bf6282d09e0d35624c2ceb53d0cef007f9cb99013bbb09e72def49001ad576cd4e3dbc5cecfb9b7115436f407ad82b48bc54bf720e396a3eee66fb8c362507f82fceeb6a88b334b6090703f941c99efd78ee25d1b94f77e5a1ff87998cab9a4571fa0d290943d00d6f7f995879140bd7664545e1708b89784e9941e23a9af3fb25bc4f5c4cbe0f9d0d58c336b0c653e6c1ee9a68d74dc4db2a2c1156885b11b64700899960415b62552bf354604c9ccd943dfebfbd69c5981a3e02096dd80e67840567ed582fa9fc98c8213dac5a7bda9a5eca7c6a99d3554dd8190d216e5e43f38e1397888664d5c5ac4c2f18f3d8d9b85a2855bfef1efc4b66b4131f47aa3df937ad6
#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(91572);
  script_version("1.19");
  script_set_attribute(attribute:"plugin_modification_date", value:"2020/08/17");

  script_cve_id("CVE-2016-2107");
  script_bugtraq_id(89760);
  script_xref(name:"EDB-ID", value:"39768");

  script_name(english:"OpenSSL AES-NI Padding Oracle MitM Information Disclosure");
  script_summary(english:"Checks if the server sends a RECORD_OVERFLOW alert to a crafted TLS handshake.");

  script_set_attribute(attribute:"synopsis", value:
"It was possible to obtain sensitive information from the remote host
with TLS-enabled services.");
  script_set_attribute(attribute:"description", value:
"The remote host is affected by a man-in-the-middle (MitM) information
disclosure vulnerability due to an error in the implementation of
ciphersuites that use AES in CBC mode with HMAC-SHA1 or HMAC-SHA256.
The implementation is specially written to use the AES acceleration
available in x86/amd64 processors (AES-NI). The error messages
returned by the server allow allow a man-in-the-middle attacker to
conduct a padding oracle attack, resulting in the ability to decrypt
network traffic.");
  script_set_attribute(attribute:"see_also", value:"https://blog.filippo.io/luckyminus20/");
  # https://web-in-security.blogspot.com/2016/05/curious-padding-oracle-in-openssl-cve.html
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?7647e9f0");
  script_set_attribute(attribute:"see_also", value:"https://www.openssl.org/news/secadv/20160503.txt");
  script_set_attribute(attribute:"solution", value:
"Upgrade to OpenSSL version 1.0.1t / 1.0.2h or later.");
  script_set_cvss_base_vector("CVSS2#AV:N/AC:H/Au:N/C:P/I:N/A:N");
  script_set_cvss_temporal_vector("CVSS2#E:POC/RL:OF/RC:C");
  script_set_attribute(attribute:"cvss_score_source", value:"CVE-2016-2107");
  script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N");
  script_set_cvss3_temporal_vector("CVSS:3.0/E:P/RL:O/RC:C");
  script_set_attribute(attribute:"exploitability_ease", value:"Exploits are available");
  script_set_attribute(attribute:"exploit_available", value:"true");

  script_set_attribute(attribute:"vuln_publication_date", value:"2016/05/03");
  script_set_attribute(attribute:"patch_publication_date", value:"2016/05/03");
  script_set_attribute(attribute:"plugin_publication_date", value:"2016/06/13");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:openssl:openssl");
  script_set_attribute(attribute:"in_the_news", value:"true");
  script_end_attributes();

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

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

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

  exit(0);
}

include("audit.inc");
include("global_settings.inc");
include("x509_func.inc");
include("rsync.inc");
include("ftp_func.inc");
include("ldap_func.inc");
include("nntp_func.inc");
include("smtp_func.inc");
include("telnet2_func.inc");
include("ssl_funcs.inc");
include("string.inc");

##
# Checks whether a cipher is in a list of cipher suites.
#
# @anonparam cipher Cipher in question.
# @anonparam ciphers List of cipher suites.
#
# @return TRUE for success, FALSE otherwise.
##
function tls_cipher_in_list()
{
  local_var cipher, ciphers, i, id, len;

  cipher = _FCT_ANON_ARGS[0];
  ciphers = _FCT_ANON_ARGS[1];

  len = strlen(ciphers);
  for (i = 0; i < len; i += 2)
  {
    id = substr(ciphers, i, i + 2 - 1);
    if (cipher == id) return TRUE;
  }

  return FALSE;
}

##
# Split the key block into IVs, cipher keys, and MAC keys.
#
# @anonparam keyblk Key block derived from the master secret.
#
# @return TRUE for success, FALSE otherwise.
##
function tls_set_keys(cipher_desc, keyblk)
{
  local_var mac_size, iv_size, key_size, pos, tls, mac, encryption;

  # Determine the size of the key block's fields.
  mac = cipher_field(name:cipher_desc, field:"mac");
  if ('SHA1' >< mac)        mac_size = 20;
  else if ('SHA256' >< mac) mac_size = 32;
  else return FALSE;

  encryption = cipher_field(name:cipher_desc, field:"encrypt");
  if ('AES-CBC(128)' >< encryption)      { key_size = 16; iv_size = 16; }
  else if ('AES-CBC(256)' >< encryption) { key_size = 32; iv_size = 16; }
  else return FALSE;

  # Ensure the block is big enough.
  if (strlen(keyblk) < 2 * (mac_size + key_size + iv_size))
    return FALSE;

  # Extract the data from the key block.
  pos = 0;
  tls['enc_mac_key'] = substr(keyblk, pos, pos + mac_size - 1); pos += mac_size;
  tls['dec_mac_key'] = substr(keyblk, pos, pos + mac_size - 1); pos += mac_size;
  tls['enc_key']     = substr(keyblk, pos, pos + key_size - 1); pos += key_size;
  tls['dec_key']     = substr(keyblk, pos, pos + key_size - 1); pos += key_size;
  tls['enc_iv']      = substr(keyblk, pos, pos + iv_size  - 1); pos += iv_size;
  tls['dec_iv']      = substr(keyblk, pos, pos + iv_size  - 1);

  return tls;
}

##
##
# Tries to make a TLS connection to the server.
#
# @return TRUE for success, FALSE otherwise.
##
function attack(port, ciphers)
{
  local_var soc, data, rec, srv_random, clt_random, version, cipher_desc;
  local_var cert, clt_cert_requested, skex, premaster, n, e, dh_privkey;
  local_var ckex, keyblk, tls_keys, tls_ciphertext, pubkey;

  # Get a socket to perform a handshake.
  soc = open_sock_ssl(port);
  if (!soc)
    # XXX-ALW Fix this error message
    return [FALSE, "open_sock_ssl", "Couldn't begin SSL handshake"];

  data = client_hello(
    v2hello:FALSE,
    version:mkword(TLS_10), # Record-layer version (RFC5246 Appendix E)
    maxver:mkword(TLS_12),  # Handshake version; maximum we support
    cipherspec:ciphers,
    extensions:tls_ext_ec(keys(curve_nid.tls))
  );
  send(socket:soc, data:data);
  rec = ssl_parse(blob:data);
  # Hang onto the Client Random; we need it to derive keys later.
  clt_random = mkdword(rec['time']) + rec['random'];

  # Read records one at a time. Expect to see at a minimum:
  # ServerHello, Certificate, and ServerHelloDone.
  while (TRUE)
  {
    # Receive a record from the server.
    data = recv_ssl(socket:soc);
    if (isnull(data))
    {
      close(soc);
      return [FALSE, "recv_ssl", "Did not receive expected ServerHello, ServerCertificate, etc."];
    }

    # ServerHello: Extract the random data for computation of keys.
    rec = ssl_find(
      blob:data,
      'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
      'handshake_type', SSL3_HANDSHAKE_TYPE_SERVER_HELLO
    );

    if (!isnull(rec))
    {
      # If server asks for version less than TLS 1.0 or higher than TLS 1.2, fail.
      if (rec['handshake_version'] < TLS_10 || rec['handshake_version'] > TLS_12)
        return [FALSE, "handshake_version", "Server does not support TLS 1.0, 1.1, or 1.2"];

      # Use the TLS version the server wants
      version = rec['handshake_version'];

      srv_random = mkdword(rec['time']) + rec['random'];

      # Wacko SSL servers might return a cipher suite not in the
      # client's request list.
      if (!tls_cipher_in_list(mkword(rec['cipher_spec']), ciphers))
      {
        close(soc);
        return [FALSE, "cipher_spec", "Server ignored our list of supported ciphers"];
      }

      # Store the negotiated cipher suite.
      cipher_desc = ciphers_desc[cipher_name(id:rec['cipher_spec'])];

      if (isnull(cipher_desc))
      {
        close(soc);
        return [FALSE, "cipher_spec", "Assertion failure"];
      }
    }

    # Certificate: Extract the server's public key.
    rec = ssl_find(
      blob:data,
      'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
      'handshake_type', SSL3_HANDSHAKE_TYPE_CERTIFICATE
    );

    if (!isnull(rec) && max_index(rec['certificates']) > 0)
    {
      # First cert in the chain should be the server cert.
      cert = parse_der_cert(cert:rec['certificates'][0]);
      if (isnull(cert))
      {
        close(soc);
        return [FALSE, "parse_der_cert", "Failed to parse server's certificate"];
      }
      cert = cert['tbsCertificate'];
    }

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

    if (!isnull(rec['data']))
      skex = ssl_parse_srv_kex(blob:rec['data'], cipher:cipher_desc, version:version);

    # Certificate Request.
    rec = ssl_find(
      blob:data,
      'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
      'handshake_type', SSL3_HANDSHAKE_TYPE_CERTIFICATE_REQUEST
    );

    if (!isnull(rec['data']))
      clt_cert_requested = TRUE;

    # Server Hello Done.
    rec = ssl_find(
      blob:data,
      'content_type', SSL3_CONTENT_TYPE_HANDSHAKE,
      'handshake_type', SSL3_HANDSHAKE_TYPE_SERVER_HELLO_DONE
    );

    # When we get a ServerHelloDone, it's our turn to send again.
    if (!isnull(rec))
      break;

    # Is it an alert?
    rec = ssl_find(
      blob:data,
      encrypted:FALSE,
      'content_type', SSL3_CONTENT_TYPE_ALERT
    );

    if (!isnull(rec))
    {
      close(soc);
        return [FALSE, "handshake_failure", "Server sent alert to ClientHello. Level: " + rec['level'] + ", description: " + rec['description']];
    }
  }

  # Will contain an empty ClientCertificate (if requested), ClientKeyExchange,
  data = '';

  # Create an empty client certificate if one is requested.
  if (clt_cert_requested)
  {
    # Send an empty certificate for now. TLSv1.0 says the client can
    # send an empty certificate.
    data += ssl_mk_record(
      type:SSL3_CONTENT_TYPE_HANDSHAKE,
      version:version,
      data:ssl_mk_handshake_msg(
        type : SSL3_HANDSHAKE_TYPE_CERTIFICATE,
        data : ssl_vldata_put(data:NULL,len:3)
      )
    );
  }

  # Process ServerCertificate and ServerKeyExchange messages.
  var cipher_kex = cipher_field(name:cipher_desc, field:"kex");
  if (cipher_kex =~ "RSA($|\()")
  {
    if (isnull(cert))
    {
      close(soc);
      return [FALSE, "rsa_kx", "Server selected RSA key exchange but didn't provide a certificate"];
    }

    if (isnull(cert['subjectPublicKeyInfo']) || isnull(cert['subjectPublicKeyInfo'][1]))
    {
      close(soc);
      return [FALSE, "rsa_kx", "A server certificate with an unsupported algorithm was found."];
    }

    n = cert['subjectPublicKeyInfo'][1][0];
    e = cert['subjectPublicKeyInfo'][1][1];

    if (isnull(n) || isnull(e))
    {
      close(soc);
      return [FALSE, "rsa_kx", "Failed to extract public key from server certificate."];
    }

    premaster = mkword(TLS_12) + rand_str(length:46);

    # Encrypt the premaster secret with server's RSA public key.
    ckex = rsa_public_encrypt(data:premaster, n:n, e:e);

    # It looks like TLS 1.0 and up prepend a two-byte length, but the
    # RFC is vague.
    if (version >= TLS_10)
      ckex = ssl_vldata_put(data:ckex, len:2);
  }
  else if (cipher_kex =~ "ECDH($|\()" && ecc_functions_available())
  {
    if (isnull(skex))
    {
      close(soc);
      return [FALSE, "ecdh_kx", "Server selected ECDHE key exchange but didn't provide a ServerKeyExchange"];
    }

    # Generate the client private key
    dh_privkey = rand_str(length:16);

    # Compute the premaster secret
    premaster = ecc_scalar_multiply(
      curve_nid:curve_nid.tls[skex['named_curve']],
      scalar:dh_privkey,
      x:substr(skex['pubkey'], 1, (strlen(skex['pubkey'])) / 2),
      y:substr(skex['pubkey'], (strlen(skex['pubkey']) / 2) + 1)
    );
    # Just the X coordinate of the curve point is used
    premaster = ecc_fe2osp(element:premaster.x, curve_nid:curve_nid.tls[skex['named_curve']]);

    pubkey = ecc_scalar_multiply(
      curve_nid:curve_nid.tls[skex['named_curve']],
      scalar:dh_privkey
    );

    pubkey.x = ecc_fe2osp(element:pubkey.x, curve_nid:curve_nid.tls[skex['named_curve']]);
    pubkey.y = ecc_fe2osp(element:pubkey.y, curve_nid:curve_nid.tls[skex['named_curve']]);

    ckex = ssl_vldata_put(
      # Uncompressed curve point encoding
      data:'\x04' + pubkey.x + pubkey.y,
      len:1
    );
  }
  else if (cipher_kex =~ "DH($|\()")
  {
    if (isnull(skex))
    {
      close(soc);
      return [FALSE, "dh_kx", "Server selected DH key exchange but didn't provide a ServerKeyExchange"];
    }

    # Generate the client private key,
    dh_privkey = rand_str(length:16);

    # Compute the premaster secret.
    premaster = bn_mod_exp(skex['dh_y'], dh_privkey, skex['dh_p']);

    # Encode the client's DH public key
    ckex = ssl_vldata_put(
      data:bn_mod_exp(skex['dh_g'], dh_privkey, skex['dh_p']),
      len:2
    );
  }
  else
  {
    close(soc);
    return [FALSE, "kx", "Unsupported key exchange method"];
  }

  # Create a ClientKeyExchange record
  data += ssl_mk_record(
    type:SSL3_CONTENT_TYPE_HANDSHAKE,
    version:version,
    data:ssl_mk_handshake_msg(
      type:SSL3_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE,
      data:ckex
    )
  );

  tls_keys = tls_set_keys(
    cipher_desc:cipher_desc,
    keyblk:ssl_derive_keyblk(
      c_random:clt_random,
      s_random:srv_random,
      version:version,
      cipher_desc:cipher_desc,
      master:ssl_calc_master(
        c_random:clt_random,
        s_random:srv_random,
        version:version,
        premaster:premaster,
        cipher_desc:cipher_desc
      )
    )
  );

  if (tls_keys == FALSE)
  {
    close(soc);
    return [FALSE, "kx", "Failed to make TLS keys from key exchange"];
  }

  data += tls_mk_record(
    type:SSL3_CONTENT_TYPE_CHANGECIPHERSPEC,
    data:mkbyte(1),
    version:version
  );

  # Use a random IV, as it's included explicitly in TLS 1.1
  if (version >= TLS_11)
    tls_keys['enc_iv'] = rand_str(length:strlen(tls_keys['enc_iv']));

  # Finished message.
  # We make a record of just bad padding to trigger a RECORD_OVERFLOW alert.
  # 48 bytes of padding because:
  # o Must be a multiple of AES block size (16 bytes).
  # o Must be at least one byte bigger than the MAC size.
  # o SHA1 is 20 bytes, SHA256 is 32 bytes, so we round up to 48.
  # o SHA384 ciphersuites are not vulnerable.
  tls_ciphertext = aes_cbc_encrypt(
    data:crap(data:'\xff', length:48),
    iv:tls_keys['enc_iv'],
    key:tls_keys['enc_key']
  );
  # aes_cbc_encrypt() returns an array, [0] is ciphertext, [1] is CBC
  # residue (for TLS 1.0 IV). We don't retain the residue because we
  # don't intent to send any more records.
  tls_ciphertext = tls_ciphertext[0];

  # TLS 1.1 explicitly includes the IV in each record
  if (version >= TLS_11)
    tls_ciphertext = tls_keys['enc_iv'] + tls_ciphertext;

  data += tls_mk_record(
    type:SSL3_CONTENT_TYPE_HANDSHAKE,
    data:tls_ciphertext,
    version:version
  );

  # Send the ChangeCipherSpec and tampered Finished message
  send(socket:soc, data:data);

  while (TRUE)
  {
    # Receive a record from the server.
    data = recv_ssl(socket:soc);
    if (isnull(data))
    {
      close(soc);
      return [FALSE, "post_attack", "Server did not send an alert when sent a crafted Finished message"];
    }

    # Is it an alert?
    rec = ssl_find(
      blob:data,
      encrypted:FALSE,
      'content_type', SSL3_CONTENT_TYPE_ALERT
    );

    if (!isnull(rec))
    {
      close(soc);
      if (rec['level'] == 2 && rec['description'] == SSL3_ALERT_TYPE_RECORD_OVERFLOW)
        return [TRUE, "post_attack", "Server sent RECORD_OVERFLOW alert"];
      else
        return [FALSE, "post_attack", "Server sent alert to tampered Finished. Level: " + rec['level'] + ", description: " + rec['description']];
    }
  }
}

get_kb_item_or_exit('SSL/Supported');

# Get a port that uses SSL.
port = get_ssl_ports(fork:TRUE);

if (isnull(port))
  exit(1, 'The host does not appear to have any SSL-based services.');

# Find out if the port is open.
if (!get_port_state(port))
  audit(AUDIT_PORT_CLOSED, port, "TCP");

# Ciphersuites should basically be the "Cartesian product" of:
# * DHE and RSA key exchanges
# * AES-CBC with 128- and 256-bit keys
# * SHA1 and SHA256 HMACs (SHA384 ciphersuites are not vulnerable)
# TODO: should support ECDHE and ECDSA, once we can do that from NASL.

# We test SHA1 separately from SHA256 and check if *either* was
# vulnerable, because vulnerable 1.0.1 servers support SHA256 but are
# only vulnerable on SHA1 ciphersuites. If we offered SHA1 and SHA256
# at the same time and the server preferred SHA256, it'd be a false
# negative.

cipher_list_sha1 =
  ciphers['TLS1_CK_RSA_WITH_AES_128_CBC_SHA'] + # <- Required by all TLS 1.2 impls.
  ciphers['TLS1_CK_RSA_WITH_AES_256_CBC_SHA'] +
  ciphers['TLS1_CK_DHE_RSA_WITH_AES_128_CBC_SHA'] +
  ciphers['TLS1_CK_DHE_RSA_WITH_AES_256_CBC_SHA'];

cipher_list_sha256 =
    ciphers['TLS1_RSA_WITH_AES_128_CBC_SHA256'] +
    ciphers['TLS1_RSA_WITH_AES_256_CBC_SHA256'] +
    ciphers['TLS1_DHE_RSA_WITH_AES_128_CBC_SHA256'] +
    ciphers['TLS1_DHE_RSA_WITH_AES_256_CBC_SHA256'];

if (ecc_functions_available())
{
  cipher_list_sha1 +=
    ciphers["TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA"] +
    ciphers["TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA"];

  cipher_list_sha256 +=
    ciphers["TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA256"] +
    ciphers["TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA256"];
}

sha1_result = attack(port:port, ciphers:cipher_list_sha1);

# Only do SHA256 test if we didn't find a vuln with SHA1.
if (sha1_result[0] == FALSE)
  sha256_result = attack(port:port, ciphers:cipher_list_sha256);

if (sha1_result[0] == TRUE || sha256_result[0] == TRUE)
{
  security_report_v4(
    port:port,
    severity:SECURITY_NOTE,
    extra:
      'Nessus was able to trigger a RECORD_OVERFLOW alert in the\n' +
      'remote service by sending a crafted SSL "Finished" message.'
  );
}
else
{
  exit(0,
    "[Port " + port + "] " +
    "SHA1 test: " + sha1_result[1] + ": " + sha1_result[2] + ". " +
    "SHA256 test: " + sha256_result[1] + ": " + sha256_result[2]);
}

CVSS2

2.6

Attack Vector

NETWORK

Attack Complexity

HIGH

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

NONE

AV:N/AC:H/Au:N/C:P/I:N/A:N

CVSS3

5.9

Attack Vector

NETWORK

Attack Complexity

HIGH

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N

EPSS

0.969

Percentile

99.7%