CVE-2020-11458: Insufficient Information (NVD-CWE-noinfo)
value: app/Model/feed.php in MISP before 2.4.124 allows administrators to choose arbitrary files that should be ingested by MISP. This does not cause a leak of the full contents of a file, but does cause a leaks of strings that match certain patterns. Among the data that can leak are passwords from database.php or GPG key passphrases from config.php.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 4.9
Published: 2020-04-02T12:15Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Controller/FeedsController.php, app/Model/Feed.php, app/Model/Server.php, app/View/Feeds/add.ctp, app/View/Feeds/edit.ctp
Commit date: 2020-03-30 14:02:14 +0200
Commit message: chg: [security] Added setting to restrict the encoding of local feeds

- By adding local feeds, a malicious administrator could point MISP to ingest configuration files that the apache user has access to
- This includes some more sensitive files (database.php / config.php / .gnupg data)
- Whilst this is currently not leading to an exploitable vulnerability as the current implementation wouldn't trigger on the values,
  having a setting to disable this will become much more interesting once we have a system in place for custom feed parsers
- The setting can only be enabled/disabled via the CLI

- As reported by Matthias Weckbecker

Diff: diff --git a/app/Controller/FeedsController.php b/app/Controller/FeedsController.php
index c9b214dc663..fe8c5e0305b 100644
--- a/app/Controller/FeedsController.php
+++ b/app/Controller/FeedsController.php
@@ -244,11 +244,11 @@ class FeedsController extends AppController
                         return $this->RestResponse->viewData($feed, $this->response->type());
                     }
                     $this->Flash->success($message);
                     $this->redirect(array('controller' => 'feeds', 'action' => 'index'));
                 } else {
-                    $message = __('Feed could not be added. Invalid field: %s', array_keys($this->Feed->validationErrors)[0]);
+                    $message = __('Feed could not be added. Reason: %s', json_encode($this->Feed->validationErrors));
                     if ($this->_isRest()) {
                         return $this->RestResponse->saveFailResponse('Feeds', 'add', false, $message, $this->response->type());
                     }
                     $this->Flash->error($message);
                     $this->request->data['Feed']['settings'] = json_decode($this->request->data['Feed']['settings'], true);
@@ -343,11 +343,11 @@ class FeedsController extends AppController
                     return $this->RestResponse->viewData($feed, $this->response->type());
                 }
                 $this->Flash->success($message);
                 $this->redirect(array('controller' => 'feeds', 'action' => 'index'));
             } else {
-                $message = __('Feed could not be updated. Invalid fields: %s', implode(', ', array_keys($this->Feed->validationErrors)));
+                $message = __('Feed could not be updated. Reason: %s', json_encode($this->Feed->validationErrors));
                 if ($this->_isRest()) {
                     return $this->RestResponse->saveFailResponse('Feeds', 'add', false, $message, $this->response->type());
                 }
                 $this->Flash->error($message);
             }
diff --git a/app/Model/Feed.php b/app/Model/Feed.php
index 89a0323edf7..239141d57c7 100644
--- a/app/Model/Feed.php
+++ b/app/Model/Feed.php
@@ -29,10 +29,14 @@ class Feed extends AppModel
         'provider' => 'valueNotEmpty',
         'name' => 'valueNotEmpty',
         'event_id' => array(
             'rule' => array('numeric'),
             'message' => 'Please enter a numeric event ID or leave this field blank.',
+        ),
+        'input_source' => array(
+            'rule' => 'validateInputSource',
+            'message' => ''
         )
     );
 
     // currently we only have an internal name and a display name, but later on we can expand this with versions, default settings, etc
     public $feed_types = array(
@@ -45,10 +49,31 @@ class Feed extends AppModel
         'csv' => array(
             'name' => 'Simple CSV Parsed Feed'
         )
     );
 
+    public function validateInputSource($fields)
+    {
+        if (!empty($this->data['Feed']['input_source'])) {
+            $localAllowed = empty(Configure::read('Security.disable_local_feed_access'));
+            $validOptions = array('network');
+            if ($localAllowed) {
+                $validOptions[] = 'local';
+            }
+            if (!in_array($this->data['Feed']['input_source'], $validOptions)) {
+                return __(
+                    'Invalid input source. The only valid options are %s. %s',
+                    implode(', ', $validOptions),
+                    (!$localAllowed && $this->data['Feed']['input_source'] === 'local') ?
+                    __('Security.disable_local_feed_access is currently enabled, local feeds are thereby not allowed.') :
+                    ''
+                );
+            }
+        }
+        return true;
+    }
+
     public function urlOrExistingFilepath($fields)
     {
         if ($this->isFeedLocal($this->data)) {
             if ($this->data['Feed']['source_format'] == 'misp') {
                 if (!is_dir($this->data['Feed']['url'])) {
diff --git a/app/Model/Server.php b/app/Model/Server.php
index d0642a2eed2..012ea1985ef 100644
--- a/app/Model/Server.php
+++ b/app/Model/Server.php
@@ -1293,10 +1293,20 @@ class Server extends AppModel
                             'errorMessage' => '',
                             'test' => 'testBool',
                             'type' => 'boolean',
                             'null' => true
                         ),
+                        'disable_local_feed_access' => array(
+                                'level' => 0,
+                                'description' => __('Disabling this setting will allow the creation/modification of local feeds (as opposed to network feeds). Enabling this setting will restrict feed sources to be network based only. When disabled, keep in mind that a malicious site administrator could get access to any arbitrary file on the system that the apache user has access to. Make sure that proper safe-guards are in place. This setting can only be modified via the CLI.'),
+                                'value' => false,
+                                'errorMessage' => '',
+                                'test' => 'testBool',
+                                'type' => 'boolean',
+                                'null' => true,
+                                'cli_only' => 1
+                        ),
                         'allow_unsafe_apikey_named_param' => array(
                             'level' => 0,
                             'description' => __('Allows passing the API key via the named url parameter "apikey" - highly recommended not to enable this, but if you have some dodgy legacy tools that cannot pass the authorization header it can work as a workaround. Again, only use this as a last resort.'),
                             'value' => false,
                             'errorMessage' => __('You have enabled the passing of API keys via URL parameters. This is highly recommended against, do you really want to reveal APIkeys in your logs?...'),
diff --git a/app/View/Feeds/add.ctp b/app/View/Feeds/add.ctp
index a023fde15f6..e4eef9c6dcc 100755
--- a/app/View/Feeds/add.ctp
+++ b/app/View/Feeds/add.ctp
@@ -1,13 +1,19 @@
 <div class="feed form">
 <?php echo $this->Form->create('Feed');?>
     <fieldset>
         <legend><?php echo __('Add MISP Feed');?></legend>
-        <p><?php echo __('Add a new MISP feed source.');?></p>
-    <?php
-        echo $this->Form->input('enabled', array());
-        echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
+        <?php
+            if (!empty(Configure::read('Security.disable_local_feed_access'))) {
+                echo sprintf(
+                    '<p class="red bold">%s</p>',
+                    __('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
+                );
+            }
+            echo '<p>' . __('Add a new MISP feed source.') . '</p>';
+            echo $this->Form->input('enabled', array());
+            echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
     ?>
         <div class="input clear"></div>
     <?php
         echo $this->Form->input('lookup_visible', array('label' => __('Lookup visible')));
         echo $this->Form->input('name', array(
@@ -19,14 +25,18 @@
                 'div' => 'input clear',
                 'label' => __('Provider'),
                 'placeholder' => __('Name of the content provider'),
                 'class' => 'form-control span6'
         ));
+        $options = array('network' => 'Network');
+        if (empty(Configure::read('Security.disable_local_feed_access'))) {
+            $options['local'] = 'Local';
+        }
         echo $this->Form->input('input_source', array(
                 'label' => __('Input Source'),
                 'div' => 'input clear',
-                'options' => array('network' => 'Network', 'local' => 'Local'),
+                'options' => $options,
                 'class' => 'form-control span6'
         ));
         ?>
         <div class="input clear"></div>
         <div id="DeleteLocalFileDiv" class="optionalField">
diff --git a/app/View/Feeds/edit.ctp b/app/View/Feeds/edit.ctp
index 7767a77e675..58ae6204a41 100755
--- a/app/View/Feeds/edit.ctp
+++ b/app/View/Feeds/edit.ctp
@@ -1,11 +1,17 @@
 <div class="feed form">
 <?php echo $this->Form->create('Feed');?>
     <fieldset>
         <legend><?php echo __('Edit MISP Feed');?></legend>
-        <p><?php echo __('Edit a new MISP feed source.');?></p>
-    <?php
+        <?php
+            if (!empty(Configure::read('Security.disable_local_feed_access'))) {
+                echo sprintf(
+                    '<p class="red bold">%s</p>',
+                    __('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
+                );
+            }
+            echo '<p>' . __('Edit a new MISP feed source.') . '</p>';
             echo $this->Form->input('enabled', array(
                 'type' => 'checkbox'
             ));
             echo $this->Form->input('caching_enabled', array(
                 'type' => 'checkbox'
@@ -24,13 +30,17 @@
             echo $this->Form->input('provider', array(
                     'div' => 'input clear',
                     'placeholder' => __('Name of the content provider'),
                     'class' => 'form-control span6'
             ));
+            $options = array('network' => 'Network');
+            if (empty(Configure::read('Security.disable_local_feed_access'))) {
+                $options['local'] = 'Local';
+            }
             echo $this->Form->input('input_source', array(
                     'div' => 'input clear',
-                    'options' => array('network' => 'Network', 'local' => 'Local'),
+                    'options' => $options,
                     'class' => 'form-control span6'
             ));
             ?>
             <div id="HeadersDiv"<?php echo $this->request->data['Feed']['input_source'] == 'file' ? 'style="display:none;"' : '';?>>
         <?php

Vulnerable code:                     $message = __('Feed could not be added. Invalid field: %s', array_keys($this->Feed->validationErrors)[0]);
                $message = __('Feed could not be updated. Invalid fields: %s', implode(', ', array_keys($this->Feed->validationErrors)));
        <p><?php echo __('Add a new MISP feed source.');?></p>
    <?php
        echo $this->Form->input('enabled', array());
        echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
                'options' => array('network' => 'Network', 'local' => 'Local'),
        <p><?php echo __('Edit a new MISP feed source.');?></p>
    <?php
                    'options' => array('network' => 'Network', 'local' => 'Local'),
Fixed code:                     $message = __('Feed could not be added. Reason: %s', json_encode($this->Feed->validationErrors));
                $message = __('Feed could not be updated. Reason: %s', json_encode($this->Feed->validationErrors));
        ),
        'input_source' => array(
            'rule' => 'validateInputSource',
            'message' => ''
    public function validateInputSource($fields)
    {
        if (!empty($this->data['Feed']['input_source'])) {
            $localAllowed = empty(Configure::read('Security.disable_local_feed_access'));
            $validOptions = array('network');
            if ($localAllowed) {
                $validOptions[] = 'local';
            }
            if (!in_array($this->data['Feed']['input_source'], $validOptions)) {
                return __(
                    'Invalid input source. The only valid options are %s. %s',
                    implode(', ', $validOptions),
                    (!$localAllowed && $this->data['Feed']['input_source'] === 'local') ?
                    __('Security.disable_local_feed_access is currently enabled, local feeds are thereby not allowed.') :
                    ''
                );
            }
        }
        return true;
    }

                        'disable_local_feed_access' => array(
                                'level' => 0,
                                'description' => __('Disabling this setting will allow the creation/modification of local feeds (as opposed to network feeds). Enabling this setting will restrict feed sources to be network based only. When disabled, keep in mind that a malicious site administrator could get access to any arbitrary file on the system that the apache user has access to. Make sure that proper safe-guards are in place. This setting can only be modified via the CLI.'),
                                'value' => false,
                                'errorMessage' => '',
                                'test' => 'testBool',
                                'type' => 'boolean',
                                'null' => true,
                                'cli_only' => 1
                        ),
        <?php
            if (!empty(Configure::read('Security.disable_local_feed_access'))) {
                echo sprintf(
                    '<p class="red bold">%s</p>',
                    __('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
                );
            }
            echo '<p>' . __('Add a new MISP feed source.') . '</p>';
            echo $this->Form->input('enabled', array());
            echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
        $options = array('network' => 'Network');
        if (empty(Configure::read('Security.disable_local_feed_access'))) {
            $options['local'] = 'Local';
        }
                'options' => $options,
        <?php
            if (!empty(Configure::read('Security.disable_local_feed_access'))) {
                echo sprintf(
                    '<p class="red bold">%s</p>',
                    __('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
                );
            }
            echo '<p>' . __('Edit a new MISP feed source.') . '</p>';
            $options = array('network' => 'Network');
            if (empty(Configure::read('Security.disable_local_feed_access'))) {
                $options['local'] = 'Local';
            }
                    'options' => $options,