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.phpfile acceptsrefas a URL parameter and reflects it in the form used to perform the change password. It's value is used to perform a redirect viaheaderPHP function.Two functions are involved after the POST, but:
sanitize_urifunction, defined intofunctions.php, only cleans up a URI in case of XSS attack.get_nfilter_request_varfunction, defined intohtml_utility.php, returns the value of the request variable deferring any filtering.No checks are performed to understand if
refis an internal URL or not.An arbitrary value of
refis sufficient to bypass the firstifclause.To reach the sink in the second
ifclause, 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.sqlfile.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.