Unix Software Discovery Command Checks

2021-08-23T00:00:00
ID UNIX_SOFTWARE_DISCOVERY_COMMAND_CHECKS.NASL
Type nessus
Reporter This script is Copyright (C) 2021 and is owned by Tenable, Inc. or an Affiliate thereof.
Modified 2021-08-23T00:00:00

Description

Nessus plugins run OS commands locally on the target host to discover and characterize software that is not managed by the target operating system. This plugin runs those commands over SSH to determine whether there is any problem that might prevent the successful discovery of unmanaged software installations.

Examples:
  find       cat       grep       ls

Problems that could interfere with the discovery of unmanaged software include scanning with weak permissions, incorrect chroot or sudo configuration, and missing or corrupt executables.

                                        
                                            #TRUSTED 0a7bf2bfb811d8d2be83955bb540a4999367ed85553fd063e8e71a1490c80f1004f61268c458e0ed6b41ae0d29510728c113417775abb1bf565b2c59db1d6a30c2badc45150a47dbf4b8c992788b51d0053d67d5734b0188221bec7c9ec6f55a37e5edffd133ee6193c593f55e7d273e3ac6034cc7b32162a12b980087a3f4865dfcd1a725c77d72fd57e9fc57238d1d965840393896ce05c07c04953d981827747c511547070132367d4a24846f185fb313f667f731e151de1de31b8f5b676adb8ba61666424b9fc33e78c671db96a95886a3c4a8471c15334a7b01db636ad9a169bbf23088ce0c79069a3af9c31b2e357ee2500986a3cd050c35708b6b1e3552faa77090bb11c66d60d1b76826cf80c9d2b1876b0a2bb78f76f3baf9281bcf3038351e1bfb7c5436a7b7c2b2eabd5ec1b1355af94a7fcd04890142d75a06bd8b9e0ceec23509a94c7a8b65a44fda8fe1e72d1108505fd86c8e1f28a058c40905daf68d733eace40a41ebc138d71b4ee2ca79203d665f1a7b75ee3ea2f542bd6af442b2f731470e5569c478cde3a13beb5a90abaa0664a0595c9a56edf0a12d59115ce942fcb5913777264d78a99e2266429b3ca3d21e2f6cbf8b7ff70b17e96bac0b9963a8f68ff5b02f9397bc076bfea27f1c2d886d399ff784e6340f2836b41c9c9cc0e29291a75b6e01bdf39bb1535b4b15c7e874e3fcc9842689c88ceb
#%NASL_MIN_LEVEL 70300

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

include('deprecated_nasl_level.inc');
include("compat.inc");

if (description)
{
  script_id(152741);
  script_version("1.2");
  script_set_attribute(attribute:"plugin_modification_date", value:"2021/08/23");

  script_name(english:"Unix Software Discovery Command Checks");
  script_summary(english:
"Checks commands used for software that is not managed by the OS.");
  script_set_attribute(attribute:"synopsis", value:
"Runs local commands over SSH that are used by plugins to find and
characterize software that is not managed by the operating system.");

  script_set_attribute(attribute:"description", value:
"Nessus plugins run OS commands locally on the target host to discover
and characterize software that is not managed by the target operating
system.  This plugin runs those commands over SSH to determine whether
there is any problem that might prevent the successful discovery of
unmanaged software installations.

    Examples:
      find
      cat
      grep
      ls

Problems that could interfere with the discovery of unmanaged
software include scanning with weak permissions, incorrect chroot or
sudo configuration, and missing or corrupt executables."
);

  script_set_attribute(attribute:"risk_factor", value:"None");
  script_set_attribute(attribute:"solution", value:"n/a");
  script_set_attribute(attribute:"agent", value:"unix");
  script_set_attribute(attribute:"plugin_publication_date", value:"2021/08/23");
  script_set_attribute(attribute:"plugin_type", value:"local");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"Misc.");

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

  script_dependencies("ssh_get_info2.nasl");
  script_require_ports("Host/FreeBSD/release", "Host/Solaris/Version", "Host/Solaris11/Version", "Host/AIX/version",
                       "Host/HP-UX/version", "Host/Linux", "Host/NetBSD/release", "Host/OpenBSD/release",
                       "Host/MacOSX/Version");

  script_require_keys("Host/uname");

  exit(0);
}

include("ssh_compat.inc");
include("ssh_lib.inc");
include("spad_log_func.inc");

##
# Tests the output of executing a command sequence against the
# expected result.
#
# Notes:  expect_error considers error output when exec mode is used.
#         In cases where the same pattern is used for both error and
#         command output, expect_error is set to TRUE.
##
function test_command(cmd, pattern, expect_error)
{
  if(isnull(cmd) || isnull(pattern))
    return FALSE;

  if(isnull(expect_error))
    expect_error = FALSE;

  var res = info_send_cmd(cmd:cmd);
  var err = sshlib::ssh_cmd_error_wrapper();
  sshlib::ssh_cmd_clear_error();

  #If the scan didn't use a shell handler and we expect an error
  if(expect_error && !res && err)
  {
    res = strip(err);
    err = NULL;
  }

  #Strip newlines in output. Output is split due to terminal width on some systems
  res = ereg_replace(string:res, pattern:"[\r\n]+", replace:"");

  if(res && preg(string:res, pattern:pattern, multiline:TRUE))
  {
    spad_log(message: "Successfully executed '" + cmd + "' on the target host and received the expected result '" + res + "'.");
    return TRUE;
  }

  spad_log(message: "Attempted to execute '" + cmd +
                    "', but received an unexpected result: '" + serialize(res) +
                    "' , error: '" + serialize(err) + "'.");

  var b64_cmd = base64(str:cmd);
  var b64_res = NULL;
  if(!isnull(res))
    b64_res = base64(str:res);

  if(isnull(b64_cmd))
    #Only one of these will ever get set, but it can help with debugging.
    replace_kb_item(name:"Host/unmanaged_software_checks/Failures/<error encoding command>", value:"<none>");
  else if(isnull(res) || isnull(b64_res))
    replace_kb_item(name:"Host/unmanaged_software_checks/Failures/" + b64_cmd, value:"<none>");
  else
    replace_kb_item(name:"Host/unmanaged_software_checks/Failures/" + b64_cmd, value:b64_res);

  return FALSE;
}

get_kb_item_or_exit("Host/uname");

if(!isnull(get_kb_item("Host/FreeBSD/release")) ||
   !isnull(get_kb_item("Host/NetBSD/release")) ||
   !isnull(get_kb_item("Host/OpenBSD/release")) ||
   !isnull(get_kb_item("Host/Linux")))
  host = "linux";

if(!isnull(get_kb_item("Host/Solaris/Version")) ||
   !isnull(get_kb_item("Host/Solaris11/Version")))
  host = "solaris";

if(!isnull(get_kb_item("Host/AIX/version")))
  host = "aix";

if(!isnull(get_kb_item("Host/HP-UX/version")))
  host = "hpux";

if(!isnull(get_kb_item("Host/MacOSX/Version")))
  host = "mac";

if(!host)
 audit(AUDIT_HOST_NOT, "Linux, Solaris, AIX, HP-UX or a known BSD distro");

if(sshlib::get_support_level() >= sshlib::SSH_LIB_SUPPORTS_COMMANDS)
  enable_ssh_wrappers();
else disable_ssh_wrappers();

info_connect(exit_on_fail:TRUE);

replace_kb_item(name:"Host/unmanaged_commands_supported", value:TRUE);

#################################
# find matching
#################################
find_expect = "\.";
find_expect_err = FALSE;
if(host == "hpux" || host == "solaris")
{
  find_expect = "find: bad option -maxdepth";
  find_expect_err = TRUE;
}
else if(host == "aix")
{
  find_expect = "find: [^\s]+ -maxdepth is not a valid option.";
  find_expect_err = TRUE;
}

#################################
# which matching
#################################
which_expect = "(/which|which \(\))|which: shell built-in";
which_expect_err = FALSE;
if(host == "mac")
{
  which_expect = NULL;
}

#################################
# cat matching
#################################
cat_expect = "(?:cat \(GNU coreutils\) [\d.]+|cat: illegal option --)";
cat_expect_err = TRUE;
if(host == "aix")
  cat_expect = "cat: Not a recognized flag: -";

#################################
# grep matching
#################################
grep_expect = "^(?:GNU )?grep(?: \((?:GNU|BSD) grep[^)]*\))? [\d.]{3}";
grep_expect_err = FALSE;
if(host == "aix")
{
  grep_expect = "grep: Not a recognized flag: V";
  grep_expect_err = TRUE;
}
else if(host == "solaris" || host == "hpux")
{
  grep_expect = "grep: illegal option -- V";
  grep_expect_err = TRUE;
}

#################################
# readlink matching
#################################
readlink_expect = "(?:readlink \(GNU coreutils\)|readlink: illegal option --)";
readlink_expect_err = TRUE;
if(host == "mac" || host == "solaris" || host == "aix" || host == "hpux")
  readlink_expect = NULL;

#################################
# unzip matching
#################################
unzip_expect = "(?:UnZip \d\.\d|Usage: unzip)";
unzip_expect_err = TRUE;
if(host == "mac" || host == "aix")
{
  unzip_expect = NULL;
}

#################################
# strings matching
#################################
strings_expect = "(?:GNU strings|strings \()";
strings_expect_err = TRUE;

if(host == "aix" || host == "hpux" || host == "solaris")
  strings_expect = "Usage: strings \[";
else if(host == "mac")
  strings_expect = NULL;

#################################

if(test_command(cmd:"find . -maxdepth 0 -type d", pattern:find_expect, expect_error: find_expect_err) &&
   test_command(cmd:"ls -d .", pattern:"\.", expect_error: FALSE) &&
   (isnull(which_expect) || test_command(cmd:"which which", pattern:which_expect, expect_error: which_expect_err)) &&
   test_command(cmd:"cat --version", pattern:cat_expect, expect_error:cat_expect_err) &&
   test_command(cmd:"grep -V", pattern:grep_expect, expect_error:grep_expect_err) &&
   (isnull(readlink_expect) || test_command(cmd:"readlink --version", pattern:readlink_expect, expect_error: readlink_expect_err)) &&
   (isnull(unzip_expect) || test_command(cmd:"unzip -v", pattern:unzip_expect, expect_error: unzip_expect_err)) &&
   (isnull(strings_expect) || test_command(cmd:"strings -v", pattern:strings_expect, expect_error: strings_expect_err)) &&
   (host != "mac" || (test_command(cmd:"plutil -help", pattern:"plutil: \[", expect_error:TRUE) &&
                      test_command(cmd:"sed -x", pattern:"sed: illegal option -- x", expect_error:TRUE) &&
                      test_command(cmd:"tail -x", pattern:"tail: illegal option -- x", expect_error:TRUE) &&
                      test_command(cmd:"awk", pattern:"usage: awk \[", expect_error:TRUE))))
{
  spad_log(message: "All unmanaged software commands ran and returned the expected result.");
  replace_kb_item(name:"Host/unmanaged_software_checks", value:TRUE);
}

if (info_t == INFO_SSH)
  ssh_close_connection();

exit(0, "This plugin does not report.");