CVE-2018-19908 (PHP, published 2018-12-06T16:29Z)
Description: value: An issue was discovered in MISP 2.4.9x before 2.4.99. In app/Model/Event.php (the STIX 1 import code), an unescaped filename string is used to construct a shell command. This vulnerability can be abused by a malicious authenticated user to execute arbitrary commands by tweaking the original filename of the STIX import.
Severity: HIGH (CVSS v3 base score: 8.8)
Weakness: CWE-78 \u2014 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
Repository: https://github.com/MISP/MISP
Files changed:
app/Model/Event.php
app/files/scripts/stix2misp.py
Commit message: fix: [internal] Handle the upload of original versions of ingested files via a helper function instead of leaving it to external tools


Vulnerable code:
        $shell_command .=  ' ' . $original_file . ' ' . escapeshellarg(Configure::read('MISP.default_event_distribution')) . ' ' . escapeshellarg(Configure::read('MISP.default_attribute_distribution')) . ' 2>' . APP . 'tmp/logs/exec-errors.log';
        if len(args) > 0 and args[0]:
            self.add_original_file(filename, args[0], stix_version)
            event_distribution = args[1]
            attribute_distribution = args[2]
    def add_original_file(self, filename, original_filename, version):
        with open(filename, 'rb') as f:
            sample = base64.b64encode(f.read()).decode('utf-8')
        original_file = MISPObject('original-imported-file')
        original_file.add_attribute(**{'type': 'attachment', 'value': original_filename,
                                       'object_relation': 'imported-sample', 'data': sample})
        original_file.add_attribute(**{'type': 'text', 'object_relation': 'format',
                                       'value': 'STIX {}'.format(version)})
        self.misp_event.add_object(**original_file)


Fixed code:
        $shell_command .=  ' ' . escapeshellarg(Configure::read('MISP.default_event_distribution')) . ' ' . escapeshellarg(Configure::read('MISP.default_attribute_distribution')) . ' 2>' . APP . 'tmp/logs/exec-errors.log';
                $this->add_original_file($tempFilePath, $original_filename, $created_id, 'STIX 1.1');

    public function add_original_file($file_path, $original_filename, $event_id, $format)
    {
        if (!Configure::check('MISP.default_attribute_distribution') || Configure::read('MISP.default_attribute_distribution') === 'event') {
            $distribution = 5;
        } else {
            $distribution = Configure::read('MISP.default_attribute_distribution');
        }
        $this->MispObject->create();
        $object = array(
            'name' => 'original-imported-file',
            'meta-category' => 'file',
            'description' => 'Object describing the original file used to import data in MISP.',
            'template_uuid' => '4cd560e9-2cfe-40a1-9964-7b2e797ecac5',
            'template_version' => '2',
            'event_id' => $event_id,
            'distribution' => $distribution
        );
        $this->MispObject->save($object);
        $object_id = $this->MispObject->id;
        $file = file_get_contents($file_path);
        $attributes = array(
            array(
                'type' => 'attachment',
                'category' => 'External analysis',
                'to_ids' => false,
                'event_id' => $event_id,
                'distribution' => $distribution,
                'object_relation' => 'imported-sample',
                'value' => $original_filename,
                'data' => base64_encode($file),
                'object_id' => $object_id,
            ),
            array(
                'type' => 'text',
                'category' => 'Other',
                'to_ids' => false,
                'uuid' => '5c08f00d-2174-4ab7-ad0d-1b1a011fb688',
                'event_id' => $event_id,
                'distribution' => $distribution,
                'object_id' => $object_id,
                'object_relation' => 'format',
                'value' => 'STIX 1.1'
            )
        );
        foreach ($attributes as $attribute) {
            $this->Attribute->create();
            $this->Attribute->save($attribute);
        }
        return true;
    }
            event_distribution = args[0]
            attribute_distribution = args[1]