CVE-2023-49926: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: app/Lib/Tools/EventTimelineTool.php in MISP before 2.4.179 allows XSS in the event timeline widget.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-12-03T03:15Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Lib/Tools/EventTimelineTool.php
Commit date: 2023-11-22 14:38:03 +0100
Commit message: security: [event:event-timeline] Fixed XSS in the event timeline widget

As reported by fukusuket(Fukusuke Takahashi)

Diff: diff --git a/app/Lib/Tools/EventTimelineTool.php b/app/Lib/Tools/EventTimelineTool.php
index d684d888296..fe20b183ade 100644
--- a/app/Lib/Tools/EventTimelineTool.php
+++ b/app/Lib/Tools/EventTimelineTool.php
@@ -95,11 +95,11 @@
             // extract links and node type
             foreach ($attribute as $attr) {
                 $toPush = array(
                     'id' => $attr['id'],
                     'uuid' => $attr['uuid'],
-                    'content' => $attr['value'],
+                    'content' => h($attr['value']),
                     'event_id' => $attr['event_id'],
                     'group' => 'attribute',
                     'timestamp' => $attr['timestamp'],
                     'first_seen' => $attr['first_seen'],
                     'last_seen' => $attr['last_seen'],
@@ -112,13 +112,13 @@
 
             foreach ($object as $obj) {
                 $toPush_obj = array(
                     'id' => $obj['id'],
                     'uuid' => $obj['uuid'],
-                    'content' => $obj['name'],
+                    'content' => h($obj['name']),
                     'group' => 'object',
-                    'meta-category' => $obj['meta-category'],
+                    'meta-category' => h($obj['meta-category']),
                     'template_uuid' => $obj['template_uuid'],
                     'event_id' => $obj['event_id'],
                     'timestamp' => $obj['timestamp'],
                     'Attribute' => array(),
                 );
@@ -138,12 +138,12 @@
                         $toPush_obj['last_seen_overwrite'] = true;
                     }
                     $toPush_attr = array(
                         'id' => $obj_attr['id'],
                         'uuid' => $obj_attr['uuid'],
-                        'content' => $obj_attr['value'],
-                        'contentType' => $obj_attr['object_relation'],
+                        'content' => h($obj_attr['value']),
+                        'contentType' => h($obj_attr['object_relation']),
                         'event_id' => $obj_attr['event_id'],
                         'group' => 'object_attribute',
                         'timestamp' => $obj_attr['timestamp'],
                         'attribute_type' => $obj_attr['type'],
                         'date_sighting' => $sightingsAttributeMap[$attr['id']] ?? [],
@@ -204,11 +204,11 @@
                     if ($fpSightingIndex === false) { // No next FP, extrapolate to now
                         $this->__json['items'][] = array(
                             'attribute_id' => $attributeId,
                             'id' => sprintf('%s-%s', $attributeId, $sighting['id']),
                             'uuid' => $sighting['uuid'],
-                            'content' => $attribute['value'],
+                            'content' => h($attribute['value']),
                             'event_id' => $attribute['event_id'],
                             'group' => $group,
                             'timestamp' => $attribute['timestamp'],
                             'first_seen' => $sighting['date_sighting'],
                             'last_seen' => $now,
@@ -233,11 +233,11 @@
                         }
                         $this->__json['items'][] = array(
                             'attribute_id' => $attributeId,
                             'id' => sprintf('%s-%s', $attributeId, $sighting['id']),
                             'uuid' => $sighting['uuid'],
-                            'content' => $attribute['value'],
+                            'content' => h($attribute['value']),
                             'event_id' => $attribute['event_id'],
                             'group' => 'sighting_positive',
                             'timestamp' => $attribute['timestamp'],
                             'first_seen' => $sighting['date_sighting'],
                             'last_seen' => $lastSeenPositive,
@@ -253,11 +253,11 @@
                             }
                             $this->__json['items'][] = array(
                                 'attribute_id' => $attributeId,
                                 'id' => sprintf('%s-%s', $attributeId, $sighting['id']),
                                 'uuid' => $fpSighting['uuid'],
-                                'content' => $attribute['value'],
+                                'content' => h($attribute['value']),
                                 'event_id' => $attribute['event_id'],
                                 'group' => 'sighting_negative',
                                 'timestamp' => $attribute['timestamp'],
                                 'first_seen' => $firstSeenNegative,
                                 'last_seen' => $now,
@@ -277,11 +277,11 @@
                             $secondNextPSighting = $sightings[$secondNextPSightingIndex];
                             $this->__json['items'][] = array(
                                 'attribute_id' => $attributeId,
                                 'id' => sprintf('%s-%s', $attributeId, $sighting['id']),
                                 'uuid' => $fpSighting['uuid'],
-                                'content' => $attribute['value'],
+                                'content' => h($attribute['value']),
                                 'event_id' => $attribute['event_id'],
                                 'group' => 'sighting_negative',
                                 'timestamp' => $attribute['timestamp'],
                                 'first_seen' => $firstSeenNegative,
                                 'last_seen' => $secondNextPSighting['date_sighting'],

Vulnerable code:                     'content' => $attr['value'],
                    'content' => $obj['name'],
                    'meta-category' => $obj['meta-category'],
                        'content' => $obj_attr['value'],
                        'contentType' => $obj_attr['object_relation'],
                            'content' => $attribute['value'],
                            'content' => $attribute['value'],
                                'content' => $attribute['value'],
                                'content' => $attribute['value'],
Fixed code:                     'content' => h($attr['value']),
                    'content' => h($obj['name']),
                    'meta-category' => h($obj['meta-category']),
                        'content' => h($obj_attr['value']),
                        'contentType' => h($obj_attr['object_relation']),
                            'content' => h($attribute['value']),
                            'content' => h($attribute['value']),
                                'content' => h($attribute['value']),
                                'content' => h($attribute['value']),