Summary
In Cacti 1.2.24, users with console access can be redirected to an arbitrary website after a change password performed via a specifically crafted URL.
Details
The auth_changepassword.php
file accepts ref
as a URL parameter and reflects it in the form used to perform the change password. It's value is used to perform a redirect via header
PHP function.
// ...
/* ok, at the point the user has been successfully authenticated; so we must decide what to do next */
/* if no console permissions show graphs otherwise, pay attention to user setting */
$realm_id = $user_auth_realm_filenames['index.php'];
$has_console = db_fetch_cell_prepared('SELECT realm_id
FROM user_auth_realm
WHERE user_id = ? AND realm_id = ?',
array($user_id, $realm_id));
if (basename(get_nfilter_request_var('ref')) == 'auth_changepassword.php' || basename(get_nfilter_request_var('ref')) == '') {
if ($has_console) {
set_request_var('ref', 'index.php');
} else {
set_request_var('ref', 'graph_view.php');
}
}
if (!empty($has_console)) {
switch ($user['login_opts']) {
case '1': /* referer */
header('Location: ' . sanitize_uri(get_nfilter_request_var('ref'))); break;
case '2': /* default console page */
header('Location: index.php'); break;
case '3': /* default graph page */
header('Location: graph_view.php'); break;
default:
api_plugin_hook_function('login_options_navigate', $user['login_opts']);
}
} else {
header('Location: graph_view.php');
}
exit;
// ...
<body class='loginBody'>
<div class='loginLeft'></div>
<div class='loginCenter'>
<div class='loginArea'>
<div class='cactiLogoutLogo'></div>
<legend><?php print __('Change Password');?></legend>
<form name='login' method='post' action='<?php print get_current_page();?>'>
<input type='hidden' name='action' value='changepassword'>
<input type='hidden' name='ref' value='<?php print html_escape(get_request_var('ref')); ?>'>
// ...
Two functions are involved after the POST, but:
- The
sanitize_uri
function, defined into functions.php
, only cleans up a URI in case of XSS attack.
- The
get_nfilter_request_var
function, defined into html_utility.php
, returns the value of the request variable deferring any filtering.
No checks are performed to understand if ref
is an internal URL or not.
An arbitrary value of ref
is sufficient to bypass the first if
clause.
To reach the sink in the second if
clause, two conditions must be true:
- The user has "Console Access" in its "Permissions", i.e.
!empty($has_console)
.
- The "Login Options" (
$user['login_opts']
) of the user are set to "Show the page that user pointed their browser to." (case '1'
), but this is the default behavior as can be verified in the cacti.sql
file.
-- ...
CREATE TABLE user_auth (
-- ...
`login_opts` tinyint(3) unsigned NOT NULL default '1',
-- ...
PoC
Prerequisites:
- The target user has "Console Access" in its "Permissions".
- The "Login Options" of the target user are set to "Show the page that user pointed their browser to.".
- Target user is tricked in performing the change password.
Exploit:
Send to the target user a link like the following.
https://<cacti_installation>/auth_changepassword.php?ref=https://<malicious_website>
After the change password operation, the browser will be redirected to the malicious website.
Impact
A naive user can be tricked in performing the change password operation, e.g., via a phishing message, and then interacting with the malicious website where the redirection has been performed, e.g., downloading malwares, providing credentials, etc.
Summary
In Cacti 1.2.24, users with console access can be redirected to an arbitrary website after a change password performed via a specifically crafted URL.
Details
The
auth_changepassword.php
file acceptsref
as a URL parameter and reflects it in the form used to perform the change password. It's value is used to perform a redirect viaheader
PHP function.Two functions are involved after the POST, but:
sanitize_uri
function, defined intofunctions.php
, only cleans up a URI in case of XSS attack.get_nfilter_request_var
function, defined intohtml_utility.php
, returns the value of the request variable deferring any filtering.No checks are performed to understand if
ref
is an internal URL or not.An arbitrary value of
ref
is sufficient to bypass the firstif
clause.To reach the sink in the second
if
clause, two conditions must be true:!empty($has_console)
.$user['login_opts']
) of the user are set to "Show the page that user pointed their browser to." (case '1'
), but this is the default behavior as can be verified in thecacti.sql
file.PoC
Prerequisites:
Exploit:
Send to the target user a link like the following.
After the change password operation, the browser will be redirected to the malicious website.
Impact
A naive user can be tricked in performing the change password operation, e.g., via a phishing message, and then interacting with the malicious website where the redirection has been performed, e.g., downloading malwares, providing credentials, etc.