Fix alert rule name stored XSS (#16443)

https://github.com/librenms/librenms/security/advisories/GHSA-7f84-28qh-9486
This commit is contained in:
Tony Murray
2024-09-29 07:42:21 -05:00
committed by GitHub
parent 0643bb5574
commit 7620d220e4

View File

@@ -199,14 +199,14 @@ foreach ($rule_list as $rule) {
if ((int) $sub['state'] === AlertState::CLEAR) { if ((int) $sub['state'] === AlertState::CLEAR) {
$ico = 'check'; $ico = 'check';
$col = 'success'; $col = 'success';
$status_msg = 'All devices matching ' . $rule['name'] . ' are OK'; $status_msg = 'All devices matching ' . htmlentities($rule['name']) . ' are OK';
} }
if ((int) $sub['state'] === AlertState::ACTIVE || (int) $sub['state'] === AlertState::ACKNOWLEDGED) { if ((int) $sub['state'] === AlertState::ACTIVE || (int) $sub['state'] === AlertState::ACKNOWLEDGED) {
$alert_style = alert_layout($severity); $alert_style = alert_layout($severity);
$ico = $alert_style['icon']; $ico = $alert_style['icon'];
$col = $alert_style['icon_color']; $col = $alert_style['icon_color'];
$extra = $alert_style['background_color']; $extra = $alert_style['background_color'];
$status_msg = 'Some devices matching ' . $rule['name'] . ' are currently alerting'; $status_msg = 'Some devices matching ' . htmlentities($rule['name']) . ' are currently alerting';
} }
} }
@@ -218,7 +218,7 @@ foreach ($rule_list as $rule) {
$ico = 'pause'; $ico = 'pause';
$col = ''; $col = '';
$extra = 'active'; $extra = 'active';
$status_msg = $rule['name'] . ' is OFF'; $status_msg = htmlentities($rule['name']) . ' is OFF';
} else { } else {
$alert_checked = 'checked'; $alert_checked = 'checked';
} }
@@ -261,7 +261,7 @@ foreach ($rule_list as $rule) {
// Name // Name
echo '<td><a href="' . url('alerts/rule_id='.$rule['id']) .'" data-container="body" data-toggle="popover" data-placement="right" data-content="View active alerts for this rule" target="_blank">' . $rule['name'] . '</a></td>'; echo '<td><a href="' . url('alerts/rule_id='.$rule['id']) .'" data-container="body" data-toggle="popover" data-placement="right" data-content="View active alerts for this rule" target="_blank">' . htmlentities($rule['name']) . '</a></td>';
// Devices (and Groups) // Devices (and Groups)
@@ -277,14 +277,12 @@ foreach ($rule_list as $rule) {
$except_device_or_group = '<strong><em>EXCEPT</em></strong> '; $except_device_or_group = '<strong><em>EXCEPT</em></strong> ';
} }
$popover_position = 'right';
$locations = null; $locations = null;
if ($location_count) { if ($location_count) {
$location_query = 'SELECT locations.location, locations.id FROM alert_location_map, locations WHERE alert_location_map.rule_id=? and alert_location_map.location_id = locations.id ORDER BY location'; $location_query = 'SELECT locations.location, locations.id FROM alert_location_map, locations WHERE alert_location_map.rule_id=? and alert_location_map.location_id = locations.id ORDER BY location';
$location_maps = dbFetchRows($location_query, [$rule['id']]); $location_maps = dbFetchRows($location_query, [$rule['id']]);
foreach ($location_maps as $location_map) { foreach ($location_maps as $location_map) {
$locations .= $except_device_or_group . '<a href="' . url('devices/location=' . $location_map['id']) . '" data-container="body" data-toggle="popover" data-placement="' . $popover_position . '" data-content="View Devices for Location" target="_blank">' . htmlentities($location_map['location']) . '</a><br>'; $locations .= $except_device_or_group . '<a href="' . url('devices/location=' . $location_map['id']) . '" data-container="body" data-toggle="popover" data-placement="right" data-content="View Devices for Location" target="_blank">' . htmlentities($location_map['location']) . '</a><br>';
} }
} }
@@ -293,7 +291,7 @@ foreach ($rule_list as $rule) {
$group_query = 'SELECT device_groups.name, device_groups.id FROM alert_group_map, device_groups WHERE alert_group_map.rule_id=? and alert_group_map.group_id = device_groups.id ORDER BY name'; $group_query = 'SELECT device_groups.name, device_groups.id FROM alert_group_map, device_groups WHERE alert_group_map.rule_id=? and alert_group_map.group_id = device_groups.id ORDER BY name';
$group_maps = dbFetchRows($group_query, [$rule['id']]); $group_maps = dbFetchRows($group_query, [$rule['id']]);
foreach ($group_maps as $group_map) { foreach ($group_maps as $group_map) {
$groups .= $except_device_or_group . '<a href="' . url('device-groups/' . $group_map['id'] . '/edit') . '" data-container="body" data-toggle="popover" data-placement="' . $popover_position . ' data-content="' . htmlentities($group_map['name']) . '" title="' . $groups_msg . '" target="_blank">' . htmlentities($group_map['name']) . '</a><br>'; $groups .= $except_device_or_group . '<a href="' . url('device-groups/' . $group_map['id'] . '/edit') . '" data-container="body" data-toggle="popover" data-placement="right" data-content="' . htmlentities($group_map['name']) . '" title="' . $groups_msg . '" target="_blank">' . htmlentities($group_map['name']) . '</a><br>';
} }
} }
@@ -302,7 +300,7 @@ foreach ($rule_list as $rule) {
$device_query = 'SELECT devices.device_id,devices.hostname FROM alert_device_map, devices WHERE alert_device_map.rule_id=? and alert_device_map.device_id = devices.device_id ORDER BY hostname'; $device_query = 'SELECT devices.device_id,devices.hostname FROM alert_device_map, devices WHERE alert_device_map.rule_id=? and alert_device_map.device_id = devices.device_id ORDER BY hostname';
$device_maps = dbFetchRows($device_query, [$rule['id']]); $device_maps = dbFetchRows($device_query, [$rule['id']]);
foreach ($device_maps as $device_map) { foreach ($device_maps as $device_map) {
$devices .= $except_device_or_group . '<a href="' . url('device/device=' . $device_map['device_id'] . '/tab=edit/') . '" data-container="body" data-toggle="popover" data-placement="' . $popover_position . '" data-content="' . htmlentities($device_map['hostname']) . '" title="' . $devices_msg . '" target="_blank">' . htmlentities(DeviceCache::get($device_map['device_id'])->displayName()) . '</a><br>'; $devices .= $except_device_or_group . '<a href="' . url('device/device=' . $device_map['device_id'] . '/tab=edit/') . '" data-container="body" data-toggle="popover" data-placement="right" data-content="' . htmlentities($device_map['hostname']) . '" title="' . $devices_msg . '" target="_blank">' . htmlentities(DeviceCache::get($device_map['device_id'])->displayName()) . '</a><br>';
} }
} }
@@ -318,7 +316,7 @@ foreach ($rule_list as $rule) {
} }
if (! $devices && ! $groups && ! $locations) { if (! $devices && ! $groups && ! $locations) {
// All Devices // All Devices
echo '<a href="' . url('devices') . '" data-container="body" data-toggle="popover" data-placement="' . $popover_position . '" data-content="View All Devices" target="_blank">All Devices</a><br>'; echo '<a href="' . url('devices') . '" data-container="body" data-toggle="popover" data-placement="right" data-content="View All Devices" target="_blank">All Devices</a><br>';
} }
echo '</td>'; echo '</td>';
@@ -380,7 +378,7 @@ foreach ($rule_list as $rule) {
echo '<i>' . htmlentities($rule_display) . '</i></td>'; echo '<i>' . htmlentities($rule_display) . '</i></td>';
// Severity // Severity
echo '<td>' . ($rule['severity'] == 'ok' ? strtoupper($rule['severity']) : ucwords($rule['severity'])) . '</td>'; echo '<td>' . htmlentities($rule['severity'] == 'ok' ? strtoupper($rule['severity']) : ucwords($rule['severity'])) . '</td>';
// Status // Status
@@ -388,10 +386,10 @@ foreach ($rule_list as $rule) {
echo "<td><a href=" . url('alerts/rule_id='.$rule['id']) ."><span data-toggle='popover' data-placement='$status_popover' data-content='$status_msg' id='alert-rule-" . $rule['id'] . "' class='fa fa-fw fa-2x fa-" . $ico . ' text-' . $col . "'></span></a>"; echo "<td><a href=" . url('alerts/rule_id='.$rule['id']) ."><span data-toggle='popover' data-placement='$status_popover' data-content='$status_msg' id='alert-rule-" . $rule['id'] . "' class='fa fa-fw fa-2x fa-" . $ico . ' text-' . $col . "'></span></a>";
if ($rule_extra['mute'] === true) { if ($rule_extra['mute'] === true) {
echo "<div data-toggle='popover' data-content='Alerts for " . $rule['name'] . " are muted' class='fa fa-fw fa-2x fa-volume-off text-primary' aria-hidden='true'></div>"; echo "<div data-toggle='popover' data-content='Alerts for " . htmlentities($rule['name']) . " are muted' class='fa fa-fw fa-2x fa-volume-off text-primary' aria-hidden='true'></div>";
} }
if ($sub['state'] == AlertState::ACKNOWLEDGED) { if ($sub['state'] == AlertState::ACKNOWLEDGED) {
echo "<div data-toggle='popover' data-content='Some Alerts for " . $rule['name'] . " are acknowledged' class='fa fa-fw fa-2x fa-sticky-note text-info' aria-hidden='true'></div>"; echo "<div data-toggle='popover' data-content='Some Alerts for " . htmlentities($rule['name']) . " are acknowledged' class='fa fa-fw fa-2x fa-sticky-note text-info' aria-hidden='true'></div>";
} }
echo '</td>'; echo '</td>';
// Enabled // Enabled
@@ -400,25 +398,23 @@ foreach ($rule_list as $rule) {
echo '<td>'; echo '<td>';
if ($rule['disabled']) { if ($rule['disabled']) {
$enabled_msg = $rule['name'] . ' is OFF'; $enabled_msg = htmlentities($rule['name']) . ' is OFF';
} }
if (! $rule['disabled']) { if (! $rule['disabled']) {
$enabled_msg = $rule['name'] . ' is ON'; $enabled_msg = htmlentities($rule['name']) . ' is ON';
} }
echo "<div id='on-off-checkbox-" . $rule['id'] . "' data-toggle='popover' data-placement='$enabled_popover' data-content='" . $enabled_msg . "' class='btn-group btn-group-sm' role='group'>"; echo "<div id='on-off-checkbox-" . $rule['id'] . "' data-toggle='popover' data-placement='$enabled_popover' data-content='" . $enabled_msg . "' class='btn-group btn-group-sm' role='group'>";
echo "<input id='" . $rule['id'] . "' type='checkbox' name='alert-rule' data-orig_class='" . $orig_class . "' data-orig_colour='" . $orig_col . "' data-orig_state='" . $orig_ico . "' data-alert_id='" . $rule['id'] . "' data-alert_name='" . $rule['name'] . "' data-alert_status='" . $status_msg . "' " . $alert_checked . " data-size='small' data-toggle='modal'>"; echo "<input id='" . $rule['id'] . "' type='checkbox' name='alert-rule' data-orig_class='" . $orig_class . "' data-orig_colour='" . $orig_col . "' data-orig_state='" . $orig_ico . "' data-alert_id='" . $rule['id'] . "' data-alert_name='" . htmlentities($rule['name']) . "' data-alert_status='" . $status_msg . "' " . $alert_checked . " data-size='small' data-toggle='modal'>";
echo '</div>'; echo '</div>';
echo '</td>'; echo '</td>';
// Action // Action
$action_popover = 'left';
echo '<td>'; echo '<td>';
echo "<div class='btn-group btn-group-sm' role='group'>"; echo "<div class='btn-group btn-group-sm' role='group'>";
echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-placement='$action_popover' data-target='#create-alert' data-rule_id='" . $rule['id'] . "' name='edit-alert-rule' data-content='Edit alert rule " . $rule['name'] . "' data-container='body'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> "; echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-placement='left' data-target='#create-alert' data-rule_id='" . $rule['id'] . "' name='edit-alert-rule' title='Edit alert rule' data-content='" . htmlentities($rule['name']) . "' data-container='body'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> ";
echo "<button type='button' class='btn btn-danger' aria-label='Delete' data-placement='$action_popover' data-toggle='modal' data-target='#confirm-delete' data-alert_id='" . $rule['id'] . "' data-alert_name='" . $rule['name'] . "' name='delete-alert-rule' data-content='Delete alert rule " . $rule['name'] . "' data-container='body'><i class='fa fa-lg fa-trash' aria-hidden='true'></i></button>"; echo "<button type='button' class='btn btn-danger' aria-label='Delete' data-placement='left' data-toggle='modal' data-target='#confirm-delete' data-alert_id='" . $rule['id'] . "' data-alert_name='" . htmlentities($rule['name']) . "' name='delete-alert-rule' title='Delete alert rule' data-content='" . htmlentities($rule['name']) . "' data-container='body'><i class='fa fa-lg fa-trash' aria-hidden='true'></i></button>";
echo '</td>'; echo '</td>';
echo "</tr>\r\n"; echo "</tr>\r\n";