def test_equal(self): # Tuple equality is provided for free by namedtuple. Every element must # be equal for the Namespaces to be seen as equal ns1 = Namespace("http://example.com/", "example", "") ns2 = Namespace("http://example.com/", "example", "") ns3 = Namespace("http://example.com", "example", "") self.assertEqual(ns1, ns2) self.assertNotEqual(ns1, ns3)
def merge_packages(package_list, namespace=None): '''Merge a list of input MAEC Packages and return a merged Package instance.''' malware_subjects = [] # Instantiate the ID generator class (for automatic ID generation) if not namespace: NS = Namespace("https://github.com/MAECProject/python-maec", "merged") else: NS = namespace maec.utils.set_id_namespace(NS) # Build the list of Malware Subjects for package in package_list: for malware_subject in package.malware_subjects: malware_subjects.append(malware_subject) # Merge the Malware Subjects merged_subjects = merge_malware_subjects(malware_subjects) # Merge the input namespace/schemaLocation dictionaries merged_namespaces = {} merged_schemalocations = {} for package in package_list: merged_namespaces.update(package.__input_namespaces__) merged_schemalocations.update(package.__input_schemalocations__) # Create a new Package with the merged Malware Subjects merged_package = Package() merged_package.malware_subjects = MalwareSubjectList(merged_subjects) merged_package.__input_namespaces__ = merged_namespaces merged_package.__input_schemalocations__ = merged_schemalocations return merged_package
def capecbuild(capecid): """Build a STIX package based on a CAPEC ID.""" data = _get_attack(capecid) if data: try: from stix.utils import set_id_namespace namespace = {NS: NS_PREFIX} set_id_namespace(namespace) except ImportError: from mixbox.idgen import set_id_namespace from mixbox.namespaces import Namespace namespace = Namespace(NS, NS_PREFIX, "") set_id_namespace(namespace) pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg.stix_header.handling = _marking() ttp = _buildttp(data) if data['related_attacks']: ttp.related_ttps.append( _buildttp(_get_attack(str(data['related_attacks'][0])))) pkg.add_ttp(ttp) xml = pkg.to_xml() title = pkg.id_.split(':', 1)[-1] if __name__ == '__main__': _postconstruct(xml, title) return xml
def test_set_semantics(self): nsset = NamespaceSet() self.assertEqual(0, len(nsset)) ns1 = Namespace("http://example.com/", "example", "") nsset.add(ns1) self.assertEqual(1, len(nsset)) # Adding the same namespace doesn't have an effect nsset.add(ns1) self.assertEqual(1, len(nsset)) # Neither does adding a new namespace object that is "equal" to the # first. nsset.add(Namespace("http://example.com/", "example", "")) self.assertEqual(1, len(nsset))
def test_schema_locations(self): ns = NamespaceSet() ns.add_namespace_uri("a:b:c", "abc", "sc:he:ma") self.assertEqual(ns.get_schema_location("a:b:c"), "sc:he:ma") self.assertRaises(mixbox.namespaces.ConflictingSchemaLocationError, ns.set_schema_location, "a:b:c", "other:schemaloc") self.assertRaises(mixbox.namespaces.ConflictingSchemaLocationError, ns.add_namespace, Namespace("a:b:c", "abc", "other:schemaloc")) self.assertRaises(mixbox.namespaces.ConflictingSchemaLocationError, ns.add_namespace_uri, "a:b:c", "abc", "other:schemaloc") self.assertRaises(mixbox.namespaces.NamespaceNotFoundError, ns.set_schema_location, "does:not:exist", "sc:he:ma") self.assertRaises(mixbox.namespaces.NamespaceNotFoundError, ns.get_schema_location, "does:not:exist") ns.set_schema_location("a:b:c", "sc:he:ma2", True) self.assertEqual(ns.get_schema_location("a:b:c"), "sc:he:ma2") # test schema location merging; these should not raise exceptions ns.add_namespace_uri("a:b:c", "abc", None) self.assertEqual(ns.get_schema_location("a:b:c"), "sc:he:ma2") ns.add_namespace_uri("d:e:f", "def", None) ns.add_namespace_uri("d:e:f", "def", "def:schema") self.assertEqual(ns.get_schema_location("d:e:f"), "def:schema") self.assertTrue(ns.is_valid())
def main(): mydata = loaddata() ''' Your Namespace ''' # NAMESPACE = {sanitizer(mydata["NSXURL"]) : (mydata["NS"])} # set_id_namespace(NAMESPACE) NAMESPACE = Namespace(sanitizer(mydata['NSXURL']), sanitizer(mydata['NS'])) set_id_namespace(NAMESPACE) # new ids will be prefixed by "myNS" wrapper = STIXPackage() info_src = InformationSource() info_src.identity = Identity(name=sanitizer(mydata["Identity"])) marking_specification = MarkingSpecification() marking_specification.controlled_structure = "//node() | //@*" tlp = TLPMarkingStructure() tlp.color = sanitizer(mydata["TLP_COLOR"]) marking_specification.marking_structures.append(tlp) handling = Marking() handling.add_marking(marking_specification) timestamp = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') MyTITLE = sanitizer(mydata["Title"]) SHORT = timestamp DESCRIPTION = sanitizer(mydata["Description"]) wrapper.stix_header = STIXHeader(information_source=info_src, title=MyTITLE, description=DESCRIPTION, short_description=SHORT) wrapper.stix_header.handling = handling indiDom = Indicator() indiDom.title = MyTITLE indiDom.add_indicator_type("IP Watchlist") for key in mydata["IOC"].keys(): myip = Address(address_value=sanitizer(key), category=Address.CAT_IPV4) myip.condition = "Equals" obsu = Observable(myip) #if mydata[key].size: for idx, mydata["IOC"][key] in enumerate(mydata["IOC"][key]): ioc = File() ioc.add_hash(sanitizer(mydata["IOC"][key])) myip.add_related(ioc, "Downloaded") indiDom.add_observable(obsu) wrapper.add_indicator(indiDom) print(wrapper.to_xml())
def cvebuild(var): """Search for a CVE ID and return a STIX formatted response.""" cve = CVESearch() data = json.loads(cve.id(var)) if data: try: from stix.utils import set_id_namespace namespace = {NS: NS_PREFIX} set_id_namespace(namespace) except ImportError: from stix.utils import idgen from mixbox.namespaces import Namespace namespace = Namespace(NS, NS_PREFIX, "") idgen.set_id_namespace(namespace) pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg.stix_header.handling = marking() # Define the exploit target expt = ExploitTarget() expt.title = data['id'] expt.description = data['summary'] # Add the vulnerability object to the package object expt.add_vulnerability(vulnbuild(data)) # Do some TTP stuff with CAPEC objects try: for i in data['capec']: ttp = TTP() ttp.title = "CAPEC-" + str(i['id']) ttp.description = i['summary'] ttp.exploit_targets.append(ExploitTarget(idref=expt.id_)) pkg.add_ttp(ttp) except KeyError: pass # Do some weakness stuff if data['cwe'] != 'Unknown': weak = Weakness() weak.cwe_id = data['cwe'] expt.add_weakness(weak) # Add the exploit target to the package object pkg.add_exploit_target(expt) xml = pkg.to_xml() # If the function is not imported then output the xml to a file. if __name__ == '__main__': title = pkg.id_.split(':', 1)[-1] with open(title + ".xml", "w") as text_file: text_file.write(xml) return xml
def cvebuild(var): """Search for a CVE ID and return a STIX formatted response.""" cve = CVESearch() data = json.loads(cve.id(var)) if data: try: from stix.utils import set_id_namespace namespace = {NS: NS_PREFIX} set_id_namespace(namespace) except ImportError: from mixbox.idgen import set_id_namespace from mixbox.namespaces import Namespace namespace = Namespace(NS, NS_PREFIX, "") set_id_namespace(namespace) pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg = STIXPackage() pkg.stix_header = STIXHeader() pkg.stix_header.handling = _marking() # Define the exploit target expt = ExploitTarget() expt.title = data['id'] expt.description = data['summary'] expt.information_source = InformationSource(identity=Identity( name="National Vulnerability Database")) # Add the vulnerability object to the package object expt.add_vulnerability(_vulnbuild(data)) # Add the COA object to the ET object for coa in COAS: expt.potential_coas.append( CourseOfAction(idref=coa['id'], timestamp=expt.timestamp)) # Do some TTP stuff with CAPEC objects if TTPON is True: try: for i in data['capec']: pkg.add_ttp(_buildttp(i, expt)) except KeyError: pass expt.add_weakness(_weakbuild(data)) # Add the exploit target to the package object pkg.add_exploit_target(expt) xml = pkg.to_xml() title = pkg.id_.split(':', 1)[-1] # If the function is not imported then output the xml to a file. if __name__ == '__main__': _postconstruct(xml, title) return xml else: sys.exit("[-] Error retrieving details for " + var)
def __init__(self): # namespace dictionary self.ns_dict = { SNSConfig.get_stix_ns_url(): SNSConfig.get_stix_ns_name(), } ns_ctim_sns = Namespace(SNSConfig.get_stix_ns_url(), SNSConfig.get_stix_ns_name(), schema_location=None) # id generator idgen.set_id_namespace(ns_ctim_sns) self.generator = idgen._get_generator()
def _custom_namespace(url, alias): try: from stix.utils import set_id_namespace namespace = {url: alias} set_id_namespace(namespace) except ImportError: from mixbox.namespaces import Namespace from stix.utils import idgen namespace = Namespace(url, alias, "") idgen.set_id_namespace(namespace)
def test_namedtuple(self): # Verify behavior of the namedtuple (mainly, that you can access # attributes but not modify them. ns = Namespace("http://example.com/", "example", "") self.assertEqual("http://example.com/", ns.name) self.assertEqual("example", ns.prefix) self.assertEqual("", ns.schema_location) self.assertRaises(AttributeError, setattr, ns, 'name', "urn:example") self.assertRaises(AttributeError, setattr, ns, 'prefix', "example") self.assertRaises(AttributeError, setattr, ns, 'schema_location', "")
def __init__( self, identity_name=DEFAULT_IDENTITY_NAME, ns_url=DEFAULT_NS_URL, ns_name=DEFAULT_NS_NAME, ): self.identity_name = identity_name self.events = [] ns_ctim_sns = Namespace(ns_url, ns_name, schema_location=None) idgen.set_id_namespace(ns_ctim_sns) self.generator = idgen._get_generator()
def test_set_semantics(self): nsset = NamespaceSet() self.assertEqual(0, len(nsset)) ns1 = Namespace("http://example.com/", "example", "") nsset.add_namespace(ns1) self.assertEqual(1, len(nsset)) # Adding the same namespace doesn't have an effect nsset.add_namespace(ns1) self.assertEqual(1, len(nsset)) # Neither does adding a new namespace object that is "equal" to the # first. nsset.add_namespace(Namespace("http://example.com/", "example", "")) self.assertEqual(1, len(nsset)) # Adding a prefix doesn't change the set size nsset.add_namespace_uri("http://example.com/", "example2") self.assertEqual(1, len(nsset)) self.assertTrue(nsset.contains_namespace("http://example.com/")) self.assertTrue(nsset.is_valid())
def __init__(self, config, dom): self.protocol_to_port_mapping = dict( modbus=502, snmp=161, http=80, s7comm=102, ) port_path_list = map(lambda x: '//conpot_template/protocols/'+x+'/@port', self.protocol_to_port_mapping.keys()) for port_path in port_path_list: try: protocol_port = ast.literal_eval(dom.xpath(port_path)[0]) protocol_name = port_path.rsplit("/", 2)[1] self.protocol_to_port_mapping[protocol_name] = protocol_port except IndexError: continue conpot_namespace = Namespace(CONPOT_NAMESPACE_URL, CONPOT_NAMESPACE, '') idgen.set_id_namespace(conpot_namespace)
def test_prefixes(self): ns = NamespaceSet() ns.add_namespace_uri("a:b:c", "pfx") ns.add_namespace_uri("a:b:c", "pfx2") ns.add_prefix("a:b:c", "pfx3") self.assertEqual(len(ns.get_prefixes("a:b:c")), 3) self.assertTrue(ns.is_valid()) ns.remove_prefix("pfx3") self.assertEqual(len(ns.get_prefixes("a:b:c")), 2) self.assertTrue(ns.is_valid()) # Make sure prefix_iter() gives the same prefixes as get_prefixes(). self.assertEqual(len(ns.get_prefixes("a:b:c")), len(list(ns.prefix_iter("a:b:c")))) #self.assertTrue(all(map(operator.eq, ns.get_prefixes("a:b:c"), # ns.prefix_iter("a:b:c")))) # One time, I saw the above test code fail. I never saw it again. # Seems like the prefixes may have come out in a different order or # something... guess I'll play it safe and copy them to sorted # lists before comparing. pfxs1 = sorted(ns.get_prefixes("a:b:c")) pfxs2 = sorted(ns.prefix_iter("a:b:c")) self.assertTrue(all(map(operator.eq, pfxs1, pfxs2))) self.assertEqual(ns.namespace_for_prefix("pfx"), "a:b:c") self.assertEqual(ns.namespace_for_prefix("pfx2"), "a:b:c") # Should get an exception if we try to map the same prefix to a # different namespace. self.assertRaises(mixbox.namespaces.DuplicatePrefixError, ns.add_namespace_uri, "x:y:z", "pfx") self.assertRaises(mixbox.namespaces.DuplicatePrefixError, ns.add_namespace, Namespace("x:y:z", "pfx", None)) self.assertRaises(mixbox.namespaces.NamespaceNotFoundError, ns.get_prefixes, "does:not:exist") self.assertRaises(mixbox.namespaces.NamespaceNotFoundError, ns.prefix_iter, "does:not:exist") self.assertRaises(mixbox.namespaces.NamespaceNotFoundError, ns.add_prefix, "does:not:exist", "dne") ns.remove_prefix("does:not:exist") self.assertTrue(ns.is_valid())
iocs = { 'title': stixTitle, 'desc': stixDescription, 'hash': file_hashes, 'fname': filenames, 'ips': ip_addresses, 'urls': urls, 'subject': email_subjects, 'senders': email_sender, 'domains': domain } # disable warning 'The use of this field has been deprecated' - STIXHeader() warnings.filterwarnings("ignore") NAMESPACE = Namespace("http://bimb.com/stix", "bimb") set_id_namespace(NAMESPACE) def main(iocs=iocs): stix_header = STIXHeader(title=iocs['title'], description=iocs['desc'], package_intents=["Indicators - Watchlist"]) stix_package = STIXPackage(stix_header=stix_header) # add indicator - file hash if iocs.get('hash'): indicator_file_hash = Indicator(title="Malicious File") indicator_file_hash.add_indicator_type("File Hash Watchlist")
# Copyright (c) 2015, The MITRE Corporation. All rights reserved. # See LICENSE.txt for complete terms. from mixbox.namespaces import Namespace, NamespaceSet, register_namespace NS_CYBOX_CORE = Namespace('http://cybox.mitre.org/cybox-2', 'cybox', 'http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd') NS_CYBOX_COMMON = Namespace('http://cybox.mitre.org/common-2', 'cyboxCommon', 'http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd') NS_CYBOX_VOCABS = Namespace('http://cybox.mitre.org/default_vocabularies-2', 'cyboxVocabs', 'http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd') NS_ACCOUNT_OBJECT = Namespace('http://cybox.mitre.org/objects#AccountObject-2', 'AccountObj', 'http://cybox.mitre.org/XMLSchema/objects/Account/2.1/Account_Object.xsd') NS_ADDRESS_OBJECT = Namespace('http://cybox.mitre.org/objects#AddressObject-2', 'AddressObj', 'http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd') NS_API_OBJECT = Namespace('http://cybox.mitre.org/objects#APIObject-2', 'APIObj', 'http://cybox.mitre.org/XMLSchema/objects/API/2.1/API_Object.xsd') NS_ARCHIVEFILE_OBJECT = Namespace('http://cybox.mitre.org/objects#ArchiveFileObject-1', 'ArchiveFileObj', 'http://cybox.mitre.org/XMLSchema/objects/Archive_File/1.0/Archive_File_Object.xsd') NS_ARPCACHE_OBJECT = Namespace('http://cybox.mitre.org/objects#ARPCacheObject-1', 'ARPCacheObj', 'http://cybox.mitre.org/XMLSchema/objects/ARP_Cache/1.0/ARP_Cache_Object.xsd') NS_ARTIFACT_OBJECT = Namespace('http://cybox.mitre.org/objects#ArtifactObject-2', 'ArtifactObj', 'http://cybox.mitre.org/XMLSchema/objects/Artifact/2.1/Artifact_Object.xsd') NS_AS_OBJECT = Namespace('http://cybox.mitre.org/objects#ASObject-1', 'ASObj', 'http://cybox.mitre.org/XMLSchema/objects/AS/1.0/AS_Object.xsd') NS_CODE_OBJECT = Namespace('http://cybox.mitre.org/objects#CodeObject-2', 'CodeObj', 'http://cybox.mitre.org/XMLSchema/objects/Code/2.1/Code_Object.xsd') NS_CUSTOM_OBJECT = Namespace('http://cybox.mitre.org/objects#CustomObject-1', 'CustomObj', 'http://cybox.mitre.org/XMLSchema/objects/Custom/1.1/Custom_Object.xsd') NS_DEVICE_OBJECT = Namespace('http://cybox.mitre.org/objects#DeviceObject-2', 'DeviceObj', 'http://cybox.mitre.org/XMLSchema/objects/Device/2.1/Device_Object.xsd') NS_DISK_OBJECT = Namespace('http://cybox.mitre.org/objects#DiskObject-2', 'DiskObj', 'http://cybox.mitre.org/XMLSchema/objects/Disk/2.1/Disk_Object.xsd') NS_DISKPARTITION_OBJECT = Namespace('http://cybox.mitre.org/objects#DiskPartitionObject-2', 'DiskPartitionObj', 'http://cybox.mitre.org/XMLSchema/objects/Disk_Partition/2.1/Disk_Partition_Object.xsd') NS_DNSCACHE_OBJECT = Namespace('http://cybox.mitre.org/objects#DNSCacheObject-2', 'DNSCacheObj', 'http://cybox.mitre.org/XMLSchema/objects/DNS_Cache/2.1/DNS_Cache_Object.xsd') NS_DNSQUERY_OBJECT = Namespace('http://cybox.mitre.org/objects#DNSQueryObject-2', 'DNSQueryObj', 'http://cybox.mitre.org/XMLSchema/objects/DNS_Query/2.1/DNS_Query_Object.xsd') NS_DNSRECORD_OBJECT = Namespace('http://cybox.mitre.org/objects#DNSRecordObject-2', 'DNSRecordObj', 'http://cybox.mitre.org/XMLSchema/objects/DNS_Record/2.1/DNS_Record_Object.xsd') NS_DOMAINNAME_OBJECT = Namespace('http://cybox.mitre.org/objects#DomainNameObject-1', 'DomainNameObj', 'http://cybox.mitre.org/XMLSchema/objects/Domain_Name/1.0/Domain_Name_Object.xsd') NS_EMAILMESSAGE_OBJECT = Namespace('http://cybox.mitre.org/objects#EmailMessageObject-2', 'EmailMessageObj', 'http://cybox.mitre.org/XMLSchema/objects/Email_Message/2.1/Email_Message_Object.xsd') NS_FILE_OBJECT = Namespace('http://cybox.mitre.org/objects#FileObject-2', 'FileObj', 'http://cybox.mitre.org/XMLSchema/objects/File/2.1/File_Object.xsd') NS_GUIDIALOGBOX_OBJECT = Namespace('http://cybox.mitre.org/objects#GUIDialogboxObject-2', 'GUIDialogboxObj', 'http://cybox.mitre.org/XMLSchema/objects/GUI_Dialogbox/2.1/GUI_Dialogbox_Object.xsd') NS_GUI_OBJECT = Namespace('http://cybox.mitre.org/objects#GUIObject-2', 'GUIObj', 'http://cybox.mitre.org/XMLSchema/objects/GUI/2.1/GUI_Object.xsd') NS_GUIWINDOW_OBJECT = Namespace('http://cybox.mitre.org/objects#GUIWindowObject-2', 'GUIWindowObj', 'http://cybox.mitre.org/XMLSchema/objects/GUI_Window/2.1/GUI_Window_Object.xsd') NS_HOSTNAME_OBJECT = Namespace('http://cybox.mitre.org/objects#HostnameObject-1', 'HostnameObj', 'http://cybox.mitre.org/XMLSchema/objects/Hostname/1.0/Hostname_Object.xsd') NS_HTTPSESSION_OBJECT = Namespace('http://cybox.mitre.org/objects#HTTPSessionObject-2', 'HTTPSessionObj', 'http://cybox.mitre.org/XMLSchema/objects/HTTP_Session/2.1/HTTP_Session_Object.xsd')
def main(): ###################################################################### # MODIFICARE LE VARIABILI SEGUENTI # Il title e' ID univoco della minaccia (es. Cobalt / Danabot / APT28) MyTITLE = "GandCrab" # La description strutturiamola come segue # <IOC PRODUCER> - <Descrizione della minaccia/campagna> - <URL (if any)> DESCRIPTION = "CERT-PA - Nuova campagna di Cyber-Estorsione basata su ransomware GandCrab - https://www.cert-pa.it/notizie/nuova-campagna-di-cyber-estorsione-basata-su-ransomware-gandcrab/" # La sorgente che ha generato l'IoC con riferimento a Cyber Saiyan Community IDENTITY = "CERT-PA via Cyber Saiyan Community" # ###################################################################### # Build STIX file info_src = InformationSource() info_src.identity = Identity(name=IDENTITY) NAMESPACE = Namespace("https://infosharing.cybersaiyan.it", "CYBERSAIYAN") set_id_namespace(NAMESPACE) timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S') SHORT = timestamp wrapper = STIXPackage() marking_specification = MarkingSpecification() marking_specification.controlled_structure = "//node() | //@*" tlp = TLPMarkingStructure() tlp.color = "WHITE" marking_specification.marking_structures.append(tlp) handling = Marking() handling.add_marking(marking_specification) wrapper.stix_header = STIXHeader(information_source=info_src, title=MyTITLE.encode(encoding='UTF-8', errors='replace'), description=DESCRIPTION.encode(encoding='UTF-8', errors='replace'), short_description=SHORT.encode(encoding='UTF-8', errors='replace')) wrapper.stix_header.handling = handling # HASH indicators indicatorHASH = Indicator() indicatorHASH.title = MyTITLE + " - HASH" indicatorHASH.add_indicator_type("File Hash Watchlist") # DOMAIN indicators indiDOMAIN = Indicator() indiDOMAIN.title = MyTITLE + " - DOMAIN" indiDOMAIN.add_indicator_type("Domain Watchlist") # URL indicators indiURL = Indicator() indiURL.title = MyTITLE + " - URL" indiURL.add_indicator_type("URL Watchlist") # IP indicators indiIP = Indicator() indiIP.title = MyTITLE + " - IP" indiIP.add_indicator_type("IP Watchlist") # EMAIL indicators indiEMAIL = Indicator() indiEMAIL.title = MyTITLE + " - EMAIL" indiEMAIL.add_indicator_type("Malicious E-mail") # Read IoC file file_ioc = "CS-ioc.txt" ioc = loaddata(file_ioc) print "Reading IoC file..." for idx, ioc in enumerate(ioc): notfound = 1 # sha256 p = re.compile(r"^[0-9a-f]{64}$", re.IGNORECASE) m = p.match(ioc) if m and notfound: filei = File() filei.add_hash(Hash(ioc)) obsi = Observable(filei) indicatorHASH.add_observable(obsi) print "SHA256: " + ioc notfound = 0 #md5 p = re.compile(r"^[0-9a-f]{32}$", re.IGNORECASE) m = p.match(ioc) if m and notfound: filej = File() filej.add_hash(Hash(ioc)) obsj = Observable(filej) indicatorHASH.add_observable(obsj) print "MD5: " + ioc notfound = 0 #sha1 p = re.compile(r"^[0-9a-f]{40}$", re.IGNORECASE) m = p.match(ioc) if m and notfound: filek = File() filek.add_hash(Hash(ioc)) obsk = Observable(filek) indicatorHASH.add_observable(obsk) print "SHA1: " + ioc notfound = 0 #domains if validators.domain(ioc) and notfound: url = URI() url.value = ioc url.type_ = URI.TYPE_DOMAIN url.condition = "Equals" obsu = Observable(url) indiDOMAIN.add_observable(obsu) print "DOMAIN: " + ioc notfound = 0 #url if validators.url(ioc) and notfound: url = URI() url.value = ioc url.type_ = URI.TYPE_URL url.condition = "Equals" obsu = Observable(url) indiURL.add_observable(obsu) print "URL: " + ioc notfound = 0 #ip if validators.ipv4(ioc) and notfound: ip = Address() ip.address_value = ioc obsu = Observable(ip) indiIP.add_observable(obsu) print "IP: " + ioc notfound = 0 # add all indicators to STIX wrapper.add_indicator(indicatorHASH) wrapper.add_indicator(indiDOMAIN) wrapper.add_indicator(indiURL) wrapper.add_indicator(indiIP) wrapper.add_indicator(indiEMAIL) # print STIX file to stdout print "Writing STIX package: package.stix" f = open ("package.stix", "w") f.write (wrapper.to_xml()) f.close () print
_XSI_TYPE = "AIS:AISMarkingStructure" is_proprietary = fields.TypedField("Is_Proprietary", IsProprietary) not_proprietary = fields.TypedField("Not_Proprietary", NotProprietary) def __init__(self, is_proprietary=None, not_proprietary=None): super(AISMarkingStructure, self).__init__() self.is_proprietary = is_proprietary self.not_proprietary = not_proprietary NAMESPACES = [ Namespace( 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2', 'AIS', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/AIS_Bundle_Marking_1.1.1_v1.0.xsd' ) ] def _update_namespaces(): # Update the python-stix namespace dictionary from stix.utils import nsparser import mixbox.namespaces nsparser.STIX_NAMESPACES.add_namespace(NAMESPACES[0]) mixbox.namespaces.register_namespace(NAMESPACES[0]) _update_namespaces()
from stix.core import STIXPackage from mixbox.idgen import set_id_namespace from mixbox.namespaces import Namespace from stix.indicator import Indicator from cybox.core import Observable from cybox.objects.address_object import Address from cybox.objects.file_object import File from cybox.common import Hash from cybox.objects.uri_object import URI from cybox.objects.win_registry_key_object import WinRegistryKey #from cybox.objects.domain_name_object import DomainName OUTPUT_FORMATS = ('csv', 'json', 'yara', 'autofocus', 'stix') #NAMESPACE = {"http://www.cert.gov.uk" : "certuk"} NAMESPACE = Namespace("http://www.cert.gov.uk", "certuk") set_id_namespace(NAMESPACE) stix_package = STIXPackage() add_ind_list = [] ind_ip = Indicator() ind_ip.add_indicator_type("IP Watchlist") ind_file = Indicator() ind_file.add_indicator_type("File Hash Watchlist") ind_url = Indicator() ind_url.add_indicator_type("URL Watchlist") ind_domain = Indicator()
def load_stix(stix): # Just save the pain and load it if the first character is a < log.debug("Loading STIX...") if sys.version_info < (3, 5): json_exception = ValueError else: json_exception = json.JSONDecodeError if isinstance(stix, STIXPackage): log.debug("Argument was already STIX package, ignoring.") # Oh cool we're ok # Who tried to load this? Honestly. return stix elif hasattr(stix, 'read'): log.debug("Argument has 'read' attribute, assuming file-like.") # It's a file! # But somehow, sometimes, reading it returns a bytes stream # and the loader dies on python 3.4. # Luckily, STIXPackage.from_json (which is mixbox.Entity.from_json) # will happily load a string. # So we're going to play dirty. data = stix.read() log.debug("Read file, type %s.", type(data)) if isinstance(data, bytes): data = data.decode() try: log.debug("Attempting to load from JSON...") # Try loading from JSON stix_package = STIXPackage.from_json(data) except json_exception: log.debug("Attempting to load from XML...") # Ok then try loading from XML # Loop zoop # Read the STIX into an Etree stix.seek(0) stix_xml = etree.fromstring(stix.read()) ns_map = stix_xml.nsmap # Remove any "marking" sections because the US-Cert is evil log.debug("Removing Marking elements...") pattern = ".//{http://data-marking.mitre.org/Marking-1}Marking" for element in stix_xml.findall(pattern): element.getparent().remove(element) log.debug("Writing cleaned XML to Tempfile") f = SpooledTemporaryFile(max_size=10 * 1024) f.write(etree.tostring(stix_xml)) f.seek(0) # Pray to anything you hold sacred ns_objmap = map(lambda x: Namespace(ns_map[x], x), ns_map) for ns in ns_objmap: log.debug("Trying to add namespace %s", ns) try: nsparser.STIX_NAMESPACES.add_namespace(ns) mixbox.namespaces.register_namespace(ns) except Exception as ex: log.exception(ex) try: log.debug("Attempting to read clean XML into STIX...") stix_package = STIXPackage.from_xml(f) except Exception as ex: # No joy. Quit. log.fatal("Could not :<") log.exception(ex) f.seek(0) with open("FAILED_STIX.xml", "wb") as g: g.write(f.read()) raise STIXLoadError("Could not load stix file. {}".format(ex)) return stix_package elif isinstance(stix, (str, bytes)): if isinstance(stix, bytes): stix = stix.decode() # It's text, we'll need to use a temporary file # Create a temporary file to load from # Y'know I should probably give it a max size before jumping to disk # idk, 10MB? Sounds reasonable. f = SpooledTemporaryFile(max_size=10 * 1024) # O I have idea for sneak # Will be very sneak # Write the (probably) XML to file f.write(stix.encode("utf-8")) # Reset the file so we can read from it f.seek(0) # AHA SNEAK DIDN'T EXPECT RECURSION DID YOU return load_stix(f)
def setUp(self): ioc_ns = Namespace( "http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1", "stix-openioc", '') idgen.set_id_namespace(ioc_ns)
def main(): ###################################################################### # MODIFICARE LE VARIABILI SEGUENTI MyTITLE = "APT28 / Fancy Bear" DESCRIPTION = "Emanuele De Lucia - APT28 / Fancy Bear still targeting military institutions - https://www.emanueledelucia.net/apt28-targeting-military-institutions/" sha256 = [] md5 = [ '43D7FFD611932CF51D7150B176ECFC29', '549726B8BFB1919A343AC764D48FDC81' ] sha1 = [] domains = ['beatguitar.com'] urls = [ 'https://beatguitar.com/aadv/gJNn/X2/ep/VQOA/3.SMPTE292M/?ct=+lMQKtXi0kf+3MVk38U=', 'https://beatguitar.com/n2qqSy/HPSe0/SY/yAsFy8/mSaYZP/lw.sip/?n=VxL0BnijNmtTnSFIcoQ=' ] ips = ['185.99.133.72'] emails = [] ###################################################################### # Costruzione STIX file NAMESPACE = Namespace("https://infosharing.cybersaiyan.it", "CYBERSAIYAN") set_id_namespace(NAMESPACE) timestamp = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') SHORT = timestamp wrapper = STIXPackage() info_src = InformationSource() info_src.identity = Identity(name="CyberSaiyan Community") marking_specification = MarkingSpecification() marking_specification.controlled_structure = "//node() | //@*" tlp = TLPMarkingStructure() tlp.color = "WHITE" marking_specification.marking_structures.append(tlp) handling = Marking() handling.add_marking(marking_specification) wrapper.stix_header = STIXHeader(information_source=info_src, title=MyTITLE, description=DESCRIPTION, short_description=SHORT) wrapper.stix_header.handling = handling # HASH indicators indicatorHASH = Indicator() indicatorHASH.title = MyTITLE + " - HASH" indicatorHASH.add_indicator_type("File Hash Watchlist") for idx, sha256 in enumerate(sha256): filei = File() filei.add_hash(Hash(sha256)) obsi = Observable(filei) indicatorHASH.add_observable(obsi) for idx, md5 in enumerate(md5): filej = File() filej.add_hash(Hash(md5)) obsj = Observable(filej) indicatorHASH.add_observable(obsj) for idx, sha1 in enumerate(sha1): filek = File() filek.add_hash(Hash(sha1)) obsk = Observable(filek) indicatorHASH.add_observable(obsk) # DOMAIN indicators indiDOMAIN = Indicator() indiDOMAIN.title = MyTITLE + " - DOMAIN" indiDOMAIN.add_indicator_type("Domain Watchlist") for idu, domains in enumerate(domains): url = URI() url.value = domains url.type_ = URI.TYPE_DOMAIN url.condition = "Equals" obsu = Observable(url) indiDOMAIN.add_observable(obsu) # URL indicators indiURL = Indicator() indiURL.title = MyTITLE + " - URL" indiURL.add_indicator_type("URL Watchlist") for idu, urls in enumerate(urls): url = URI() url.value = urls url.type_ = URI.TYPE_URL url.condition = "Equals" obsu = Observable(url) indiURL.add_observable(obsu) # IP indicators indiIP = Indicator() indiIP.title = MyTITLE + " - IP" indiIP.add_indicator_type("IP Watchlist") for idu, ips in enumerate(ips): ip = Address() ip.address_value = ips obsu = Observable(ip) indiIP.add_observable(obsu) # EMAIL indicators indiEMAIL = Indicator() indiEMAIL.title = MyTITLE + " - EMAIL" indiEMAIL.add_indicator_type("Malicious E-mail") for idu, emails in enumerate(emails): email = EmailAddress() email.address_value = emails obsu = Observable(email) indiEMAIL.add_observable(obsu) # add all indicators wrapper.add_indicator(indicatorHASH) wrapper.add_indicator(indiDOMAIN) wrapper.add_indicator(indiURL) wrapper.add_indicator(indiIP) wrapper.add_indicator(indiEMAIL) print(wrapper.to_xml())
from cybox.objects.file_object import File from stix.exploit_target import Vulnerability from cybox.objects.mutex_object import Mutex from cybox.common import Hash from stix.indicator import Indicator, CompositeIndicatorExpression from stix.common import InformationSource, Identity from cybox.common import Time from lxml import etree as et from stix.common.vocabs import PackageIntent from stix.core import STIXPackage from mixbox.idgen import set_id_namespace from mixbox.namespaces import Namespace from IPy import * PULSE_SERVER_BASE = "https://otx.alienvault.com/" STIXNAMESPACE = Namespace("https://otx.alienvault.com", "alienvault-otx") set_id_namespace(STIXNAMESPACE) class StixExport: def __init__(self, pulse): self.stix_package = STIXPackage() self.stix_header = STIXHeader() self.pulse = pulse self.hash_translation = { "FileHash-MD5": Hash.TYPE_MD5, "FileHash-SHA1": Hash.TYPE_SHA1, "FileHash-SHA256": Hash.TYPE_SHA256 } self.address_translation = { "IPv4": Address.CAT_IPV4,
# Copyright (c) 2017, The MITRE Corporation. All rights reserved. # See LICENSE.txt for complete terms. from mixbox.namespaces import Namespace ISA_NAMESPACES = [ # ISA v2/EDH v3 Namespace( 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ISAMarkingsAssertionsType.v2.xsd', 'isam-assert-v2', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ISAMarkingsAssertionsType.v2.xsd' ), Namespace( 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ISAMarkingsType.v2.xsd', 'isam-v2', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ISAMarkingsType.v2.xsd' ), Namespace( 'urn:edm:edh:cyber:v3', 'edh-v3', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/SD-EDH_Profile_Cyber.v3.xsd' ) ]
def init_id_namespace(): # setup namespace... short_namespace = "openioc" namespace = Namespace("http://openioc.org/", short_namespace, "") set_id_namespace(namespace)
def main(): # define constants TI_REQUEST_URL = "https://api.intelgraph.idefense.com/rest/threatindicator/v0" # iDefense API Key # To avoid hard-coding creds, I'm using environment variables if os.environ.get('IDEF_TOKEN') is None: print( "error: please store your iDefense IntelGraph API key in the IDEF_TOKEN environment" ) sys.exit(1) API_KEY = os.environ.get('IDEF_TOKEN') API_SECRET = '' # TODO: use command-line parameter timestr = datetime.datetime.utcnow() - datetime.timedelta(days=1) LAST_IMPORT = timestr.strftime("%Y-%m-%dT%H:%M:%S") + ".000Z" HEADERS = { "Content-Type": "application/json", "auth-token": API_KEY, "X-Api-Key-Proof": API_SECRET } print(HEADERS) page = 1 more_data = True count = 0 # Set namespace NAMESPACE = Namespace("https://intelgraph.idefense.com", "idefense") set_id_namespace(NAMESPACE) # Create STIX Package stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = "iDefense Threat Indicators Feed" stix_package.stix_header = stix_header ttps = {} malware = {} try: while more_data: request_payload = { "start_date": LAST_IMPORT, "page_size": 200, "page": page } r = requests.post(TI_REQUEST_URL, headers=HEADERS, data=json.dumps(request_payload)) print(r) response = [] if r.status_code == requests.codes.ok: try: # Read in response as json response = r.json() except (ValueError, KeyError): print("Response couldn't be decoded :(") more_data = False continue more_data = response.get('more', 'False') print("Page %d ==> %s (%s)" % (page, response['more'], response['total_size'])) page += 1 # Iterate the response for indicatorD in response['results']: count += 1 # Indicator value such as the value of the IP/Domain/URL indicator = indicatorD.get('key') print(indicator, indicatorD.get('type')) if indicatorD.get('last_seen_as') is None: last_seen_as = 'UNKNOWN' else: last_seen_as = ''.join(indicatorD.get('last_seen_as')) # Identify TTP if last_seen_as not in ttps: ttps[last_seen_as] = TTP(title=last_seen_as) stix_package.add_ttp(ttps[last_seen_as]) # Identify malware source if 'files' in indicatorD: for hashD in indicatorD['files']: md5 = hashD.get('key') # Malware Family classification of the hash if available if hashD.get('malware_family') is None: malware_family = "Unknown" else: malware_family = ''.join( hashD.get('malware_family')) if md5 not in malware: malware[md5] = add_malware( md5, malware_family, hashD.get('uuid')) if indicatorD.get('type') == "url": # Create indicator indicator = Indicator( id_="indicator-{0}".format(indicatorD.get('uuid')), title=''.join(indicatorD.get('malware_family')), timestamp=indicatorD.get('last_seen')) indicator.add_indicator_type("URL Watchlist") # Populate URL url = URI() url.value = indicatorD.get('key') url.type_ = URI.TYPE_URL url.value.condition = "Equals" indicator.add_observable(url) elif indicatorD.get('type') == "domain": # Populate domain name indicator = Indicator( id_="indicator-{0}".format(indicatorD.get('uuid')), title=''.join(indicatorD.get('malware_family')), timestamp=indicatorD.get('last_seen')) indicator.add_indicator_type("Domain Watchlist") domain = DomainName() domain.value = indicatorD.get('key') domain.value.condition = "Equals" indicator.add_observable(domain) elif indicatorD.get('type') == "ip": # Create indicator indicator = Indicator( id_="indicator-{0}".format(indicatorD.get('uuid')), title=indicatorD.get('malware_family'), timestamp=indicatorD.get('last_seen')) indicator.add_indicator_type("IP Watchlist") # Populate IP address addr = Address(address_value=indicatorD.get('key'), category=Address.CAT_IPV4) addr.condition = "Equals" indicator.add_observable(addr) # Link TTP indicator.add_indicated_ttp( TTP(idref=ttps[last_seen_as].id_)) # Indicate confidence score indicator.confidence = Confidence( value=VocabString(indicatorD.get('confidence'))) # Add related indicator to malware indicator.add_related_indicator(malware[md5]) # Add to package stix_package.add_indicator(indicator) else: print("API request couldn't be fulfilled due status code: %d" % r.status_code) more_data = False except requests.exceptions.ConnectionError as e: print("Check your network connection\n %s" % str(e)) except requests.exceptions.HTTPError as e: print("Bad HTTP response\n %s" % str(e)) except Exception as e: print("Uncaught exception\n %s" % str(e)) # Output to XML with open('stix-1.2.1.xml', 'wb') as f: f.write(stix_package.to_xml())
# Copyright (c) 2015, The MITRE Corporation. All rights reserved. # See LICENSE.txt for complete terms. import unittest from mixbox.namespaces import Namespace from mixbox import idgen TEST_NS = Namespace("http://some.namespace.com", "something", '') class IDGeneratorMinimalTest(unittest.TestCase): def test_id(self): # Make sure we can create an ID with a minimum of effort. # TODO: actually delete the module and reimport it to make sure there # is nothing left over from another test. self.assertNotEqual(idgen.create_id(), "") class IDGeneratorTest(unittest.TestCase): """Tests for the cybox.utils.IDGenerator class.""" def setUp(self): method = idgen.IDGenerator.METHOD_INT self.generator = idgen.IDGenerator(method=method) def test_incrementing_ids(self): self.assertEqual(self.generator.create_id(), "example:guid-1") self.assertEqual(self.generator.create_id(), "example:guid-2") self.assertEqual(self.generator.create_id(), "example:guid-3")
from cbfeeds import CbFeed from cbfeeds import CbFeedInfo from stix.core import STIXPackage from stix.utils.parser import EntityParser, UnsupportedVersionError from cybox.bindings.file_object import FileObjectType from cybox.bindings.domain_name_object import DomainNameObjectType from cybox.bindings.address_object import AddressObjectType from stix.utils import nsparser import mixbox.namespaces from mixbox.namespaces import Namespace ADDITIONAL_NAMESPACES = [ Namespace( 'http://us-cert.gov/ciscp', 'CISCP', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ciscp_vocab_v1.1.1.xsd' ) ] def merge(d1, d2): """ given two dictionaries, return a single dictionary that merges the two. """ result = d1 if not d2: return result for k in d2: if k in result: result[k].extend(d2[k]) else:
def main(argv): ###################################################################### # Se non impostati da command line vengono utilizzati i seguenti valori per TITLE, DESCRIPTION, IDENTITY # Il title e' ID univoco della minaccia (es. Cobalt / Danabot / APT28) TITLE = "Test" # La description strutturiamola come segue # <IOC PRODUCER> - <Descrizione della minaccia/campagna> - <URL (if any)> DESCRIPTION = "Cyber Saiyan - Test - https://infosharing.cybersaiyan.it" # La sorgente che ha generato l'IoC con riferimento a Cyber Saiyan Community IDENTITY = "Cyber Saiyan Community" # File degli IoC IOCFILE = "CS-ioc.txt" # Prefisso STIX output files STIX 1.2 e STIX 2 OUTFILEPREFIX = "package" # Short Description - UNUSED SHORT = "unused" ###################################################################### VERBOSE = 0 # Parse ARGV[] try: opts, args = getopt.getopt(argv, "ht:d:i:f:o:v") except getopt.GetoptError: print( "CS_build_stix-from_files.py [-t TITLE] [-d DESCRIPTION] [-i IDENTITY] [-f IOC_FILE] [-o STIX_FILES_PREFIX]") sys.exit(2) for opt, arg in opts: if opt == "-h": print( "CS_build_stix-from_files.py [-t TITLE] [-d DESCRIPTION] [-i IDENTITY] [-f IOC_FILE] [-o STIX_FILES_PREFIX]") sys.exit() elif opt == "-t": TITLE = arg elif opt == "-d": DESCRIPTION = arg elif opt == "-i": IDENTITY = arg elif opt == "-f": IOCFILE = arg elif opt == "-o": OUTFILEPREFIX = arg elif opt == "-v": VERBOSE = 1 print("---------------------") print("TITLE: " + TITLE) print("DESCRIPTION: " + DESCRIPTION) print("IDENTITY: " + IDENTITY) print("IOC FILE: " + IOCFILE) print("---------------------") ######################## # Commond data timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") ######################## # Build STIX 1.2 file info_src = InformationSource() info_src.identity = Identity(name=IDENTITY) NAMESPACE = Namespace("https://infosharing.cybersaiyan.it", "CYBERSAIYAN") set_id_namespace(NAMESPACE) wrapper = STIXPackage() marking_specification = MarkingSpecification() marking_specification.controlled_structure = "//node() | //@*" tlp = TLPMarkingStructure() tlp.color = "white" marking_specification.marking_structures.append(tlp) handling = Marking() handling.add_marking(marking_specification) wrapper.stix_header = STIXHeader(information_source=info_src, title=TITLE, description=DESCRIPTION, short_description=SHORT) wrapper.stix_header.handling = handling # HASH indicators indicatorHASH = Indicator() indicatorHASH.title = TITLE + " - HASH" indicatorHASH.add_indicator_type("File Hash Watchlist") # DOMAIN indicators indiDOMAIN = Indicator() indiDOMAIN.title = TITLE + " - DOMAIN" indiDOMAIN.add_indicator_type("Domain Watchlist") # URL indicators indiURL = Indicator() indiURL.title = TITLE + " - URL" indiURL.add_indicator_type("URL Watchlist") # IP indicators indiIP = Indicator() indiIP.title = TITLE + " - IP" indiIP.add_indicator_type("IP Watchlist") # EMAIL indicators indiEMAIL = Indicator() indiEMAIL.title = TITLE + " - EMAIL" indiEMAIL.add_indicator_type("Malicious E-mail") ######################## # Build STIX 2 file pattern_sha256 = [] pattern_md5 = [] pattern_sha1 = [] pattern_domain = [] pattern_url = [] pattern_ip = [] pattern_email = [] # Marking marking_def_white = stix2.TLP_WHITE # campagna # [TODO] aggiungere tutti i campi dello STIX 1.2 (es. IDENTITY) campaign_MAIN = stix2.Campaign( created=timestamp, modified=timestamp, name=TITLE, description=DESCRIPTION, first_seen=timestamp, objective="TBD" ) ######################## # Read IoC file loaddata(IOCFILE) if (VERBOSE): print("Reading IoC file " + IOCFILE + "...") ioccount = 0 # sha256 for ioc in listSHA256: # STIX 1.2 filei = File() filei.add_hash(Hash(ioc)) obsi = Observable(filei) indicatorHASH.add_observable(obsi) if (VERBOSE): print("SHA256: " + ioc) ioccount += 1 # STIX 2 pattern_sha256.append("[file:hashes.'SHA-256' = '" + ioc + "'] OR ") # md5 for ioc in listMD5: # STIX 1.2 filej = File() filej.add_hash(Hash(ioc)) obsj = Observable(filej) indicatorHASH.add_observable(obsj) if (VERBOSE): print("MD5: " + ioc) ioccount += 1 # STIX 2 pattern_md5.append("[file:hashes.'MD5' = '" + ioc + "'] OR ") # sha1 for ioc in listSHA1: # STIX 1.2 filek = File() filek.add_hash(Hash(ioc)) obsk = Observable(filek) indicatorHASH.add_observable(obsk) if (VERBOSE): print("SHA1: " + ioc) ioccount += 1 # STIX 2 pattern_sha1.append("[file:hashes.'SHA1' = '" + ioc + "'] OR ") # domains for ioc in listDOMAIN: # STIX 1.2 url = URI() url.value = ioc url.type_ = URI.TYPE_DOMAIN url.condition = "Equals" obsu = Observable(url) indiDOMAIN.add_observable(obsu) if (VERBOSE): print("DOMAIN: " + ioc) ioccount += 1 # STIX 2 pattern_domain.append("[domain-name:value = '" + ioc + "'] OR ") # url for ioc in listURL: # STIX 1.2 url = URI() url.value = ioc url.type_ = URI.TYPE_URL url.condition = "Equals" obsu = Observable(url) indiURL.add_observable(obsu) if (VERBOSE): print("URL: " + ioc) ioccount += 1 # STIX 2 pattern_url.append("[url:value = '" + ioc + "'] OR ") # ip for ioc in listIP: # STIX 1.2 ip = Address() ip.address_value = ioc obsu = Observable(ip) indiIP.add_observable(obsu) if (VERBOSE): print("IP: " + ioc) ioccount += 1 # STIX 2 pattern_ip.append("[ipv4-addr:value = '" + ioc + "'] OR ") # email for ioc in listEMAIL: # STIX 1.2 email = EmailAddress() email.address_value = ioc obsu = Observable(email) indiEMAIL.add_observable(obsu) if (VERBOSE): print("Email: " + ioc) ioccount += 1 # STIX 2 pattern_email.append("[email-message:from_ref.value = '" + ioc + "'] OR ") # subject for ioc in listSUBJECT: # STIX 1.2 emailsubject = EmailMessage() emailsubject.subject = ioc obsu = Observable(emailsubject) indiEMAIL.add_observable(obsu) if (VERBOSE): print("Subject: " + ioc) ioccount += 1 # STIX 2 (http://docs.oasis-open.org/cti/stix/v2.0/stix-v2.0-part5-stix-patterning.html) # Replace all quotes in a subject string with escaped quotes pattern_email.append("[email-message:subject = '" + ioc.replace("'", "\\'") + "'] OR ") ######################## # add all indicators to STIX 1.2 wrapper.add_indicator(indicatorHASH) wrapper.add_indicator(indiDOMAIN) wrapper.add_indicator(indiURL) wrapper.add_indicator(indiIP) wrapper.add_indicator(indiEMAIL) ######################## # prepare for STIX 2 bundle_objects = [campaign_MAIN, marking_def_white] if len(pattern_sha256) != 0: stix2_sha256 = "".join(pattern_sha256) stix2_sha256 = stix2_sha256[:-4] indicator_SHA256 = stix2.Indicator( name=TITLE + " - SHA256", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_sha256, object_marking_refs=[marking_def_white] ) relationship_indicator_SHA256 = stix2.Relationship(indicator_SHA256, "indicates", campaign_MAIN) bundle_objects.append(indicator_SHA256) bundle_objects.append(relationship_indicator_SHA256) if len(pattern_md5) != 0: stix2_md5 = "".join(pattern_md5) stix2_md5 = stix2_md5[:-4] indicator_MD5 = stix2.Indicator( name=TITLE + " - MD5", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_md5, object_marking_refs=[marking_def_white] ) relationship_indicator_MD5 = stix2.Relationship(indicator_MD5, "indicates", campaign_MAIN) bundle_objects.append(indicator_MD5) bundle_objects.append(relationship_indicator_MD5) if len(pattern_sha1) != 0: stix2_sha1 = "".join(pattern_sha1) stix2_sha1 = stix2_sha1[:-4] indicator_SHA1 = stix2.Indicator( name=TITLE + " - SHA1", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_sha1, object_marking_refs=[marking_def_white] ) relationship_indicator_SHA1 = stix2.Relationship(indicator_SHA1, "indicates", campaign_MAIN) bundle_objects.append(indicator_SHA1) bundle_objects.append(relationship_indicator_SHA1) if len(pattern_domain) != 0: stix2_domain = "".join(pattern_domain) stix2_domain = stix2_domain[:-4] indicator_DOMAINS = stix2.Indicator( name=TITLE + " - DOMAINS", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_domain, object_marking_refs=[marking_def_white] ) relationship_indicator_DOMAINS = stix2.Relationship(indicator_DOMAINS, "indicates", campaign_MAIN) bundle_objects.append(indicator_DOMAINS) bundle_objects.append(relationship_indicator_DOMAINS) if len(pattern_url) != 0: stix2_url = "".join(pattern_url) stix2_url = stix2_url[:-4] indicator_URLS = stix2.Indicator( name=TITLE + " - URL", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_url, object_marking_refs=[marking_def_white] ) relationship_indicator_URLS = stix2.Relationship(indicator_URLS, "indicates", campaign_MAIN) bundle_objects.append(indicator_URLS) bundle_objects.append(relationship_indicator_URLS) if len(pattern_ip) != 0: stix2_ip = "".join(pattern_ip) stix2_ip = stix2_ip[:-4] indicator_IPS = stix2.Indicator( name=TITLE + " - IPS", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_ip, object_marking_refs=[marking_def_white] ) relationship_indicator_IPS = stix2.Relationship(indicator_IPS, "indicates", campaign_MAIN) bundle_objects.append(indicator_IPS) bundle_objects.append(relationship_indicator_IPS) if len(pattern_email) != 0: stix2_email = "".join(pattern_email) stix2_email = stix2_email[:-4] indicator_EMAILS = stix2.Indicator( name=TITLE + " - EMAILS", created=timestamp, modified=timestamp, description=DESCRIPTION, labels=["malicious-activity"], pattern=stix2_email, object_marking_refs=[marking_def_white] ) relationship_indicator_EMAILS = stix2.Relationship(indicator_EMAILS, "indicates", campaign_MAIN) bundle_objects.append(indicator_EMAILS) bundle_objects.append(relationship_indicator_EMAILS) # creo il bunble STIX 2 bundlestix2 = stix2.Bundle(objects=bundle_objects) if (ioccount > 0): ######################## # save to STIX 1.2 file print("Writing STIX 1.2 package: " + OUTFILEPREFIX + ".stix") f = open(OUTFILEPREFIX + ".stix", "wb") f.write(wrapper.to_xml()) f.close() ######################## # save to STIX 2 file print("Writing STIX 2 package: " + OUTFILEPREFIX + ".stix2") g = open(OUTFILEPREFIX + ".stix2", "w") g.write(str(bundlestix2)) g.close() else: print("No IoC found")