From bdcfe06cf3a1c432484bff1121f67cad45e12be5 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Tue, 12 Dec 2023 10:57:57 +0100 Subject: [PATCH 1/8] 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) From 5e8b122c2ed2bebdd8485e1b9c30bf87b5e30c1b Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Tue, 12 Dec 2023 11:24:30 +0100 Subject: [PATCH 2/8] chg: [misp-stix] Bumped latest version --- app/files/scripts/misp-stix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/scripts/misp-stix b/app/files/scripts/misp-stix index 5b678c26b..b0a1dcffa 160000 --- a/app/files/scripts/misp-stix +++ b/app/files/scripts/misp-stix @@ -1 +1 @@ -Subproject commit 5b678c26b95e0f34ad4515292f09e192aa0e4730 +Subproject commit b0a1dcffa44aee1af5b316babf323fcb24a6c0e1 From c5baab3328b665f915d532b0befc6f8ddeb74351 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Tue, 12 Dec 2023 11:34:05 +0100 Subject: [PATCH 3/8] fix: [stix2 import] Fixed STIX2 parser name --- app/files/scripts/stix2/stix2misp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/scripts/stix2/stix2misp.py b/app/files/scripts/stix2/stix2misp.py index d6d0bbc65..9164dd697 100644 --- a/app/files/scripts/stix2/stix2misp.py +++ b/app/files/scripts/stix2/stix2misp.py @@ -67,7 +67,7 @@ def _process_stix_file(args: argparse.ArgumentParser): ) stix_version = getattr(bundle, 'version', '2.1') to_call, arguments = _get_stix_parser(_from_misp(bundle.objects), args) - parser = globals()[f'{to_call}STIX2toMISPParser'](**arguments) + parser = globals()[to_call](**arguments) parser.load_stix_bundle(bundle) parser.parse_stix_bundle() with open(f'{args.input}.out', 'wt', encoding='utf-8') as f: From debae13bc21d3296e0a7fd78c3bb04986167f0ae Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Thu, 14 Dec 2023 11:41:47 +0100 Subject: [PATCH 4/8] chg: [upload_stix] Casting distributions and sharing group IDs type --- app/Model/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Model/Event.php b/app/Model/Event.php index fd5d6d43e..5b6248656 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -5936,7 +5936,7 @@ class Event extends AppModel * @throws InvalidArgumentException * @throws Exception */ - public function upload_stix(array $user, $file, $stix_version, $original_file, $publish, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $debug = false) + public function upload_stix(array $user, $file, $stix_version, $original_file, bool $publish, int $distribution, int $sharingGroupId, bool $galaxiesAsTags, int $clusterDistribution, int $clusterSharingGroupId, $debug = false) { $scriptDir = APP . 'files' . DS . 'scripts'; if ($stix_version == '2' || $stix_version == '2.0' || $stix_version == '2.1') { From d70150d237dc238980547f22c01834be52467c14 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Thu, 14 Dec 2023 14:10:58 +0100 Subject: [PATCH 5/8] fix: [upload_stix] Avoiding issues with sharing group arguments being null --- app/Model/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Model/Event.php b/app/Model/Event.php index 5b6248656..32e10f9f9 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -5936,7 +5936,7 @@ class Event extends AppModel * @throws InvalidArgumentException * @throws Exception */ - public function upload_stix(array $user, $file, $stix_version, $original_file, bool $publish, int $distribution, int $sharingGroupId, bool $galaxiesAsTags, int $clusterDistribution, int $clusterSharingGroupId, $debug = false) + public function upload_stix(array $user, $file, $stix_version, $original_file, bool $publish, int $distribution, ?int $sharingGroupId, bool $galaxiesAsTags, int $clusterDistribution, ?int $clusterSharingGroupId, $debug = false) { $scriptDir = APP . 'files' . DS . 'scripts'; if ($stix_version == '2' || $stix_version == '2.0' || $stix_version == '2.1') { From 116353903847af1d2eb853e7e3225e5bfe39a4c0 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Fri, 23 Feb 2024 16:03:00 +0100 Subject: [PATCH 6/8] fix: [upload_stix] Fixed undefined index `cluster_sharing_group_id` when uploading stix file --- app/Controller/EventsController.php | 2 +- app/Model/Event.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 21705e617..466c767ae 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -2491,7 +2491,7 @@ class EventsController extends AppController $this->data['Event']['sharing_group_id'] ?? null, $this->data['Event']['galaxies_handling'], $this->data['Event']['cluster_distribution'], - $this->data['Event']['cluster_sharing_group_id'], + $this->data['Event']['cluster_sharing_group_id'] ?? null, $debug ); if (is_numeric($result)) { diff --git a/app/Model/Event.php b/app/Model/Event.php index b23b84b9d..a55e12634 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -5996,7 +5996,7 @@ class Event extends AppModel * @param int|null $sharingGroupId * @param bool $galaxiesAsTags * @param int $clusterDistribution - * @param int $clusterSharingGroupId + * @param int|null $clusterSharingGroupId * @param bool $debug * @return int|string|array * @throws JsonException @@ -6070,7 +6070,7 @@ class Event extends AppModel * @param int|null $sharingGroupId * @param bool $galaxiesAsTags * @param int $clusterDistribution - * @param int $clusterSharingGroupId + * @param int|null $clusterSharingGroupId * @param bool $debug * @return array * @throws Exception From 41b20f96d3cd6ba7aaa08cf3657a3ec485a1face Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Fri, 23 Feb 2024 21:41:08 +0100 Subject: [PATCH 7/8] add: [stix2 import] Added organisation UUID parameter to be used when generating custom Galaxy Clusters UUID --- app/Model/Event.php | 6 ++++-- app/files/scripts/stix2/stix2misp.py | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/Model/Event.php b/app/Model/Event.php index a55e12634..342337a45 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -6005,7 +6005,7 @@ class Event extends AppModel */ public function upload_stix(array $user, $file, $stixVersion, $originalFile, $publish, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $debug = false) { - $decoded = $this->convertStixToMisp($stixVersion, $file, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $debug); + $decoded = $this->convertStixToMisp($stixVersion, $file, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $user['Organisation']['uuid'], $debug); if (!empty($decoded['success'])) { $data = JsonTool::decodeArray($decoded['converted']); @@ -6071,11 +6071,12 @@ class Event extends AppModel * @param bool $galaxiesAsTags * @param int $clusterDistribution * @param int|null $clusterSharingGroupId + * @param string $orgUuid * @param bool $debug * @return array * @throws Exception */ - private function convertStixToMisp($stixVersion, $file, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $debug) + private function convertStixToMisp($stixVersion, $file, $distribution, $sharingGroupId, $galaxiesAsTags, $clusterDistribution, $clusterSharingGroupId, $orgUuid, $debug) { $scriptDir = APP . 'files' . DS . 'scripts'; if ($stixVersion === '2' || $stixVersion === '2.0' || $stixVersion === '2.1') { @@ -6086,6 +6087,7 @@ class Event extends AppModel $scriptFile, '-i', $file, '--distribution', $distribution, + '--org_uuid', $orgUuid ]; if ($distribution == 4) { array_push($shellCommand, '--sharing_group_id', $sharingGroupId); diff --git a/app/files/scripts/stix2/stix2misp.py b/app/files/scripts/stix2/stix2misp.py index 271c8be88..6fdad7073 100644 --- a/app/files/scripts/stix2/stix2misp.py +++ b/app/files/scripts/stix2/stix2misp.py @@ -29,7 +29,8 @@ sys.path.insert(2, str(_scripts_path / 'python-cybox')) sys.path.insert(3, str(_scripts_path / 'mixbox')) sys.path.insert(4, str(_scripts_path / 'misp-stix')) from misp_stix_converter import ( - ExternalSTIX2toMISPParser, InternalSTIX2toMISPParser, _from_misp) + ExternalSTIX2toMISPParser, InternalSTIX2toMISPParser, + MISP_org_uuid, _from_misp) from stix2.parsing import parse as stix2_parser @@ -103,6 +104,10 @@ if __name__ == '__main__': '-i', '--input', required=True, type=Path, help='Input file containing STIX 2 content.' ) + argparser.add_argument( + '--org_uuid', default=MISP_org_uuid, + help='Organisation UUID to use when creating custom Galaxy clusters.' + ) argparser.add_argument( '--distribution', type=int, default=0, help='Distribution level for the resulting MISP Event.' From 5f6c1327ff54e95346215378e16681f6f8a7e390 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Fri, 23 Feb 2024 21:42:38 +0100 Subject: [PATCH 8/8] chg: [misp-stix] Bumped latest version with the changes on the organisation uuid argument --- app/files/scripts/misp-stix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/scripts/misp-stix b/app/files/scripts/misp-stix index b8b8b7445..dd3037ee7 160000 --- a/app/files/scripts/misp-stix +++ b/app/files/scripts/misp-stix @@ -1 +1 @@ -Subproject commit b8b8b7445754ea3cbc84e2d0b434ecd08740ef95 +Subproject commit dd3037ee7f31c1f43a3ad3aaaa6cccfa232dc530