Skip to content

Commit f142b0b

Browse files
committed
wip: [stix2 import] Better way to store matchings between indicators and observable objects
1 parent 45d4b05 commit f142b0b

File tree

3 files changed

+56
-48
lines changed

3 files changed

+56
-48
lines changed

misp_stix_converter/stix2misp/converters/stix2_observable_converter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ def x509_hashes_mapping(cls, field: str) -> Union[dict, None]:
225225

226226

227227
class STIX2ObservableConverter(STIX2Converter):
228+
@property
229+
def indicator_references(self) -> dict:
230+
return self.main_parser.indicator_references
231+
228232
def _fetch_observable(self, object_ref: str) -> dict:
229233
return self.main_parser._observable.get(object_ref)
230234

misp_stix_converter/stix2misp/converters/stix2_observed_data_converter.py

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,16 @@ class STIX2ObservedDataConverter(STIX2ObservableConverter, metaclass=ABCMeta):
5858
def __init__(self, main: _MAIN_PARSER_TYPING):
5959
self._set_main_parser(main)
6060

61-
def _get_observed_data(
62-
self, object_id: str) -> dict | _OBSERVED_DATA_TYPING:
63-
return self.main_parser._observed_data[object_id]
61+
def _get_observed_data(self, object_id: str) -> _OBSERVED_DATA_TYPING:
62+
observed_data = self.main_parser._observed_data[object_id]
63+
if isinstance(observed_data, (ObservedData_v20, ObservedData_v21)):
64+
return observed_data
65+
return observed_data['observed_data']
66+
67+
def _get_observed_data_indicator_refs(
68+
self, observed_data_id: str, object_id: str) -> Union[set, None]:
69+
observed_data = self.main_parser._observed_data[observed_data_id]
70+
return observed_data.get('indicator_refs', {}).get(object_id)
6471

6572
@property
6673
def observables(self) -> dict:
@@ -151,31 +158,15 @@ def referenced_ids(self):
151158

152159
def parse(self, observed_data_ref: str):
153160
observed_data = self._get_observed_data(observed_data_ref)
154-
if observed_data.get('indicator_refs') is not None:
155-
observed_data_object = observed_data['observed_data']
156-
try:
157-
if hasattr(observed_data_object, 'object_refs'):
158-
self._parse_observable_object_refs(
159-
observed_data_object, observed_data['indicator_refs']
160-
)
161-
else:
162-
self._parse_observable_objects(
163-
observed_data_object, observed_data['indicator_refs']
164-
)
165-
except UnknownObservableMappingError as observable_types:
166-
self._observable_mapping_error(
167-
observed_data_object.id, observable_types
168-
)
169-
else:
170-
try:
171-
if hasattr(observed_data, 'object_refs'):
172-
self._parse_observable_object_refs(observed_data)
173-
else:
174-
self._parse_observable_objects(observed_data)
175-
except UnknownObservableMappingError as observable_types:
176-
self._observable_mapping_error(
177-
observed_data.id, observable_types
178-
)
161+
try:
162+
if hasattr(observed_data, 'object_refs'):
163+
self._parse_observable_object_refs(observed_data)
164+
else:
165+
self._parse_observable_objects(observed_data)
166+
except UnknownObservableMappingError as observable_types:
167+
self._observable_mapping_error(
168+
observed_data.id, observable_types
169+
)
179170

180171
def parse_relationships(self):
181172
for misp_object in self.main_parser.misp_event.objects:

misp_stix_converter/stix2misp/external_stix2_to_misp.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
from typing import Iterator, Optional, Union
2626

2727
_EXTENSION_TYPES = (Extension_v20, Extension_v21, STIXBase_v20, STIXBase_v21)
28-
_INDICATOR_FIELDS = {'_indicator': 1, '_observable': 2, '_observed_data': 4}
2928
_OBSERVABLE_FIELDS_TO_SKIP = (
3029
'defanged', 'granular_markings', 'id', 'object_marking_refs',
3130
'spec_version', 'type'
3231
)
32+
_SDO_STORAGE_FIELDS = {'_indicator': 1, '_observable': 2, '_observed_data': 4}
3333
_SIGHTING_TYPING = Union[Sighting_v20, Sighting_v21]
3434

3535

@@ -371,23 +371,23 @@ def _fetch_observable_references(
371371
if isinstance(value, _EXTENSION_TYPES):
372372
yield from self._fetch_observable_references(value)
373373
continue
374-
yield f'{key} - {value}'
374+
yield value
375375
continue
376376
if isinstance(values, _EXTENSION_TYPES):
377377
yield from self._fetch_observable_references(values)
378378
continue
379-
yield f'{key} - {values}'
379+
yield values
380380

381381
def _set_indicator_references(self):
382382
score = 0
383-
for feature, count in _INDICATOR_FIELDS.items():
383+
for feature, count in _SDO_STORAGE_FIELDS.items():
384384
if getattr(self, feature, []):
385385
score += count
386386
if score in (0, 1, 2, 4, 6):
387387
return
388388
pattern_parser = self.indicator_parser._compile_stix_pattern
389389
self._indicator_references = {
390-
indicator_id: tuple(f'{val[0][-1]} - {val[-1]}' for val in pattern)
390+
indicator_id: tuple(val[-1] for val in pattern)
391391
for indicator_id, indicator in self._indicator.items()
392392
for pattern in pattern_parser(indicator).comparisons.values()
393393
}
@@ -400,31 +400,44 @@ def _set_indicator_references(self):
400400
continue
401401
for indicator_reference in indicator_references:
402402
indicator = self._indicator[indicator_reference]
403-
self._indicator[indicator_reference] = {
404-
'indicator': indicator,
405-
'observable_ref': observable_id
406-
}
407-
observable['indicator_ref'] = indicator_reference
403+
if not isinstance(indicator, dict):
404+
self._indicator[indicator_reference] = {
405+
'indicator': indicator,
406+
'observable_ref': set()
407+
}
408+
indicator = self._indicator[indicator_reference]
409+
indicator['observable_ref'].add(observable_id)
410+
if 'indicator_ref' not in observable:
411+
observable['indicator_ref'] = {indicator_reference}
412+
continue
413+
observable['indicator_ref'].add(indicator_reference)
408414
if score >= 5:
409415
for observed_id, observed_data in self._observed_data.items():
410416
if not hasattr(observed_data, 'objects'):
411417
continue
412-
indicator_refs = {}
418+
indicator_refs = defaultdict(set)
413419
for observable_id, observable in observed_data.objects.items():
414420
indicator_references = set(
415421
self._fetch_indicator_reference(observable)
416422
)
417423
if not indicator_references:
418424
continue
419425
for indicator_reference in indicator_references:
426+
indicator_refs[observable_id].add(indicator_reference)
420427
indicator = self._indicator[indicator_reference]
421-
self._indicator[indicator_reference] = {
422-
'indicator': indicator,
423-
'observable_ref': observed_id
424-
}
425-
indicator_refs[observable_id] = indicator_reference
428+
if not isinstance(indicator, dict):
429+
self._indicator[indicator_reference] = {
430+
'indicator': indicator,
431+
'observable_ref': {observed_id}
432+
}
433+
continue
434+
indicator['observable_ref'].add(observed_id)
426435
if indicator_refs:
427-
self._observed_data[observed_id] = {
428-
'indicator_refs': indicator_refs,
429-
'observed_data': observed_data
430-
}
436+
if not isinstance(observed_data, dict):
437+
self._observed_data[observed_id] = {
438+
'indicator_refs': indicator_refs,
439+
'observed_data': observed_data
440+
}
441+
continue
442+
for observable_id, refs in indicator_refs.items():
443+
observed_data['indicator_refs'][observable_id].update(refs)

0 commit comments

Comments
 (0)