def main(): NAMESPACE = {"https://www.ncsc.gov.uk/": "ncscuk"} idgen.set_id_namespace(NAMESPACE) pkg = STIXPackage() coa = CourseOfAction() obj = file_to_obj('out.json') if obj.type == 'bundle': for _dict in obj.objects: object = dict_to_obj(_dict) if object.type == 'indicator': ind = Indicator() id_str = object.id.replace('--', '-') print id_str #ind.id_ = object.id pattern_type = object.pattern.split(':')[0] _value = re.sub("'", '', object.pattern.split(' = ')[1]) if pattern_type == 'ipv4-addr': obs = Observable( Address(address_value=_value, category=Address.CAT_IPV4)) elif pattern_type == 'url': obs = Observable(URI(value=_value, type_=URI.TYPE_URL)) pkg.add_observable(obs) obs_ref = Observable() obs_ref.id_ = None obs_ref.idref = obs.id_ ind.add_observable(obs_ref) pkg.add_indicator(ind) print pkg.to_xml()
def test_observble_init(self): obj = Object() dobj = ObjectProperties() a = Address() oc = ObservableComposition() e = Event() obs1 = Observable(obj) self.assertTrue(obs1.object_ is obj) self.assertFalse(obs1.observable_composition) self.assertFalse(obs1.event) obs2 = Observable(dobj) self.assertTrue(obs2.object_) self.assertTrue(obs2.object_.properties is dobj) self.assertFalse(obs2.observable_composition) self.assertFalse(obs2.event) obs3 = Observable(a) self.assertTrue(obs3.object_) self.assertTrue(obs3.object_.properties is a) self.assertFalse(obs3.event) self.assertFalse(obs3.observable_composition) obs4 = Observable(oc) self.assertFalse(obs4.object_) self.assertFalse(obs4.event) self.assertTrue(obs4.observable_composition is oc) obs5 = Observable(e) self.assertFalse(obs5.object_) self.assertTrue(obs5.event is e) self.assertFalse(obs5.observable_composition)
def main(): pkg = STIXPackage() file_object1 = File() file_object1.file_name = "readme.doc.exe" file_object1.size_in_bytes = 40891 file_object1.add_hash( Hash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" )) observable1 = Observable(file_object1) file_object2 = File() file_object2.file_name = "readme.doc.exe" file_object2.size_in_bytes = 40891 file_object2.add_hash( Hash("d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" )) observable2 = Observable(file_object2) incident = Incident(title="Malicious files detected") related_observable1 = RelatedObservable( observable1, relationship="Malicious Artifact Detected") related_observable2 = RelatedObservable( observable2, relationship="Malicious Artifact Detected") incident.related_observables.append(related_observable1) incident.related_observables.append(related_observable2) pkg.add_incident(incident) print(pkg.to_xml(encoding=None))
def generateIPObservable(indicator, attribute): indicator.add_indicator_type("IP Watchlist") address_object = resolveIPType(attribute["value"], attribute["type"]) address_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":AddressObject-" + attribute[ "uuid"] if ("|" in attribute["value"]): port = attribute["value"].split('|')[1] address_observable = Observable(address_object) address_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Address-" + attribute[ "uuid"] port_object = Port() port_object.port_value = attribute["value"].split('|')[1] port_object.port_value.condition = "Equals" port_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":PortObject-" + attribute[ "uuid"] port_observable = Observable(port_object) port_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Port-" + attribute[ "uuid"] compositeObject = ObservableComposition( observables=[address_observable, port_observable]) compositeObject.operator = "AND" observable = Observable( id_=cybox.utils.idgen.__generator.namespace.prefix + ":ObservableComposition-" + attribute["uuid"]) observable.observable_composition = compositeObject return observable else: return address_object
def returnAttachmentComposition(attribute): file_object = File() file_object.file_name = attribute["value"] file_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":FileObject-" + attribute[ "uuid"] observable = Observable() if "data" in attribute: artifact = Artifact(data=attribute["data"]) artifact.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ArtifactObject-" + attribute[ "uuid"] observable_artifact = Observable(artifact) observable_artifact.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-artifact-" + attribute[ "uuid"] observable_file = Observable(file_object) observable_file.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-file-" + attribute[ "uuid"] composition = ObservableComposition( observables=[observable_artifact, observable_file]) observable.observable_composition = composition else: observable = Observable(file_object) observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-" + attribute[ "uuid"] if attribute["comment"] != "": observable.description = attribute["comment"] return observable
def test_is_empty_observable(self): # Check to see if the cybox.core.Observable object is empty by calling `is_empty_observable` # Empty Observable test = Observable() self.assertTrue(utils.is_empty_observable(test)) # Observable is None test = None self.assertTrue(utils.is_empty_observable(test)) # Non empty Observable with Object test = Observable(MockObject()) self.assertFalse(utils.is_empty_observable(test)) # Non empty Observable with Event test = Observable(Event()) self.assertFalse(utils.is_empty_observable(test)) # Checks non empty observable_composition and observable_composition.observables test = Observable() obs = ObservableComposition() test.observable_composition = obs test.observable_composition.observables = [Observable()] self.assertFalse(utils.is_empty_observable(test))
def to_cybox(self, exclude=None): if exclude == None: exclude = [] observables = [] f = File() for attr in ['md5', 'sha1', 'sha256']: if attr not in exclude: val = getattr(self, attr, None) if val: setattr(f, attr, val) if self.ssdeep and 'ssdeep' not in exclude: f.add_hash(Hash(self.ssdeep, Hash.TYPE_SSDEEP)) if 'size' not in exclude and 'size_in_bytes' not in exclude: f.size_in_bytes = UnsignedLong(self.size) if 'filename' not in exclude and 'file_name' not in exclude: f.file_name = self.filename # create an Artifact object for the binary if it exists if 'filedata' not in exclude: data = self.filedata.read() if data: data = base64.b64encode(data) a = Artifact(data=data, type_=Artifact.TYPE_FILE) observables.append(Observable(a)) #if 'filetype' not in exclude and 'file_format' not in exclude: #NOTE: this doesn't work because the CybOX File object does not # have any support built in for setting the filetype to a # CybOX-binding friendly object (e.g., calling .to_dict() on # the resulting CybOX object fails on this field. #f.file_format = self.filetype observables.append(Observable(f)) return (observables, self.releasability)
def main(): data = json.load(open("data.json")) stix_package = STIXPackage(stix_header=STIXHeader( title=data['title'], package_intents='Incident')) ttps = {} for info in data['ips']: if info['bot'] not in ttps: ttps[info['bot']] = TTP(title=info['bot']) stix_package.add_ttp(ttps[info['bot']]) incident = Incident(title=info['ip']) incident.time = Time() incident.time.first_malicious_action = info['first_seen'] addr = Address(address_value=info['ip'], category=Address.CAT_IPV4) observable = Observable(item=addr) stix_package.add_observable(observable) related_ttp = RelatedTTP(TTP(idref=ttps[info['bot']].id_), relationship="Used Malware") incident.leveraged_ttps.append(related_ttp) related_observable = RelatedObservable( Observable(idref=observable.id_)) incident.related_observables.append(related_observable) stix_package.add_incident(incident) print(stix_package.to_xml(encoding=None))
def generateDomainIPObservable(indicator, attribute): indicator.add_indicator_type("Domain Watchlist") domain = attribute["value"].split('|')[0] ip = attribute["value"].split('|')[1] address_object = resolveIPType(ip, attribute["type"]) address_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":AddressObject-" + attribute[ "uuid"] address_observable = Observable(address_object) address_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Address-" + attribute[ "uuid"] domain_object = DomainName() domain_object.value = domain domain_object.value.condition = "Equals" domain_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":DomainNameObject-" + attribute[ "uuid"] domain_observable = Observable(domain_object) domain_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":DomainName-" + attribute[ "uuid"] compositeObject = ObservableComposition( observables=[address_observable, domain_observable]) compositeObject.operator = "AND" observable = Observable( id_=cybox.utils.idgen.__generator.namespace.prefix + ":ObservableComposition-" + attribute["uuid"]) observable.observable_composition = compositeObject return observable
def test_set_indicator_observables_to_list_of_one_observable(self): # https://github.com/STIXProject/python-stix/issues/325 i = Indicator() o1 = Observable() o2 = Observable() i.observables = [o1] self.assertEqual(type([]), type(i.observables)) self.assertEqual(1, len(i.observables))
def test_set_indicator_observables_to_list_of_two_observables(self): # https://github.com/STIXProject/python-stix/issues/325 i = Indicator() o1 = Observable() o2 = Observable() i.observables = [o1, o2] self.assertEqual(mixbox.typedlist.TypedList, type(i.observables)) self.assertEqual(2, len(i.observables))
def returnAttachmentComposition(attribute): file_object = File() file_object.file_name = attribute["value"] observable = Observable() if "data" in attribute: artifact = Artifact(data=attribute["data"]) composition = ObservableComposition( observables=[artifact, file_object]) observable.observable_composition = composition else: observable = Observable(file_object) return observable
def test_observables_property_composition(self): f1 = File() f1.file_name = "README.txt" f2 = File() f2.file_name = "README2.txt" obs1 = Observable(f1) obs2 = Observable(f2) comp = Observable(ObservableComposition('AND', [obs1, obs2])) ind = Indicator() ind.observable = comp ind2 = Indicator.from_dict(ind.to_dict()) self.assertEqual([obs1.to_dict(), obs2.to_dict()], [x.to_dict() for x in ind2.observables])
def create_url_observable(url): url_object = URI.from_dict({'value': url, 'type': URI.TYPE_URL}) url_observable = Observable(url_object) url_observable.title = "Malware Artifact - URL" url_observable.description = "URL derived from sandboxed malware sample." url_observable.short_description = "URL from malware." return url_observable
def process_sighting(o): if indicator_ref(o["sighting_of_ref"]): indicator_of_sighting = _ID_OBJECT_MAPPING[o["sighting_of_ref"]] if not indicator_of_sighting: warn("%s is not in this bundle. Referenced from %s", 308, o["sighting_of_ref"], o["id"]) return if not indicator_of_sighting.sightings: indicator_of_sighting.sightings = Sightings() if "where_sighted_refs" in o: for ref in o["where_sighted_refs"]: s = Sighting() indicator_of_sighting.sightings.append(s) if ref in _IDENTITIES: identity20_tuple = _IDENTITIES[ref] s.information_source = create_information_source( identity20_tuple) if "observed_data_refs" in o: # reference, regardless of whether its in the bundle or not s.related_observables = RelatedObservables() for od_ref in o["observed_data_refs"]: ro = RelatedObservable() s.related_observables.append(ro) ro.item = Observable(idref=convert_id20(od_ref)) # TODO: first_seen # TODO: last_seen else: warn( "Unable to convert STIX 2.0 sighting %s because it doesn't refer to an indicator", 508, o["sighings_of_ref"])
def create_stix_hash_observable(namespace, indicator): """ Create STIX file observable. Args: namespace: The XML namespace. indicator: The Demisto File indicator. Returns: STIX File observable. """ id_ = f'{namespace}:observable-{uuid.uuid4()}' value = indicator.get('value', '') type_ = indicator.get('indicator_type', '') file_object = cybox.objects.file_object.File() file_object.add_hash(indicator) observable = Observable( title=f'{value}: {type_}', id_=id_, item=file_object ) return [observable]
def create_stix_email_observable(namespace: str, indicator: dict) -> List[Observable]: """ Create STIX Email observable. Args: namespace: The XML namespace. indicator: The Demisto Email indicator. Returns: STIX Email observable. """ category = cybox.objects.address_object.Address.CAT_EMAIL type_ = indicator.get('indicator_type', '') value = indicator.get('value', '') id_ = f'{namespace}:observable-{uuid.uuid4()}' email_object = cybox.objects.address_object.Address( address_value=indicator.get('value', ''), category=category ) observable = Observable( title=f'{type_}: {value}', id_=id_, item=email_object ) return [observable]
def to_cybox_observable(self): """ Convert a Certificate to a CybOX Observables. Returns a tuple of (CybOX object, releasability list). To get the cybox object as xml or json, call to_xml() or to_json(), respectively, on the resulting CybOX object. """ custom_prop = Property( ) # make a custom property so CRITs import can identify Certificate exports custom_prop.name = "crits_type" custom_prop.description = "Indicates the CRITs type of the object this CybOX object represents" custom_prop._value = "Certificate" obj = File() # represent cert information as file obj.md5 = self.md5 obj.file_name = self.filename obj.file_format = self.filetype obj.size_in_bytes = self.size obj.custom_properties = CustomProperties() obj.custom_properties.append(custom_prop) obs = Observable(obj) obs.description = self.description data = self.filedata.read() if data: # if cert data available a = Artifact(data, Artifact.TYPE_FILE) # create artifact w/data a.packaging.append(Base64Encoding()) obj.add_related(a, "Child_Of") # relate artifact to file return ([obs], self.releasability)
def _dostix(hashes): '''This function creates a STIX packages containing hashes.''' print("[+] Creating STIX Package") title = SETTINGS['stix']['ind_title'] + " " + str(datetime.datetime.now()) _custom_namespace(SETTINGS['stix']['ns'], SETTINGS['stix']['ns_prefix']) stix_package = STIXPackage() stix_package.stix_header = STIXHeader() stix_package.stix_header.title = title stix_package.stix_header.handling = _marking() try: indicator = Indicator() indicator.set_producer_identity(SETTINGS['stix']['producer']) indicator.set_produced_time(indicator.timestamp) indicator.set_received_time(indicator.timestamp) indicator.add_kill_chain_phase(PHASE_DELIVERY) indicator.confidence = "Low" indicator.title = title indicator.add_indicator_type("File Hash Watchlist") indicator.description = SETTINGS['stix']['ind_desc'] try: indicator.add_indicated_ttp( TTP(idref=SETTINGS['indicated_ttp'], timestamp=indicator.timestamp)) indicator.suggested_coas.append( CourseOfAction(idref=SETTINGS['suggested_coa'], timestamp=indicator.timestamp)) except KeyError: pass for info in hashes: try: file_name = info['filename'] file_object = File() file_object.file_name = file_name file_object.file_name.condition = "Equals" file_object.file_extension = "." + file_name.split('.')[-1] file_object.file_extension.condition = "Equals" file_object.size_in_bytes = info['filesize'] file_object.size_in_bytes.condition = "Equals" file_object.file_format = info['fileformat'] file_object.file_format.condition = "Equals" file_object.add_hash(Hash(info['md5'])) file_object.add_hash(Hash(info['sha1'])) file_object.add_hash(Hash(info['sha256'])) file_object.add_hash(Hash(info['sha512'])) file_object.add_hash(Hash(info['ssdeep'], Hash.TYPE_SSDEEP)) for hashobj in file_object.hashes: hashobj.simple_hash_value.condition = "Equals" hashobj.type_.condition = "Equals" file_obs = Observable(file_object) file_obs.title = "File: " + file_name indicator.add_observable(file_obs) except TypeError: pass stix_package.add_indicator(indicator) return stix_package except KeyError: pass
def create_file_hash_observable(fn, hash_value): '''Create a CybOX Observable representing a file hash.''' hash_ = Hash(hash_value) file_ = File() file_.file_name = fn file_.add_hash(hash_) return Observable(file_)
def to_cybox_observable(self): """ Convert an IP to a CybOX Observables. Returns a tuple of (CybOX object, releasability list). To get the cybox object as xml or json, call to_xml() or to_json(), respectively, on the resulting CybOX object. """ obj = Address() obj.address_value = self.ip temp_type = self.ip_type.replace("-", "") if temp_type.find(Address.CAT_ASN.replace("-", "")) >= 0: obj.category = Address.CAT_ASN elif temp_type.find(Address.CAT_ATM.replace("-", "")) >= 0: obj.category = Address.CAT_ATM elif temp_type.find(Address.CAT_CIDR.replace("-", "")) >= 0: obj.category = Address.CAT_CIDR elif temp_type.find(Address.CAT_MAC.replace("-", "")) >= 0: obj.category = Address.CAT_MAC elif temp_type.find(Address.CAT_IPV4_NETMASK.replace("-", "")) >= 0: obj.category = Address.CAT_IPV4_NETMASK elif temp_type.find(Address.CAT_IPV4_NET.replace("-", "")) >= 0: obj.category = Address.CAT_IPV4_NET elif temp_type.find(Address.CAT_IPV4.replace("-", "")) >= 0: obj.category = Address.CAT_IPV4 elif temp_type.find(Address.CAT_IPV6_NETMASK.replace("-", "")) >= 0: obj.category = Address.CAT_IPV6_NETMASK elif temp_type.find(Address.CAT_IPV6_NET.replace("-", "")) >= 0: obj.category = Address.CAT_IPV6_NET elif temp_type.find(Address.CAT_IPV6.replace("-", "")) >= 0: obj.category = Address.CAT_IPV6 return ([Observable(obj)], self.releasability)
def create_email_address_observable(email_address): '''Create a CybOX Observable representing an IPv4 address''' email_address_object = Address.from_dict({ 'address_value': email_address, 'category': Address.CAT_EMAIL }) return Observable(email_address_object)
def create_domain_name_observable(domain_name): '''Create a CybOX Observable representing a domain name.''' domain_name_object = URI.from_dict({ 'value': domain_name, 'type': URI.TYPE_DOMAIN }) return Observable(domain_name_object)
def create_ipv4_observable(ipv4_address): '''Create a CybOX Observable representing an IPv4 address''' ipv4_object = Address.from_dict({ 'address_value': ipv4_address, 'category': Address.CAT_IPV4 }) return Observable(ipv4_object)
def add_object(self, object_): """Adds a python-cybox Object instance to the ``observables`` list property. This is the same as calling ``indicator.add_observable(object_)``. Note: If the `object` param is not an instance of ``cybox.core.Object`` an attempt will be made to to convert it into one before wrapping it in an ``cybox.core.Observable`` layer. Args: object_: An instance of ``cybox.core.Object`` or an object that can be converted into an instance of ``cybox.core.Observable`` Raises: ValueError: if the `object_` param cannot be converted to an instance of ``cybox.core.Observable``. """ if not object_: return observable = Observable(object_) self.add_observable(observable)
def create_stix_url_observable(namespace, indicator): """ Create STIX URL observable. Args: namespace: The XML namespace. indicator: The Demisto URL indicator. Returns: STIX URL observable. """ id_ = f'{namespace}:observable-{uuid.uuid4()}' value = indicator.get('value', '') uri_object = cybox.objects.uri_object.URI( value=value, type_=cybox.objects.uri_object.URI.TYPE_URL ) observable = Observable( title=f'URL: {value}', id_=id_, item=uri_object ) return [observable]
def test_add_related_observable(self): from cybox.core import Observable from stix.common.related import RelatedObservable i = self.klass() self.assertEqual(0, len(i.related_observables)) i.add_related_observable(Observable()) self.assertEqual(1, len(i.related_observables)) related = RelatedObservable(Observable()) i.add_related_observable(related) self.assertEqual(2, len(i.related_observables)) # Test that this fails self.assertRaises(TypeError, i.add_related_observable, "THIS SHOULD FAIL")
def test_id_idref_exclusive(self): o = Observable() self.assertTrue(o.id_ is not None) self.assertTrue(o.idref is None) o.idref = "foo" self.assertTrue(o.idref is not None) self.assertTrue(o.id_ is None)
def return_attachment_composition(self, attribute): file_object = File() file_object.file_name = attribute.value file_object.parent.id_ = "{}:FileObject-{}".format(self.namespace_prefix, attribute.uuid) if 'data' in attribute: observable_artifact = self.create_artifact_object(attribute, artifact="a") observable_file = Observable(file_object) observable_file.id_ = "{}:observable-file-{}".format(self.namespace_prefix, attribute.uuid) observable = Observable() composition = ObservableComposition(observables=[observable_artifact, observable_file]) observable.observable_composition = composition else: observable = Observable(file_object) observable.id_ = "{}:observable-{}".format(self.namespace_prefix, attribute.uuid) if attribute.comment: observable.description = attribute.comment return observable
def createArtifactObject(indicator, attribute): artifact = Artifact(data=attribute["data"]) artifact.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ArtifactObject-" + attribute[ "uuid"] observable = Observable(artifact) observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-artifact-" + attribute[ "uuid"] indicator.add_observable(observable)