def test_markable_self_node(self): """Test that a marking to an element with descendants=False will result in ``self::node()`` selector.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(indicator, red_marking) self.assertTrue(package.indicators[0].handling is None) container.flush() indicator_path = package.indicators[0].handling.marking[0] \ .controlled_structure.split("/")[-1] self.assertTrue(indicator_path == xml.XPATH_AXIS_SELF_NODE) counter = 0 for elem in navigator.iterwalk(package): if api.is_marked(elem): counter += 1 # There should be only one object with markings in the whole package. self.assertTrue(counter == 1)
def test_markable_attributes(self): """Test that attribute selector used on resulting xpath. Does not check for accuracy of marked data.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") observable = generate_observable() indicator.add_observable(observable) package.add_indicator(indicator) observable.object_.id_ = container.add_marking(observable.object_.id_, red_marking) indicator.timestamp = container.add_marking(indicator.timestamp, red_marking) self.assertTrue(package.stix_header is None) self.assertTrue(package.indicators[0].handling is None) container.flush() self.assertTrue(package.stix_header is None) self.assertTrue(package.indicators[0].handling is not None) for marking in package.indicators[0].handling.marking: selector = marking.controlled_structure.split("/")[-1] self.assertTrue(selector.startswith("@"))
def test_duplicate_marking(self): """Test that duplicate markings get added once.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(indicator, red_marking) self.assertRaises(errors.DuplicateMarkingError, container.add_marking, indicator, red_marking, False) container.add_global(red_marking) self.assertRaises(errors.DuplicateMarkingError, container.add_global, red_marking) self.assertTrue(indicator.handling is None) self.assertTrue(package.stix_header is None) container.flush() self.assertTrue(len(indicator.handling.marking) == 1) self.assertTrue(len(package.stix_header.handling.marking) == 1)
def test_stix_header_marking_placement(self): """Test that marking an individual field whose parent does not contain a handling structure, marking is placed in stix header.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) kill_chain = KillChain(id_="example:kc-1234", name="Test Kill Chain") kill_chain_phase = KillChainPhase(phase_id="example:kcp-1234", name="Test Kill Chain Phase") test_ttps = ttps.TTPs() package.ttps = test_ttps kill_chain.add_kill_chain_phase(kill_chain_phase) package.ttps.kill_chains.kill_chain.append(kill_chain) container.add_marking(kill_chain_phase, red_marking) self.assertTrue(package.stix_header is None) container.flush() self.assertTrue(package.stix_header.handling.marking[0]. controlled_structure is not None)
def _get_stix_package(in_json): if in_json is not None and len(in_json) > 0: initialize_options() container = stixmarx.new() stix_package = container.package json_content = json.loads(in_json) if type(json_content) == list: for json_data in json_content: if "type" in json_data and json_data["type"] == "indicator": indicator = convert_indicator(json_data) stix_package.add_indicator(indicator) else: if "type" in json_content and json_content["type"] == "bundle": if "objects" in json_content and json_content["objects"] and type(json_content["objects"]) == list: for json_data in json_content["objects"]: if "type" in json_data and json_data["type"] == "indicator": indicator = convert_indicator(json_data) stix_package.add_indicator(indicator) elif "type" in json_content and json_content["type"] == "indicator": indicator = convert_indicator(json_content) stix_package.add_indicator(indicator) container.flush() container = None return stix_package else: raise RuntimeError('request body is empty.')
def test_package_marking_error(self): """Marking a package with `add(package, marking)` is not allowed. Use `add_global(marking)` instead.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) self.assertRaises(errors.UnmarkableError, container.add_marking, package, red_marking)
def test_observable_marking(self): """Test that Observables can be marked directly""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) observable = generate_observable() package.add_observable(observable) container.add_marking(observable, red_marking) self.assertTrue(container.is_marked(observable, red_marking))
def test_global_package_marking(self): """Test that global markings apply to the package and TLOs""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) container.add_global(red_marking) indicator = Indicator(title="Test") package.add_indicator(indicator) self.assertTrue(container.is_marked(indicator, red_marking)) self.assertTrue(container.is_marked(package, red_marking))
def test_is_marked(self): container = stixmarx.new() package = container.package indicator = Indicator(title="Test") package.add(indicator) red_struct = generate_red_marking_struct() red_marking = generate_marking_spec(red_struct) container.add_marking(indicator, red_marking) # Test that our marking has been added self.assertTrue(container.is_marked(indicator, red_marking))
def test_remove_null_making(self): container = stixmarx.new() red_struct = generate_red_marking_struct() red_marking = generate_marking_spec(red_struct) container.add_marking(None, red_marking) self.assertTrue(len(container.null_markings) == 1) container.remove_marking(None, red_marking) self.assertTrue(len(container.null_markings) == 0)
def test_component_marking(self): """Test that top-level STIX components are marked correctly""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(indicator, red_marking, descendants=True) self.assertTrue(container.is_marked(indicator, red_marking))
def test_global_marking_on_observables(self): """Test that global markings apply to Obseravbles""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) container.add_global(red_marking) observable = generate_observable() package.add_observable(observable) self.assertTrue(container.is_marked(observable, red_marking)) self.assertFalse( container.is_marked(observable, MarkingSpecification()))
def test_global_marking_placement(self): """Test that global markings are placed in stix header.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) container.add_global(red_marking) self.assertTrue(package.stix_header is None) container.flush() self.assertTrue(package.stix_header.handling.marking[0]. controlled_structure is not None)
def test_marking_removal(self): """Test that markings can be removed""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(indicator, red_marking) self.assertTrue(container.is_marked(indicator, red_marking)) container.remove_marking(indicator, red_marking) self.assertFalse(container.is_marked(indicator, red_marking))
def test_embedded_component_direct_marking(self): """Test that embedded STIX components can be directly marked""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) incident = Incident(title="Test") package.add_incident(incident) indicator = Indicator(title="Test") incident.related_indicators.append(indicator) container.add_marking(indicator, red_marking) self.assertTrue(container.is_marked(indicator, red_marking))
def test_absent_marking_removal_failure(self): """Test that markings can be removed""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) self.assertRaises(errors.MarkingNotFoundError, container.remove_marking, indicator, red_marking) observable = generate_observable() package.add_observable(observable) self.assertRaises(errors.MarkingNotFoundError, container.remove_marking, observable, red_marking)
def test_duplicate_check(self): container = stixmarx.new() package = container.package indicator = Indicator(title="Test") package.add(indicator) red_marking = generate_marking_spec(generate_red_marking_struct()) container.add_marking(indicator, red_marking) # Test that our marking has been added self.assertTrue(container.is_marked(indicator, red_marking)) self.assertTrue(red_marking in container.get_markings(indicator)) # Test that the trying to re-add the original would raise an error self.assertRaises(errors.DuplicateMarkingError, container.add_marking, indicator, red_marking)
def test_embedded_observable_marking_removal(self): """Test that markings on embedded Observables can be removed""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) observable = generate_observable() indicator.add_observable(observable) container.add_marking(observable, red_marking) self.assertTrue(container.is_marked(observable, red_marking)) container.remove_marking(observable, red_marking) self.assertFalse(container.is_marked(observable, red_marking))
def test_embedded_observable_direct_marking(self): """Test that embedded Observables can be directly marked""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) amber_marking = generate_marking_spec(generate_amber_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) observable = generate_observable() indicator.add_observable(observable) container.add_marking(indicator, amber_marking) container.add_marking(observable, red_marking) self.assertTrue(container.is_marked(observable, red_marking))
def test_remove_parent_marking_failure(self): """Test that inherited parent markings cannot be removed from children""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) incident = Incident(title="Test") package.add_incident(incident) indicator = Indicator(title="Test") incident.related_indicators.append(indicator) container.add_marking(incident, red_marking, descendants=True) self.assertTrue(container.is_marked(incident, red_marking)) self.assertTrue(container.is_marked(indicator, red_marking)) self.assertRaises(errors.MarkingRemovalError, container.remove_marking, indicator, red_marking, True)
def test_embedded_observable_marking(self): """Test that embedded Observables are marked according to their parent TLO and global markings""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) amber_marking = generate_marking_spec(generate_amber_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) observable = generate_observable() indicator.add_observable(observable) container.add_marking(indicator, red_marking, descendants=True) container.add_global(amber_marking) self.assertTrue(container.is_marked(observable, red_marking)) self.assertTrue(container.is_marked(observable, amber_marking))
def test_embedded_component_marking(self): """Test that embedded STIX components are marked according to their parent TLO and global markings""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) amber_marking = generate_marking_spec(generate_amber_marking_struct()) incident = Incident(title="Test") package.add_incident(incident) indicator = Indicator(title="Test") incident.related_indicators.append(indicator) container.add_marking(incident, red_marking, descendants=True) container.add_global(amber_marking) self.assertTrue(container.is_marked(indicator, red_marking)) self.assertTrue(container.is_marked(indicator, amber_marking))
def test_null_marking_serialization(self): """Test that a null marking gets serialized.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(None, red_marking) self.assertTrue(package.stix_header is None or package.stix_header.handling is None) container.flush() self.assertTrue(package.stix_header.handling is not None)
def main(): # Create a new stixmarx MarkingContainer with a # new STIXPackage object contained within it. container = stixmarx.new() # Get the associated STIX Package package = container.package # Create an Indicator object indicator = Indicator(title='Indicator Title', description='Gonna Mark This') # Add the Indicator object to our STIX Package package.add(indicator) # Build MarkingSpecification and add TLP MarkingStructure red_marking = MarkingSpecification(marking_structures=TLP(color="RED")) amber_marking = MarkingSpecification(marking_structures=TLP(color="AMBER")) green_marking = MarkingSpecification(marking_structures=TLP(color="GREEN")) # Mark the indicator with our TLP RED marking # This is the equivalent of a component marking. Applies to all descendants # nodes, text and attributes. container.add_marking(indicator, red_marking, descendants=True) # Mark the indicator with TLP GREEN. If descendants is false, the marking # will only apply to the indicator node. Does NOT include text, attributes # or descendants. container.add_marking(indicator, green_marking) # Mark the description text. # >>> type(indicator.description.value) <type 'str'> indicator.description.value = container.add_marking( indicator.description.value, amber_marking) # >>> type(indicator.description.value) <class 'stixmarx.api.types.MarkableBytes'> # Mark the indicator timestamp attribute. # >>> type(indicator.description.value) <type 'datetime.datetime'> indicator.timestamp = container.add_marking(indicator.timestamp, amber_marking) # >>> type(indicator.description.value) <type 'stixmarx.api.types.MarkableDateTime'> # Print the XML! print(container.to_xml().decode("utf-8"))
def stix2to1(): try: data_dir = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data')) in_str = read2str(data_dir + '/stixv2.json') initialize_options() container = stixmarx.new() stix_package = container.package json_content = json.loads(in_str) if type(json_content) == list: for json_data in json_content: if "type" in json_data and json_data["type"] == "indicator": indicator = convert_indicator(json_data) stix_package.add_indicator(indicator) else: if "type" in json_content and json_content["type"] == "bundle": if "objects" in json_content and json_content[ "objects"] and type(json_content["objects"]) == list: for json_data in json_content["objects"]: if "type" in json_data and json_data[ "type"] == "indicator": indicator = convert_indicator(json_data) stix_package.add_indicator(indicator) elif "type" in json_content and json_content["type"] == "indicator": indicator = convert_indicator(json_content) stix_package.add_indicator(indicator) container.flush() container = None # print stix_package.to_xml() out_fname = './stixv2.xml' write2file(out_fname, stix_package.to_xml()) except: print traceback.format_exc().decode('utf-8')
def test_markable_text_nodes(self): """Test that text selector is used on resulting xpath. Does not check for accuracy of marked data.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") # STIX 1.1.1 doesn't have multiple descriptions indicator.description = "Test description" observable = generate_observable() indicator.add_observable(observable) package.add_indicator(indicator) observable.object_.properties.address_value.value = \ container.add_marking( observable.object_.properties.address_value.value, red_marking ) indicator.description.value = \ container.add_marking( indicator.description.value, red_marking ) self.assertTrue(package.stix_header is None) self.assertTrue(package.indicators[0].handling is None) container.flush() self.assertTrue(package.stix_header is None) self.assertTrue(package.indicators[0].handling is not None) for marking in package.indicators[0].handling.marking: selector = marking.controlled_structure.split("/")[-1] self.assertTrue("text()" == selector) print(package.to_xml().decode("utf-8"))
def generateContainer(header, intent, stixObject, input_dict): container = stixmarx.new() stix_package = container.package stix_header = STIXHeader() stix_header.description = header + " " + input_dict['title'] stix_header.add_package_intent (intent) stix_package.stix_header = stix_header # TODO workaround for pyStix error if stixObject.__class__ is stix.ttp.TTP: stix_package.add_ttp(stixObject) else: stix_package.add(stixObject) marking_specification = generateMarking(input_dict['marking']) container.add_component(stixObject, marking_specification) return container
def test_marking_flush(self): """Tests that markings do not affect a package until flushed from the container.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) amber_marking = generate_marking_spec(generate_amber_marking_struct()) indicator = Indicator(title="Test") package.add_indicator(indicator) container.add_marking(indicator, amber_marking) container.add_global(red_marking) # package has not been changed yet self.assertTrue(package.indicators[0].handling is None) self.assertTrue(package.stix_header is None or package.stix_header.handling is None) container.flush() # package has been changed by markings self.assertTrue(package.indicators[0].handling.marking[0] is not None) self.assertTrue(package.stix_header.handling.marking[0] is not None)
def test_local_marking_placement(self): """Test that marking an individual field whose parent or self object contains a handling structure is placed correctly.""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) indicator = Indicator(title="Test") # STIX 1.1.1 doesn't have multiple descriptions indicator.description = "Test description" package.add_indicator(indicator) container.add_marking(indicator.description, red_marking) self.assertTrue(package.indicators[0].handling is None) self.assertTrue(package.stix_header is None) container.flush() self.assertTrue(package.stix_header is None) self.assertTrue(package.indicators[0].handling.marking[0]. controlled_structure is not None)
def test_marking_round_trip(self): """Test that get_markings() yields the same number of results after calling to_xml().""" container = stixmarx.new() package = container.package red_marking = generate_marking_spec(generate_red_marking_struct()) amber_marking = generate_marking_spec(generate_amber_marking_struct()) incident = Incident(title="Test Incident") package.add_incident(incident) indicator = Indicator(idref="example:Indicator-test-1234") incident.related_indicators.append(indicator) container.add_marking(incident, red_marking, descendants=True) container.add_global(amber_marking) self.assertTrue(container.is_marked(indicator, red_marking)) self.assertTrue(container.is_marked(indicator, amber_marking)) markings = container.get_markings(indicator) self.assertEqual(len(markings), 2) xml = container.to_xml() sio = StringIO(xml.decode("utf-8")) new_xml_container = stixmarx.parse(sio) parsed_indicator = new_xml_container.package.incidents[ 0].related_indicators[0] parsed_markings = new_xml_container.get_markings(parsed_indicator) for x in parsed_markings: print(x.to_dict()) self.assertEqual(len(parsed_markings), 2)
def convert_bundle(bundle_obj): global _ID_OBJECT_MAPPING global _EXPLICIT_OBJECT_USED global _ID_NAMESPACE global _VICTIM_TARGET_TTPS global _KILL_CHAINS global CONTAINER _ID_OBJECT_MAPPING = {} _EXPLICIT_OBJECT_USED = {} _VICTIM_TARGET_TTPS = [] _KILL_CHAINS = {} if get_option_value("use_namespace"): option_value = get_option_value("use_namespace").split(" ") _ID_NAMESPACE = option_value[0] set_default_namespace(*option_value) CONTAINER = stixmarx.new() pkg = CONTAINER.package pkg.id_ = convert_id20(bundle_obj["id"]) for identity in (v for v in bundle_obj["objects"] if v["type"] == "identity"): debug("Found '%s'", 0, identity["id"]) i1x = convert_identity(identity) record_id_object_mapping(identity["id"], i1x, used=False) for marking_definition in (v for v in bundle_obj["objects"] if v["type"] == "marking-definition"): debug("Found '%s'", 0, marking_definition["id"]) m1x = convert_marking_definition(marking_definition) if not pkg.stix_header: pkg.stix_header = STIXHeader(handling=Marking()) pkg.stix_header.handling.add_marking(m1x) for o in bundle_obj["objects"]: if o["type"] == "attack-pattern": pkg.add_ttp(convert_attack_pattern(o)) elif o["type"] == "campaign": pkg.add_campaign(convert_campaign(o)) elif o["type"] == 'course-of-action': pkg.add_course_of_action(convert_coa(o)) elif o["type"] == "indicator": pkg.add_indicator(convert_indicator(o)) elif o["type"] == "intrusion-set": error( "Cannot convert STIX 2.0 content that contains intrusion-sets", 524) return None elif o["type"] == "malware": pkg.add_ttp(convert_malware(o)) elif o["type"] == "observed-data": pkg.add_observable(convert_observed_data(o)) elif o["type"] == "report": pkg.add_report(convert_report(o)) elif o["type"] == "threat-actor": pkg.add_threat_actor(convert_threat_actor(o)) elif o["type"] == "tool": pkg.add_ttp(convert_tool(o)) elif o["type"] == "vulnerability": pkg.add_exploit_target(convert_vulnerability(o)) # second passes for o in bundle_obj["objects"]: if o["type"] == "relationship": process_relationships(o) for o in bundle_obj["objects"]: if "created_by_ref" in o: process_created_by_ref(o) if "external_references" in o: create_references(o) for o in bundle_obj["objects"]: if o["type"] == "sighting": process_sighting(o) for k, v in _KILL_CHAINS.items(): pkg.ttps.kill_chains.append(v["kill_chain"]) CONTAINER.flush() CONTAINER = None return pkg