Lucene search
K

Datagram Transport Layer Security Detection

🗓️ 16 Oct 2007 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 103 Views

The remote service is encrypted using Datagram Transport Layer Security (DTLS), which provides communications privacy for datagram protocols." - Tenable Network Security, Inc

Refs
Code
#
# (C) Tenable Network Security, Inc.
#


include("compat.inc");


if (description)
{
  script_id(27057);
  script_version("1.16");
  script_set_attribute(attribute:"plugin_modification_date", value:"2026/04/13");

  script_name(english:"Datagram Transport Layer Security Detection");
  script_summary(english:"Performs initial DTLS handshake");

  script_set_attribute(attribute:"synopsis", value:"An encrypted service is listening on the remote host.");
  script_set_attribute(attribute:"description", value:
"The remote service is encrypted using Datagram Transport Layer Security
(DTLS), which provides communications privacy for datagram protocols."
  );
  script_set_attribute(attribute:"see_also", value:"https://tools.ietf.org/html/rfc4347");
  script_set_attribute(attribute:"solution", value:"n/a");
  script_set_attribute(attribute:"risk_factor", value:"None");

 script_set_attribute(attribute:"plugin_publication_date", value:"2007/10/16");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"asset_inventory", value:"True");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"Service detection");

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

  script_exclude_keys("global_settings/disable_test_ssl_based_services");  
  exit(0);
}


include("byte_func.inc");
include("misc_func.inc");
include("ssl_funcs.inc");


# nb: some UDP services are fragile so only run the plugin if
#     safe checks are disabled.
if (safe_checks()) exit(0);

if (get_kb_item("global_settings/disable_test_ssl_based_services"))
  exit(1, "Not testing SSL based services per user config.");

set_byte_order(BYTE_ORDER_BIG_ENDIAN);

dtls_ver_10 = raw_string(0x01, 0x00);
ports = make_list(
  601,                                 # syslog (per draft-petch-gerhards-syslog-transport-dtls-00.txt)
  4433,                                # openssl s_server -dtls1 (default port)
  5061                                 # SIP (per draft-jennings-sip-dtls-05)
);


function dtls_client_hello(hlen, htype, ver, cipherspec, cspeclen, epoch, seqno, compmeths, compmethslen)
{
  local_var clen, frag_len, frag_ofs, handshake, hello;

  # Assign some defaults.
  # - handshake type.
  if (isnull(htype) || htype <= 0) htype = 1;  # client hello
  # - DTLS version.
  if (isnull(ver)) ver = dtls_ver_10;
  # - fragment offset.
  frag_ofs = 0;
  # - ciphers.
  if (isnull(cipherspec))
  {
    if (isnull(cspeclen))
      # nb: this is what openssl s_client uses by default.
      # update 7/26/2019 Added openssl 1.1.0 s_client default ciphers
      cipherspec =
          ciphers["TLS12_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"] +
          ciphers["TLS12_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] +
          ciphers["TLS12_DHE_RSA_WITH_AES_256_GCM_SHA384"] +
          ciphers["TLS12_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"] +
          ciphers["TLS12_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"] +
          ciphers["TLS12_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"] +
          ciphers["TLS12_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"] +
          ciphers["TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA256"] +
          ciphers["TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256"] +
          ciphers["TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"] +
          ciphers["TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA384"] +
          ciphers["TLS1_DHE_RSA_WITH_AES_256_CBC_SHA256"] +
          ciphers["TLS1_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"] +
          ciphers["TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA256"] +
          ciphers["TLS1_DHE_RSA_WITH_AES_128_CBC_SHA256"] +
          ciphers["TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"] +
          ciphers["TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA"] +
          ciphers["TLS1_DHE_RSA_WITH_AES_256_CBC_SHA"] +
          ciphers["TLS1_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"] +
          ciphers["TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA"] +
          ciphers["TLS1_DHE_DSS_WITH_AES_256_CBC_SHA"] +
          ciphers["TLS12_RSA_WITH_AES_256_GCM_SHA384"] +
          ciphers["TLS12_RSA_WITH_AES_128_GCM_SHA256"] +
          ciphers["TLS1_RSA_WITH_NULL_SHA256"] +
          ciphers["TLS1_RSA_WITH_AES_128_CBC_SHA256"] +
          ciphers["TLS1_RSA_WITH_AES_256_CBC_SHA256"] +
          ciphers["TLS1_RSA_WITH_AES_256_CBC_SHA"] +
          ciphers["TLS1_DHE_RSA_WITH_3DES_EDE_CBC_SHA"] +
          ciphers["TLS1_DHE_DSS_WITH_3DES_EDE_CBC_SHA"] +
          ciphers["TLS1_RSA_WITH_3DES_EDE_CBC_SHA"] +
          ciphers["TLS1_DHE_RSA_WITH_AES_128_CBC_SHA"] +
          ciphers["TLS1_DHE_DSS_WITH_AES_128_CBC_SHA"] +
          ciphers["TLS1_RSA_WITH_AES_128_CBC_SHA"] +
          ciphers["TLS1_RSA_WITH_IDEA_CBC_SHA"] +
          ciphers["TLS1_RSA_WITH_RC4_128_SHA"] +
          ciphers["TLS1_RSA_WITH_RC4_128_MD5"] +
          ciphers["TLS1_DHE_RSA_WITH_DES_CBC_SHA"]  +
          ciphers["TLS1_DHE_DSS_WITH_DES_CBC_SHA"] +
          ciphers["TLS1_RSA_WITH_DES_CBC_SHA"] +
          ciphers["TLS1_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"] +
          ciphers["TLS1_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"] +
          ciphers["TLS1_RSA_EXPORT_WITH_DES40_CBC_SHA"] +
          ciphers["TLS1_RSA_EXPORT_WITH_RC2_CBC_40_MD5"] +
          ciphers["TLS1_RSA_EXPORT_WITH_RC4_40_MD5"];
    else
      # nb: fill it with random bytes.
      while (strlen(cipherspec) < cspeclen)
        cipherspec = cipherspec + (rand() % 256);
  }
  if (isnull(cspeclen))
  {
    cspeclen = strlen(cipherspec);
    cspeclen = raw_string(cspeclen / 256, cspeclen % 256);
  }
  # - epoch
  if (isnull(epoch)) epoch = 0;
  # - sequence number.
  if (isnull(seqno)) seqno = 0;
  # - compression methods
  if (isnull(compmeths)) {
    compmeths = raw_string(0x00);
    # nb: fill out field with random bytes.
    while (strlen(compmeths) < compmethslen)
      compmeths = compmeths + (rand() % 256);
  }
  if (isnull(compmethslen)) compmethslen = raw_string(strlen(compmeths));

  # Assemble the message.
  clen = 39 + strlen(cipherspec) + strlen(compmeths);
  frag_len = clen;

  handshake = mkbyte(htype) +          # handshake type
    mkbyte(clen / 0xff) +
      mkword(clen % 0xff) +
    mkword(seqno) +
    mkbyte(frag_ofs / 0xff) +
      mkword(frag_ofs % 0xff) +
    mkbyte(frag_len / 0xff) +
      mkword(frag_len % 0xff) +
    ver +
    mkdword(unixtime()) +
    crap(28) +
    mkbyte(0x00) +                     # session id length
    mkbyte(0x00) +                     # cookie length
    mkword(strlen(cipherspec)) +
    cipherspec +
    mkbyte(strlen(compmeths)) +
      compmeths;

  if (isnull(hlen)) hlen = strlen(handshake);
  hello = mkbyte(0x16) +                 # message type (0x16 => handshake)
    ver +
    mkword(epoch) +
    mkword(seqno / 0x10000) +
      mkdword(seqno % 0x10000) +
    mkword(hlen) +
      handshake;

  return(hello);
}


foreach port (ports)
{
  if (service_is_unknown(port:port, ipproto:"udp") && get_udp_port_state(port))
  {
    soc = open_sock_udp(port);
    if (soc)
    {
      hello = dtls_client_hello(seqno:0);
      send(socket:soc, data:hello);
      res = recv(socket:soc, length:8192, min:14);

      # If...
      if (
        # the response is long enough and...
        strlen(res) >= 13 &&
        # the reply uses our epoch and...
        getword(blob:res, pos:3) == epoch &&
        # the reply uses our sequence number and...
        (getword(blob:res, pos:5)*0x10000+getdword(blob:res, pos:7)) == seqno &&
        # the reply is either...
        (
          # a handshake verify request or...
          (getbyte(blob:res, pos:0) == 0x16 && getbyte(blob:res, pos:13) == 3) ||
          # an alert
          getbyte(blob:res, pos:0) == 0x15
        )
      )
      {
        # Complete the handshake so the connection can be reused.
        if (getbyte(blob:res, pos:0) == 0x16)
        {
          hello2 = dtls_client_hello(seqno:1);
          send(socket:soc, data:hello2);
          res2 = recv(socket:soc, length:8192, min:14);
          if (strlen(res2) >= 13  && getbyte(blob:res2, pos:13) == 2)
          {
            alert = mkbyte(0x15) +
              dtls_ver_10 +
              mkword(epoch) +
              mkword(0) + mkdword(2) +
              mkword(7) +
              mkbyte(2) +
              mkbyte(0x2a) +
              crap(5);
            send(socket:soc, data:alert);
            res3 = recv(socket:soc, length:14);
          }
        }

        # Report it.
        security_note(port:port, proto:"udp");
      }
      close(soc);
    }
  }
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation