From bdcfe06cf3a1c432484bff1121f67cad45e12be5 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Tue, 12 Dec 2023 10:57:57 +0100 Subject: [PATCH] add: [upload_stix] Handling cluster distribution and sharing group for content imported from STIX 2.x --- app/Controller/EventsController.php | 31 ++++++++++--- app/Model/Event.php | 13 +++++- app/View/Events/upload_stix.ctp | 67 ++++++++++++++++++++++++---- app/files/scripts/stix2/stix2misp.py | 31 ++++++++++--- 4 files changed, 121 insertions(+), 21 deletions(-) diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 67175c2f0..f7b5d2edc 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -2408,14 +2408,14 @@ class EventsController extends AppController } if (isset($this->params['named']['distribution'])) { $distribution = intval($this->params['named']['distribution']); - if (array_key_exists($distribution, $distributionLevels)) { - $initialDistribution = $distribution; - } else { + if (!array_key_exists($distribution, $distributionLevels)) { throw new MethodNotAllowedException(__('Wrong distribution level')); } + } else { + $distribution = $initialDistribution; } $sharingGroupId = null; - if ($initialDistribution == 4) { + if ($distribution == 4) { if (!isset($this->params['named']['sharing_group_id'])) { throw new MethodNotAllowedException(__('The sharing group id is needed when the distribution is set to 4 ("Sharing group").')); } @@ -2424,8 +2424,25 @@ class EventsController extends AppController throw new MethodNotAllowedException(__('Please select a valid sharing group id.')); } } + $clusterDistribution = $initialDistribution; + $clusterSharingGroupId = null; if (isset($this->params['named']['galaxies_as_tags'])) { $galaxies_as_tags = $this->params['named']['galaxies_as_tags']; + if (isset($this->params['name']['cluster_distribution'])) { + $clusterDistribution = intval($this->params['named']['cluster_distribution']); + if (!array_key_exists($clusterDistribution, $distributionLevels)) { + throw new MethodNotAllowedException(__('Wrong cluster distribution level')); + } + if ($clusterDistribution == 4) { + if (!isset($this->params['named']['cluster_sharing_group_id'])) { + throw new MethodNotAllowedException(__('The cluster sharing group id is needed when the cluster distribution is set to 4 ("Sharing group").')); + } + $clusterSharingGroupId = intval($this->params['named']['cluster_sharing_group_id']); + if (!array_key_exists($clusterSharingGroupId, $sgs)) { + throw new MethodNotAllowedException(__('Please select a valid cluster sharing group id.')); + } + } + } } if (isset($this->params['named']['debugging'])) { $debug = $this->params['named']['debugging']; @@ -2437,9 +2454,11 @@ class EventsController extends AppController $stix_version, 'uploaded_stix_file.' . ($stix_version == '1' ? 'xml' : 'json'), $publish, - $initialDistribution, + $distribution, $sharingGroupId, $galaxies_as_tags, + $clusterDistribution, + $clusterSharingGroupId, $debug ); if (is_numeric($result)) { @@ -2471,6 +2490,8 @@ class EventsController extends AppController $this->data['Event']['distribution'], $this->data['Event']['sharing_group_id'], $this->data['Event']['galaxies_handling'], + $this->data['Event']['cluster_distribution'], + $this->data['Event']['cluster_sharing_group_id'], $debug ); if (is_numeric($result)) { diff --git a/app/Model/Event.php b/app/Model/Event.php index 5b15fb915..fd5d6d43e 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -5925,12 +5925,18 @@ class Event extends AppModel * @param string $stix_version * @param string $original_file * @param bool $publish + * @param int $distribution + * @param int $sharingGroupId + * @param bool $galaxiesAsTags + * @param int $clusterDistribution + * @param int $clusterSharingGroupId + * @param bool $debug * @return int|string|array * @throws JsonException * @throws InvalidArgumentException * @throws Exception */ - public function upload_stix(array $user, $file, $stix_version, $original_file, $publish, $distribution, $sharingGroupId, $galaxiesAsTags, $debug = false) + public function upload_stix(array $user, $file, $stix_version, $original_file, $publish, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $debug = false) { $scriptDir = APP . 'files' . DS . 'scripts'; if ($stix_version == '2' || $stix_version == '2.0' || $stix_version == '2.1') { @@ -5947,6 +5953,11 @@ class Event extends AppModel } if ($galaxiesAsTags) { $shell_command[] = '--galaxies_as_tags'; + } else { + array_push($shell_command, '--cluster_distribution', $clusterDistribution); + if ($clusterDistribution == 4) { + array_push($shell_command, '--cluster_sharing_group_id', $clusterSharingGroupId); + } } if ($debug) { $shell_command[] = '--debug'; diff --git a/app/View/Events/upload_stix.ctp b/app/View/Events/upload_stix.ctp index ef49d101e..2a1888fa7 100644 --- a/app/View/Events/upload_stix.ctp +++ b/app/View/Events/upload_stix.ctp @@ -27,17 +27,16 @@ 'label' => __('Distribution ') . $distributionFormInfo, 'selected' => $initialDistribution, )); -?> -
Form->input('publish', array( @@ -68,6 +67,36 @@ 'label' => __('How to handle Galaxies and Clusters') . $galaxiesFormInfo, 'selected' => 0 )); +?> +
+element( + 'genericElements/Form/formInfo', + [ + 'field' => [ + 'field' => 'cluster_distribution' + ], + 'modelForForm' => 'Event', + 'fieldDesc' => $fieldDesc['distribution'], + ] + ); + $clusterDistribution = $this->Form->input( + 'cluster_distribution', array( + 'options' => $distributionLevels, + 'label' => __('Cluster distribution ') . $clusterDistributionFormInfo, + 'selected' => $initialDistribution, + ) + ); + echo ''; + if (!empty($sharingGroups)) { + $clusterSGContainer = $this->Form->input( + 'cluster_sharing_group_id', array( + 'options' => array($sharingGroups), + 'label' => __('Cluster Sharing Group'), + ) + ); + echo ''; + } } if ($me['Role']['perm_site_admin'] && Configure::read('debug') > 0) { $debugFormInfo = $this->element( @@ -108,4 +137,26 @@ $(function(){ } }).change(); }); +$(function(){ + $('#EventGalaxiesHandling').change(function() { + if ($(this).val() == 0) { + $('#ClusterDistribution').show(); + if ($('#EventClusterDistribution').val() == 4) { + $('#ClusterSGContainer').show(); + } + } else { + $('#ClusterDistribution').hide(); + $('#ClusterSGContainer').hide(); + } + }).change(); +}); +$(function(){ + $('#EventClusterDistribution').change(function() { + if ($(this).val() == 4 && $('#EventGalaxiesHandling').val() == 0) { + $('#ClusterSGContainer').show(); + } else { + $('#ClusterSGContainer').hide(); + } + }).change(); +}); \ No newline at end of file diff --git a/app/files/scripts/stix2/stix2misp.py b/app/files/scripts/stix2/stix2misp.py index ed5fa15ef..d6d0bbc65 100644 --- a/app/files/scripts/stix2/stix2misp.py +++ b/app/files/scripts/stix2/stix2misp.py @@ -33,6 +33,21 @@ from misp_stix_converter import ( from stix2.parsing import parse as stix2_parser +def _get_stix_parser(from_misp, args): + arguments = { + 'distribution': args.distribution, + 'galaxies_as_tags': args.galaxies_as_tags + } + if args.distribution == 4 and args.sharing_group_id is not None: + arguments['sharing_group_id'] = args.sharing_group_id + if from_misp: + return 'InternalSTIX2toMISPParser', arguments + arguments['cluster_distribution'] = args.cluster_distribution + if args.cluster_distribution == 4 and args.cluster_sharing_group_id is not None: + arguments['cluster_sharing_group_id'] = args.cluster_sharing_group_id + return 'ExternalSTIX2toMISPParser', arguments + + def _handle_return_message(traceback): if isinstance(traceback, dict): messages = [] @@ -51,13 +66,7 @@ def _process_stix_file(args: argparse.ArgumentParser): f.read(), allow_custom=True, interoperability=True ) stix_version = getattr(bundle, 'version', '2.1') - to_call = 'Internal' if _from_misp(bundle.objects) else 'External' - arguments = { - 'distribution': args.distribution, - 'galaxies_as_tags': args.galaxies_as_tags - } - if args.distribution == 4 and args.sharing_group_id is not None: - arguments['sharing_group_id'] = args.sharing_group_id + to_call, arguments = _get_stix_parser(_from_misp(bundle.objects), args) parser = globals()[f'{to_call}STIX2toMISPParser'](**arguments) parser.load_stix_bundle(bundle) parser.parse_stix_bundle() @@ -107,6 +116,14 @@ if __name__ == '__main__': '--galaxies_as_tags', action='store_true', help='Import MISP Galaxies as tag names.' ) + argparser.add_argument( + '--cluster_distribution', type=int, default=0, + help='Cluster distribution level for clusters generated from STIX 2.x objects' + ) + argparser.add_argument( + '--cluster_sharing_group_id', type=int, + help='Cluster sharing group id when the cluster distribution level is 4.' + ) try: args = argparser.parse_args() _process_stix_file(args)