Skip to content

Insecure deserialization of filter data

Moderate
netniV published GHSA-77rf-774j-6h3p Sep 5, 2023

Package

Cacti (PHP)

Affected versions

< 1.2.25

Patched versions

1.2.25, 1.3.0

Description

Summary

There are two instances of insecure deserialization in Cacti version 1.2.24. While a viable gadget chain exists in Cacti’s vendor directory (phpseclib), the necessary gadgets are not included, making them inaccessible and the insecure deserializations not exploitable.

Details

Each instance of insecure deserialization is due to using the unserialize function without sanitizing the user input. Cacti has a “safe” deserialization that attempts to sanitize the content and check for specific values before calling unserialize, but it isn’t used in these instances.

In graphs_new.php

The vulnerable code lies in graphs_new.php, specifically within the host_new_graphs_save function. The following code is taken from the beginning of the function in Cacti 1.2.10:

function host_new_graphs_save($host_id) {
        $selected_graphs_array = unserialize(stripslashes(get_nfilter_request_var('selected_graphs_array')));
        $values = array();

This function unserializes the user controlled parameter ‘selected_graphs_array’. While stripslashes is run first, this simply removes extra slashes that are needed in strings during pre-processing (e.g. &rdquo; to “). In order to reach this function, the user makes a request to graphs_new with two parameters: action=save and save_component_new_graphs, which causes the vulnerable function to be called, as shown in the two code snippets below:

switch (get_request_var('action')) {
        case 'save':
            form_save();
            break;
        case 'query_reload':
            ...
        ...
        ...
function form_save() {
	...
        ...
	...
	if (isset_request_var('save_component_new_graphs')) {
		host_new_graphs_save(get_filter_request_var('host_id'));

		header('Location: graphs_new.php?host_id=' . get_filter_request_var('host_id') . &header=false');
	}
}

In managers.php

The vulnerable code lies in managers.php, specifically within the form_actions function. The following code is extracted from the function in Cacti 1.2.10:

function form_actions() {
	global $manager_actions, $manager_notification_actions;
	
	if (isset_request_var('selected_items')) {
		if (isset_request_var('action_receivers')) {
			...
			...
			...
		} elseif (isset_request_var('action_receiver_notifications')) {
			get_filter_request_var('id');
			$selected_items = unserialize(stripslashes(get_nfilter_request_var('selected_items')));
			...
		}
	...
}

By setting the request variable action_receiver_notifications, we can control the code flow to hit the unserialize call in form_actions. In order to reach form_actions, we need to set the action variable to actions, as shown in the extracted code snippet below:

switch (get_request_var('action')) {
	case 'save':
		form_save();
		break;
	case 'actions':
		form_actions();
		break;
	...
	...
}

PoC

In graphs_new.php

To hit the vulnerable code, an authenticated user sends a POST request that looks like the following:
graphs_new_example_request
If we put an invalid object (e.g. one that is malformed or includes a class Cacti does not know about) as the value for the selected_graphs_array, we can see Cacti attempting to unserialize the payload in the logs:
graphs_new_unserialize_error
At this point, we can easily control code flow to call unserialize on an arbitrary injected object.

In managers.php

To hit the vulnerable code, an authenticated user sends a POST request that looks like the following:
managers_example_request
If we put an invalid object (e.g. one that is malformed or includes a class Cacti does not know about) as the value for the selected_graphs_array, we can see Cacti attempting to unserialize the payload in the logs:
managers_unserialize_error

At this point, we can easily control code flow to call unserialize on an arbitrary injected object.

Impact

Searching for Gadget Chains

There is one known usable gadget chain in Cacti’s PHP vendors, PHPSecLib. However, Cacti does not require or include any of the necessary php files that are needed in order to use the PHPSecLib gadget. Thus, these deserialization vulnerabilities can not be exploited in a vanilla installation of Cacti.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

CVE ID

CVE-2023-30534

Weaknesses

Credits