SSHD libkeyutils Backdoor

2013-02-27T00:00:00
ID SSHD_LIBKEYUTILS_BACKDOOR.NASL
Type nessus
Reporter Tenable
Modified 2017-05-30T00:00:00

Description

The remote host appears to contain a trojaned libkeyutils library. The trojaned library links to SSHD, steals credentials, and sends spam.

                                        
                                            #TRUSTED 6d60fc631687738fb04e42efdbe873a62b7f04a48813d72f093f9708a0f278ace4a2bd7d8a3ce1ed97ee928b1d14b9d2104aff1680b14ca3ddc68d3174a8a8d290e11aa7bbb544b13f568e414d6109079cb11fde4cdb1133ae4f56308a0c1b4973cf68229a59ddf312ab2e32b74aa656a5bedcd5c0def891517c57d56a6a5aae8ca6e7a6e1cf6b13fc53e8a8d02216825bce7d8c94cd87955724efd54c3e6739dcb2eaa4bd451db5672eedb2dabdcb23b0b1c383a5569c8a1d9a3ed817dfda0a6c83166107c20f0415b65667ac64473ee16f4a04efa42b22f51426223003c7c7d79f4a81a52d027292e3ddf7da3814aefccd8b15559c56b522a423f325e2b482dbaaa5e6cd90a3e2f94872eb9b303a5f1acd9d0786ed82a4bcec13b0d727a2266a3231d6a5c9e15c2a4ed98cb8f676d28967ed4a755c652b482dd2ac4fe4488ea057b5a6c3b4c2364638d2aeed1fd76a472b461c942066e5db05a403149bb39d198c3ac87b2eaba99a8158d32b006e8b1b46e7b01ed08dee46e7a6be2d4d75da2cf0530b54feb2a3bc8c972bd12dacfd34185bda094d881a4f30929bea101f204d3557fe6ef779586d07af7c68ea8f6e97d1f6ae50d4b2a9f9e0f2d45170f1231dc64b9493ed5f45dacf24873e34e8db006404633bb31a093150aa8b7024aec4e9a0683c82ccc2b87423b9452d4479ac9bec98f08f754c1f698e1c881323304f
#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(64913);
  script_version("1.3");
  script_set_attribute(attribute:"plugin_modification_date", value:"2017/05/30");

  script_name(english:"SSHD libkeyutils Backdoor");
  script_summary(english:"Checks for evidence of a libkeyutils library being trojaned");

  script_set_attribute(
    attribute:"synopsis",
    value:"The remote host may be compromised."
  );
  script_set_attribute(
    attribute:"description",
    value:
"The remote host appears to contain a trojaned libkeyutils library.  The
trojaned library links to SSHD, steals credentials, and sends spam."
  );
  script_set_attribute(attribute:"see_also", value:"http://www.webhostingtalk.com/showthread.php?t=1235797");
  # http://blog.solidshellsecurity.com/2013/02/18/0day-linuxcentos-sshd-spam-exploit-libkeyutils-so-1-9/
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?f62cb60d");
  # http://contagiodump.blogspot.com/2013/02/linuxcentos-sshd-spam-exploit.html
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?b03816df");
  # https://isc.sans.edu/diary/SSHD%20rootkit%20in%20the%20wild/15229
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?4958f5dd");
  script_set_attribute(attribute:"see_also", value:"http://www.webhostingtalk.com/showpost.php?p=8563741&postcount=284");
  script_set_attribute(
    attribute:"solution",
    value:
"Verify whether or not the system has been compromised.  Restore from
known good backups and investigate the network for further signs of a
compromise, if necessary."
  );
  script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:C/I:C/A:C");

  script_set_attribute(attribute:"plugin_publication_date", value:"2013/02/27");

  script_set_attribute(attribute:"plugin_type", value:"local");
  script_end_attributes();

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

  script_copyright(english:"This script is Copyright (C) 2013-2017 Tenable Network Security, Inc.");

  script_dependencies("ssh_get_info.nasl");
  script_require_keys("Host/local_checks_enabled");

  exit(0);
}

include("audit.inc");
include("global_settings.inc");
include("misc_func.inc");
include("telnet_func.inc");
include("ssh_func.inc");
include("hostlevel_funcs.inc");


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

if (!get_kb_item("Host/local_checks_enabled"))
  audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);

# public reports indicate only RPM-based distros have been infected
rpm_list = get_kb_list_or_exit('Host/*/rpm-list');
rpm_list = make_list(rpm_list);
rpm_list = split(rpm_list[0], sep:'\n', keep:FALSE);

keyutils_rpms = make_list();

foreach line (rpm_list)
{
  fields = split(line, sep:'|', keep:FALSE);
  rpm = fields[0];
  if (rpm =~ "^keyutils-libs-\d")
    keyutils_rpms = make_list(keyutils_rpms, rpm);
}

if (max_index(keyutils_rpms) == 0)
  audit(AUDIT_NOT_INST, 'keyutils-libs');

# initialization required for using info_send_cmd()
if (islocalhost())
{
  if (!defined_func("pread")) audit(AUDIT_FN_UNDEF, 'pread');
  info_t = INFO_LOCAL;
}
else
{
  sock_g = ssh_open_connection();
  if (!sock_g) audit(AUDIT_FN_FAIL, 'ssh_open_connection');
  info_t = INFO_SSH;
}

affected_files = make_array();
rpm_verify = make_array();

foreach rpm (keyutils_rpms)
{
  # verify the files in the rpm package
  rpm_cmd = '/bin/rpm -Vv ' + rpm;
  rpm_output = info_send_cmd(cmd:rpm_cmd);
  output_lines = split(rpm_output, sep:'\n', keep:FALSE);

  foreach line (output_lines)
  {
    # determine if the size and md5sum of any library files have changed
    match = eregmatch(string:line, pattern:"^S.5......\s+(/lib(64)?/libkeyutils.+)$");
    file = match[1];
    if (isnull(file)) continue;

    # if so, check if the file contains the encoded IP address associated with this backdoor.
    # the string below is 78.47.139.110 - each byte is xor'd with 0x81
    encoded_ip = "\xb6\xb9\xaf\xb5\xb6\xaf\xb0\xb2\xb8\xaf\xb0\xb0\xb1";
    cmd = "/bin/grep -P '" + encoded_ip + "' " + file + ' &> /dev/null ; /bin/echo $?';
    results = info_send_cmd(cmd:cmd);

    if (chomp(results) == '0') # avoid false negatives by checking the exit status
    {
      affected_files[file] = cmd;
      rpm_verify[rpm_cmd] = rpm_output;
    }
  }
}

ssh_close_connection();

if (max_index(keys(affected_files)) == 0)
  audit(AUDIT_HOST_NOT, 'affected');

if (report_verbosity > 0)
{
  if (max_index(keys(affected_files)) == 1)
    s = ' appears';
  else
    s = 's appear';

  report =
    '\nThe following file' + s + ' to contain backdoor code :\n\n' +
    join(sort(keys(affected_files)), sep:'\n') +'\n\n' +
    'This was determined by verifying any libkeyutils RPM packages :\n\n' +
    join(sort(keys(rpm_verify)), sep:'\n') + '\n\n' +
    join(sort(make_list(rpm_output)), sep:'\n') + '\n' +
    'And checking if any modified library files contain a string which\n' +
    'can be decoded to "78.47.139.110" (an IP address associated with the\n' +
    'backdoor) :\n\n';
  foreach key (sort(keys(affected_files)))
    report += affected_files[key] + '\n';

  security_hole(port:0, extra:report);
}
else security_hole(0);