CVE-2024-25675: Insufficient Information (NVD-CWE-noinfo)
value: An issue was discovered in MISP before 2.4.184. A client does not need to use POST to start an export generation process. This is related to app/Controller/JobsController.php and app/View/Events/export.ctp.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2024-02-09T09:15Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Controller/JobsController.php, app/View/Events/export.ctp
Commit date: 2024-01-31 14:24:17 +0100
Commit message: fix: [security] Enforce usage of POST to start an export generation process

As reported by Andrei Agape / Teliacompany

Diff: diff --git a/app/Controller/JobsController.php b/app/Controller/JobsController.php
index 6c0f238a531..1e712ce56c9 100644
--- a/app/Controller/JobsController.php
+++ b/app/Controller/JobsController.php
@@ -152,10 +152,13 @@ class JobsController extends AppController
     public function cache($type)
     {
         if (Configure::read('MISP.disable_cached_exports')) {
             throw new MethodNotAllowedException('This feature is currently disabled');
         }
+        if (!$this->request->is('post')) {
+            throw new MethodNotAllowedException('This endpoint only accept POST.');
+        }
         if ($this->_isSiteAdmin()) {
             $target = 'All events.';
         } else {
             $target = 'Events visible to: ' . $this->Auth->user('Organisation')['name'];
         }
diff --git a/app/View/Events/export.ctp b/app/View/Events/export.ctp
index 60e29ed7993..2e793858af9 100755
--- a/app/View/Events/export.ctp
+++ b/app/View/Events/export.ctp
@@ -112,19 +112,20 @@
                 if ($background) {
                     $cells[] = sprintf(
                         '<td><span class="btn-group">%s%s</span></td>',
                         ($k === 'text') ? '' : $this->Html->link(__('Download'), array('action' => 'downloadExport', $k), array('class' => 'btn btn-inverse btn-small')),
                         sprintf(
-                            '<button class="btn btn-inverse btn-small" id=button%s onClick="generate(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\')" %s>%s</button>',
+                            '<button class="btn btn-inverse btn-small" id=button%s onClick="generate(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\')" %s>%s</button><div class="hidden">%s</div>',
                             $i,
                             h($i),
                             h($k),
                             h($type['job_id']),
                             h($type['progress']),
                             h($type['lastModified']),
                             (!$type['recommendation']) ? 'disabled' : '',
-                            __('Generate')
+                            __('Generate'),
+                            $this->Form->postLink(__('Download'), array('controller' => 'jobs', 'action' => 'cache', h($k)), array('class' => 'btn btn-inverse btn-small')),
                         )
                     );
                 } else {
                     $params = array();
                     foreach ($type['params'] as $param => $param_value) {
@@ -172,12 +173,16 @@
 <?php
     echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event-collection', 'menuItem' => 'export'));
 ?>
 <script type="text/javascript">
     function generate(i, type, id, progress, modified) {
+        var $clicked = $('#button'+i)
+        var $form = $clicked.next().find('form')
         $.ajax({
-            url: "<?php echo $baseurl; ?>/jobs/cache/" + type,
+            url: $form.attr('action'),
+            type:'post',
+            data: $form.serialize()
             })
             .done(function(data) {
                 jobsArray[i] = data;
                 editMessage(i, "Adding...");
                 queueInterval(i, type, data, 1, "Just now");

Vulnerable code:                             '<button class="btn btn-inverse btn-small" id=button%s onClick="generate(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\')" %s>%s</button>',
                            __('Generate')
            url: "<?php echo $baseurl; ?>/jobs/cache/" + type,
Fixed code:         if (!$this->request->is('post')) {
            throw new MethodNotAllowedException('This endpoint only accept POST.');
        }
                            '<button class="btn btn-inverse btn-small" id=button%s onClick="generate(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\')" %s>%s</button><div class="hidden">%s</div>',
                            __('Generate'),
                            $this->Form->postLink(__('Download'), array('controller' => 'jobs', 'action' => 'cache', h($k)), array('class' => 'btn btn-inverse btn-small')),
        var $clicked = $('#button'+i)
        var $form = $clicked.next().find('form')
            url: $form.attr('action'),
            type:'post',
            data: $form.serialize()