Lucene search
+L

Junos Version Detection

🗓️ 22 Aug 2011 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 143 Views

Junos Version Detection. Obtain the version number of the remote Juniper device

Code
#TRUSTED 2ee1e8cff32f007ca776e87a1bacbc3fa03c25550c495f67502bc40d389643f74419a029a967b0bd4489cdc4fe798fc15d496b8decae24158e667db6b8c995eb9028424ba533d45799689a318f838ef7dc0db7f610b4e59ae9c7a884c2748d3730a52b833f97db6d84cb4572b94cc8199c1c701dec4745020b675c60d273261e20021e1f395b71215c8f1f89a03ec0c7e197871093e3147737040ae2a8ba7dbfcd53cf9094cb1598dbeac097cc59a5be9e463a5800166c04d7c9ad25283fd083ce91fa5feccc87c8e564c0a35f442652dadf9f755cad076fef22a4ad9af471f76e1a9c1b9b01798b07b45fc84edd024a4766a16496c26ae5e9a2d5503232905545189e00e882e7141ab168abb085ce785182997351e823167ff1b66f0288863745f593e6e106ca8b8c19928bb806486c727a105f689f278e54c491022a0906d880e15156a11818604d3eaf1fd0209f579c1ac5fb8b043931ef7f1ec9b60211b20714b1defdb80c651e9273c09571348df90eb3f5e261e1417544e807877457d66578d325e8a930d410f945f6f2d33b2deb11aefb7360136783fc44e779495a2516ed096038773d3348ff23a8bf2120599a9a0d657dcb2a4fbed19da15d231abbe2a3862d70fabfbd43e5cd4b507650e7e7c645c3373f61912d42b09c3caad472098bfbe5febcd5700a07d82033ba95207a0ffc4d09544fbb7dfeb68fd52bcb3f
#TRUST-RSA-SHA256 272ac670927d11f30dadc60d6a6175833465debb7afb6cffa844166b653aaab70c04c1778a57c3848ee1a9d891783721b7915d294b09db6b0f08126e51e4434595a8c1a85a9a5a3e644cee5b42ec4120402a2e74dc40bf7f83849b352a588db82f80f7e84e2af93e7a78309a8ae8caf7f2f1b063123b99b6aaefd15a6ad3167c44b61209e9d39e894d02e5843867184763990f9a35ab691e59c39526fd7a639bd549f407c185696781a82591271adc66ec1c681912b0ac84b8fe3b8fda732aafde29bcc84a5390fd5fe44e53cb1431ee775dc87b7ba23cbc36a9691132730af39841abed1353d8a4954b02b60cb79992ac322b0f78a3526e4472ac88fbbb3fe4bd7ab95fe8d54946d044e365b6846d961d188f76095e654bc737513eddad29ee3c2174c4e07bb5c5d9902ef2861c14b20a98b94d2654ecd1c100b4bb470df20f0b4478e707afe71a7de1a226cd7cf58ab7b560923a7fc113251752b3ef4c14d7cb9fb917948b9168ec691a19b03ad8f587d37abd3db3ca83e708c153141fa536c816b757fac0f305330d823dc7d66fdfdabd06408006a356bf6d3d65027863678170fd5d6de06d3c41dd2a6cf904eae00bb071b9d32923fc8e5acdd288190a5ec76847943aad15a821fbfb5a6ef4614cb65ff4e673883ec3ca92fcad6feca43a5cae02bd2b4b92143ee88a2b4a17dc973bfea88989443d1150e04e82a7e7b59c
##
# (C) Tenable, Inc.
##

include("compat.inc");

if (description)
{
 script_id(55932);
 script_version("1.30");
 script_set_attribute(attribute:"plugin_modification_date", value:"2025/08/13");

  script_xref(name:"IAVT", value:"0001-T-0642");

 script_name(english:"Junos Version Detection");

 script_set_attribute(attribute:"synopsis", value:
"It is possible to obtain the operating system version number of the
remote Juniper device.");
 script_set_attribute(attribute:"description", value:
"The remote host is running Junos, an operating system for Juniper
devices.

It is possible to read the Junos version number by logging into the
device via SSH, using SNMP, or viewing the web interface.");
 script_set_attribute(attribute:"solution", value:"n/a");
 script_set_attribute(attribute:"risk_factor", value:"None");

 script_set_attribute(attribute:"plugin_publication_date", value:"2011/08/22");

 script_set_attribute(attribute:"plugin_type", value:"combined");
 script_set_attribute(attribute:"cpe", value:"cpe:/o:juniper:junos");
 script_set_attribute(attribute:"asset_inventory", value:"True");
 script_set_attribute(attribute:"hardware_inventory", value:"True");
 script_set_attribute(attribute:"os_identification", value:"True");
 script_end_attributes();
 script_category(ACT_GATHER_INFO);

 script_copyright(english:"This script is Copyright (C) 2011-2025 and is owned by Tenable, Inc. or an Affiliate thereof.");
 script_family(english:"Junos Local Security Checks");

 script_dependencies("ssh_get_info.nasl", "snmp_sysDesc.nasl", "netconf_detect.nbin");
 script_require_ports("Host/Juniper/show_ver", "SNMP/sysDesc", "Services/www");

 exit(0);
}

include("snmp_func.inc");
include("http.inc");
include('host_os.inc');
include('hardware_registration.inc');
include('os_install.inc');
include('structured_data.inc');

##
# Saves the provided Junos version, build date, model,
# source, port and chassis serial number in the KB,
# generates plugin output, registers os and exits.
#
# @param ver JUNOS version number
# @param build Juniper device type
# @param model Juniper model number
# @param source service used to obtain the version
# @param port Port used in detection (0 for SSH)
#
##
function junos_report_exit(ver, build, model, source, port, serial, node_info)
{
  var snj; # Serial Number Juniper
  var type, confidence;
  var report = '';
  var id_data = {};

  if (!empty_or_null(node_info))
  {
    if (!empty_or_null(node_info['node_id']))
    {
      set_kb_item(name:'Host/Juniper/JUNOS/node', value:node_info['node_id']);
      report += '\n  Cluster node  : ' + node_info['node_id'];
    }
    if (!empty_or_null(node_info['node_status']))
    {
      set_kb_item(name:'Host/Juniper/JUNOS/node_status', value:node_info['node_status']);
      report += '\n  Node status   : ' + node_info['node_status'];
    }
  }

  if (!empty_or_null(ver))
  {
    set_kb_item(name:"Host/Juniper/JUNOS/Version", value:ver);
    report += '\n  Junos version : ' + ver;
  }
  if (!empty_or_null(build))
  {
    set_kb_item(name:"Host/Juniper/JUNOS/BuildDate", value:build);
    report += '\n  Build date    : ' + build;
  }
  if (!empty_or_null(model))
  {
    set_kb_item(name:"Host/Juniper/model", value:model);
    report += '\n  Model         : ' + model;
  }
  if (!empty_or_null(port))
  {
    set_kb_item(name:"Host/Juniper/JUNOS/Port", value:port);
    report += '\n  Port          : ' + port;
  }
  if(!empty_or_null(serial))
  {
    set_kb_item(name:"Host/Juniper/JUNOS/Serial Number", value:serial);
    snj = new structured_data_asset_identifier();

    # report structured data value
    id_data['identifier_source'] =  'juniperSerialNumber';
    id_data['identifier_value'] = serial;
    id_data['type'] = 'Network Device Serial Identifier';

    dbg::detailed_log(lvl:3,
      src:SCRIPT_NAME,
      msg:'id data found',
      msg_details: {
        "findings": { "lvl": 3, "value":id_data }
        }
    );

    snj.append('identifier', id_data);
    snj.report_internal();

    report += '\n  Serial        : ' + serial;
  }

  ## set os identification
  if (!empty_or_null(source))
  {
    set_kb_item(name:"Host/Juniper/JUNOS/Source", value:source);
    report += '\n  Source        : ' + source;

    if (source == 'SSH')
    {
      if (!empty_or_null(ver))
        juniper_os += ver;

      type = 'local';
      confidence = 100;

      host_os_add(method: 'SSH', os: juniper_os, confidence: confidence, type: 'embedded');
    }

    if (source == 'SNMP')
    {
      if (!empty_or_null(ver))
        juniper_os += ver;

      type = 'remote';
      confidence = 85;

      host_os_add(method: 'SNMP', os: juniper_os, confidence: confidence, type: 'embedded');
    }

    if (source == 'NETCONF')
    {
      if (!empty_or_null(ver))
        juniper_os += ver;

      type = 'remote';
      confidence = 85;

      host_os_add(method: 'NETCONF', os: juniper_os, confidence: confidence, type: 'embedded');
    }

    if (source == 'HTTP')
    {
      if (!empty_or_null(ver))
        juniper_os += ver;

      type = 'remote';
      confidence = 85;

      host_os_add(method: 'WebUI', os: juniper_os, confidence: confidence, type: 'embedded');
    }

  }

  var vendor = 'Juniper';
  var product = 'Junos';
  var os_name = strcat(vendor, ' ', product);

  var cpe = 'cpe:/o:juniper:junos:';

  var display_version, version, update;

  # Parse out the 'release' as the 'update' to match CPEs
  #  - Examples:
  #   - 18.4R2-S9   => cpe:/o:juniper:junos:18.4:r2-s9
  #   - 15.1X53-D25 => cpe:/o:juniper:junos:15.1x53:d25
  var pattern = '^([0-9]+\\.[0-9X]+)-?([A-WYZ][A-Z0-9.-]+)';
  var matches = pregmatch(string:ver, pattern:pattern, icase:TRUE);
  if (!empty_or_null(matches))
  {
    display_version = matches[0];
    version         = matches[1];
    update          = matches[2];
  }

  register_os(
    type       : type,
    method     : source,
    confidence : confidence,
    port       : port,

    vendor          : vendor,
    product         : product,
    version         : version,
    display_version : display_version,
    update          : update,
    os_name         : os_name,

    cpe : cpe
  );

  if (!empty_or_null(model))
  {
    var full_name = strcat(vendor, ' ', model);
    cpe = 'cpe:/h:juniper:' + model;

    register_hardware(
      type        : type,
      method      : source,
      confidence  : confidence,
      port        : port,

      category    : 'system',
      full_name   : full_name,
      vendor      : vendor,
      product     : model,

      serial_number : serial,

      cpe         : cpe
    );
  }

  security_report_v4(severity:SECURITY_NOTE, port:port, extra:report);

  exit(0);
}

var juniper_os = 'Juniper Junos ';

# 1. SSH

# Device like the SRX series can be clustered. If so, the have two nodes which are separate
# devices, but the SSH command outputs contain information for both nodes. The nodes are always
# named node0 and node1. Either can be "primary" or secondary - REF: CS-71588
# Determine which node we are on
var is_node_0 = FALSE;
var is_node_1 = FALSE;
var is_primary = FALSE;
var is_secondary = FALSE;
var cluster = FALSE;
var node_info = {};

var post_login_buf = get_kb_list('SSH/*/post_login_buffer');
var node_pat = "{(primary|secondary):(node0|node1)}";

# I can't say with certainty that the post_login_buffer KB item only ever appears once
# In theory, this should be fine even if there is more than one item, as one would assume
# that the banner will always be the same, regardless of session ID (because, same host)?
var item, val, node_match;
for (item in post_login_buf)
{
  val = post_login_buf[item];
  node_match = pregmatch(multiline:TRUE , pattern:node_pat , string:val);

  # Check if we are on primary or secondry node
  if (node_match[1] == 'primary')
  {
    is_primary = TRUE;
    node_info['node_status'] = 'Primary';
  }
  else if (node_match[1] ==  'secondary')
  {
    is_secondary = TRUE;
    node_info['node_status'] = 'Secondary';
  }

  # Check if we are on node0 oe node1
  if (node_match[2] == 'node0')
  {
    is_node_0 = TRUE;
    node_info['node_id'] = 'node0';
  }
  else if (node_match[2] == 'node1')
  {
    is_node_1 = TRUE;
    node_info['node_id'] = 'node1';
  }
}

var showver = get_kb_item("Host/Juniper/show_ver");

# If dealing with cluster, we only want the portion of the command outputs that are relevant to the node we are on
var split_output_pat = "(^node0:.*)(node1:.*$)";
var split_showver = pregmatch(multiline:TRUE, pattern:split_output_pat, string:showver);

var showver_node0, showver_node1;
if (split_showver[1] && split_showver[2])
{
  cluster = TRUE;

  if (split_showver[1] =~ "^node0")
  {
    showver_node0 = split_showver[1];
    if (is_node_0)
    {
      showver = showver_node0;
    }
  }
  if (split_showver[2] =~ "^node1")
  {
    showver_node1 = split_showver[2];
    if (is_node_1)
    {
      showver = showver_node1;
    }
  }
}

var register_junos_os = FALSE;

var model, junos, port, hardware_extensive, he_model, kernel, he_serial, serial,
report, desc, build, community, soc, device, ports, res, match, split_hardware_extensive;

if (showver)
{
  model = pregmatch(string:showver, pattern:'Model: +(.+)');
  junos = pregmatch(string:showver, pattern:'Junos: (.+)');
  port = 0; #SSH port is considered local

  hardware_extensive = get_kb_item("Host/Juniper/show_chassis_hardware_extensive");

  if (cluster)
  {
    split_hardware_extensive = pregmatch(pattern:split_output_pat, string:hardware_extensive, multiline:TRUE);
    if (split_hardware_extensive[1] && split_hardware_extensive[2])
    {
      if (is_node_0)
      {
        hardware_extensive = split_hardware_extensive[1];
      }
      if (is_node_1)
      {
        hardware_extensive = split_hardware_extensive[2];
      }
    }
  }

  if (!empty_or_null(hardware_extensive))
  {
    he_model = pregmatch(string:hardware_extensive, pattern:'FRU Model Number: +(.+)');
    if (!empty_or_null(he_model) && !empty_or_null(he_model[1]))
      model = he_model;

    # Grab chassis serial number
    he_serial = pregmatch(string:hardware_extensive, pattern:"Chassis\s+([A-Za-z0-9]+)\s");
    if(!empty_or_null(he_serial) && !empty_or_null(he_serial[1]))
    {
      serial = he_serial[1];
    }
  }

  # Get approximate Date of Build from Junos build version
  # example: MGD release 16.2R2-S1 built by builder on 2017-08-25 04:07:53 UTC
  if (junos)
  {
    kernel = pregmatch(string:showver, pattern:'(' + junos[1] + ') .+on ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) .+');
  }
  # Get Date ond approximate version of Build
  # example: KERNEL 16.2R2-S1 built by builder on 2019-18-18 12:01:53 UTC
  else
  {
    kernel = pregmatch(string:showver, pattern:'KERNEL ([^ ]+) .+on ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])');
  }

  if (model && kernel)
  {
    set_kb_item(name:"Host/Juniper/kernel", value:kernel[0]);
    junos_report_exit(ver:kernel[1], build:kernel[2], model:toupper(model[1]), source:'SSH', port:0, serial:serial, node_info:node_info);
  }
}

# 2. SNMP

desc = get_kb_item("SNMP/sysDesc");

if (desc)
{
  junos = pregmatch(string:desc, pattern:"JUNOS ([0-9.]+[^ ,]+)");
  build = pregmatch(string:desc, pattern:"Build date: ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])");

  # if the Junos version was obtained via SNMP, try to get the model as well
  if (junos && build)
  {
    community = get_kb_item_or_exit("SNMP/community");
    port = get_kb_item("SNMP/port");
    if(!port) port = 161;

    if (!get_udp_port_state(port)) exit(0, "UDP port "+port+" is not open.");
    soc = open_sock_udp(port);
    if (!soc) exit (0, "Failed to open a socket on port "+port+".");
    device = snmp_request(socket:soc, community:community, oid:"1.3.6.1.4.1.2636.3.1.2.0");
    close(soc);

    if (device)
    {
      # e.g. Juniper J2350 Internet Router
      model = pregmatch(string:device, pattern:"^Juniper ([^ ]+)");
      if (empty_or_null(model) && empty_or_null(model[1]))
        model[1] = 'n/a';
    }

    junos_report_exit(ver:junos[1], build:build[1], model:toupper(model[1]), source:'SNMP', port:port);

  }
}

# 3. NETCONF

if (get_kb_item('Host/netconf/junos'))
{
  var netconf_port = get_kb_item('Host/netconf/port');

  # try and get hardware model and firmware version from 'show versions' output.
  var versions = get_kb_item('Host/netconf/junos/versions');
  if (!empty_or_null(versions))
  {
    var version_check = pregmatch(pattern:"JUNOS: ([A-Z0-9\.-]+)(?:-S[0-9\.]+)?(?:\sFLEX)?",string:toupper(versions));
    var model_check   = pregmatch(pattern:'MODEL: ([A-Z]+)',string:toupper(versions));

    if (empty_or_null(version_check) && empty_or_null(version_check[1]))
      version_check[1] = 'n/a';

    if (empty_or_null(model_check) && empty_or_null(model_check[1]))
      model_check[1] = 'n/a';

    junos_report_exit(ver:toupper(version_check[1]), model:toupper(model_check[1]), source:'NETCONF', port:netconf_port);
  }
}

# 4. Web (only older versions allow us to view the version w/o authenticating)

var ui_ports = get_kb_list('Services/www');
if (isnull(ui_ports)) exit(0, 'The "Services/www" KB item is missing.');

foreach port (ui_ports)
{
  var http_cache = http_get_cache(port:port, item:'/', exit_on_fail:TRUE);
  if ('juniper networks' >!< tolower(http_cache) || 'juniper web device' >!< tolower(http_cache) || 'juniper.net' >!< tolower(http_cache))
  {
    dbg::detailed_log(lvl:2, msg:'No indication of Juniper was found in the web server\'s cache on port ' + port);
    continue;
  }

  res = http_send_recv3(method:'GET', item:'/login', port:port, exit_on_fail:TRUE);
  dbg::detailed_log(lvl:3, msg:'Request sent: ' + http_last_sent_request());
  dbg::detailed_log(lvl:3, msg:'Response recieved: ' + res[0] + res[1] + res[2]);
  # Parse for the model
  match = pregmatch(string:res[2], pattern:'<div class="jweb-title uppercase">.* - ([^<]+)</div>|\\.productVersion  = \'(.+)\'');
  if (!isnull(match))
  {
    if (!isnull(match[1])) model = toupper(match[1]);
    else model = toupper(match[2]);
  }
  # Parse for the version
  match = pregmatch(string:res[2], pattern:'src=\\"\\/extjs\\/ext-all\\.js\\?ver=([^"]+)\\"><\\/script>');
  if (!isnull(match) && !isnull(match[1]))
    junos = match[1];
  else if (!isnull(model))
  {
    # Final attempt to pull the version
    res = http_send_recv3(method:'GET', item:'/about', port:port, exit_on_fail:TRUE);
    dbg::detailed_log(lvl:3, msg:'Request sent: ' + http_last_sent_request());
    dbg::detailed_log(lvl:3, msg:'Response recieved: ' + res[0] + res[1] + res[2]);

    match = pregmatch(string:res[2], pattern:'Version (.+) *built by [^ ]+ on ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])');
    if (isnull(match))
    {
      junos = 'n/a';
      dbg::detailed_log(lvl:2, msg:'Unable to get Junos version from the web interface, authentication may be required.');
    }
    else
    {
      junos = match[1];
      build = match[2];
    }
  }

  junos_report_exit(ver:junos, build:build, model:toupper(model), source:'HTTP', port:port);
}

exit(0, "The Junos version is not available.");

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

13 Aug 2025 00:00Current
5.6Medium risk
Vulners AI Score5.6
143