def stix_xml(bldata): # Create the STIX Package and Header objects stix_package = STIXPackage() stix_header = STIXHeader() # Set the description stix_header.description = "RiskIQ Blacklist Data - STIX Format" # Set the namespace NAMESPACE = {"http://www.riskiq.com": "RiskIQ"} set_id_namespace(NAMESPACE) # Set the produced time to now stix_header.information_source = InformationSource() stix_header.information_source.time = Time() stix_header.information_source.time.produced_time = datetime.now() # Create the STIX Package stix_package = STIXPackage() # Build document stix_package.stix_header = stix_header # Build the Package Intent stix_header.package_intents.append(PackageIntent.TERM_INDICATORS) # Build the indicator indicator = Indicator() indicator.title = "List of Malicious URLs detected by RiskIQ - Malware, Phishing, and Spam" indicator.add_indicator_type("URL Watchlist") for datum in bldata: url = URI() url.value = "" url.value = datum['url'] url.type_ = URI.TYPE_URL url.condition = "Equals" indicator.add_observable(url) stix_package.add_indicator(indicator) return stix_package.to_xml()
def main(): ioc = etree.parse('6d2a1b03-b216-4cd8-9a9e-8827af6ebf93.ioc') stix_package = STIXPackage() ttp = TTP() malware_instance = MalwareInstance() malware_instance.names = ['Zeus', 'twexts', 'sdra64', 'ntos'] ttp = TTP(title="Zeus") ttp.behavior = Behavior() ttp.behavior.add_malware_instance(malware_instance) indicator = Indicator(title="Zeus", description="Finds Zeus variants, twexts, sdra64, ntos") tm = OpenIOCTestMechanism() tm.ioc = ioc tm.producer = InformationSource(identity=Identity(name="Yara")) time = Time() time.produced_time = "0001-01-01T00:00:00" tm.producer.time = time tm.producer.references = ["http://openioc.org/iocs/6d2a1b03-b216-4cd8-9a9e-8827af6ebf93.ioc"] indicator.test_mechanisms = [tm] indicator.add_indicated_ttp(TTP(idref=ttp.id_)) stix_package.add_indicator(indicator) stix_package.add_ttp(ttp) print stix_package.to_xml()
def set_received_time(self, received_time): """Sets the received time for this :class:`Indicator`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `received_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Args: received_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `received_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time
def to_source(obj): from stix.common import InformationSource, Identity mySource = InformationSource() mySource.time = Time(obj.request.date) mySource.description = obj.request.rfi mySource.identity = Identity(name=obj.request.source) for item in obj.response: itemSource = InformationSource() itemSource.time = Time(item.date) itemSource.identity = Identity(name=item.source) itemSource.description = item.rfi mySource.add_contributing_source(itemSource) return mySource
def to_stix_sightings(obj): from stix.indicator.sightings import Sighting from stix.common import InformationSource, Identity mySighting = Sighting() mySighting.source = InformationSource() if obj.sightings.sighting: itemSighting = InformationSource() itemSighting.time = Time(obj.sightings.date) itemSighting.identity = Identity(name=settings.COMPANY_NAME) mySighting.source.add_contributing_source(itemSighting) for each in obj.sightings.instances: itemSighting = InformationSource() itemSighting.time = Time(each.date) itemSighting.identity = Identity(name=each.name) mySighting.source.add_contributing_source(itemSighting) return mySighting
def buildSTIX(ident,confid,restconfid, effect, resteffect,typeIncident,resttype,asset,restasset,hashPkg): # IMPLEMENTATION WORKAROUND - # restConfid --> header.description # resteffect --> breach.description # resttype --> reporter.description # restasset --> reporter.identity.name # setup stix document stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = restconfid # "Example description" stix_package.stix_header = stix_header # add incident and confidence breach = Incident(id_=ident) breach.description = resteffect # "Intrusion into enterprise network" breach.confidence = Confidence() breach.confidence.value=confid print("confidence set to %s"%(str(breach.confidence.value))) breach._binding_class.xml_type = typeIncident print("incident set to %s"%(str(breach._binding_class.xml_type))) # stamp with reporter breach.reporter = InformationSource() breach.reporter.description = resttype #"The person who reported it" breach.reporter.time = Time() breach.reporter.time.produced_time = datetime.strptime("2014-03-11","%Y-%m-%d") # when they submitted it breach.reporter.identity = Identity() breach.reporter.identity.name = restasset # set incident-specific timestamps breach.time = incidentTime() breach.title = "Breach of Company Dynamics" breach.time.initial_compromise = datetime.strptime("2012-01-30", "%Y-%m-%d") breach.time.incident_discovery = datetime.strptime("2012-05-10", "%Y-%m-%d") breach.time.restoration_achieved = datetime.strptime("2012-08-10", "%Y-%m-%d") breach.time.incident_reported = datetime.strptime("2012-12-10", "%Y-%m-%d") affected_asset = AffectedAsset() affected_asset.description = "Database server at hr-data1.example.com" affected_asset.type_ = asset breach.affected_assets = affected_asset # add the victim breach.add_victim (hashPkg) # add the impact impact = ImpactAssessment() impact.add_effect(effect) breach.impact_assessment = impact stix_package.add_incident(breach) return stix_package
def build_stix(): # setup stix document stix_package = STIXPackage() # add incident and confidence breach = Incident() breach.description = "Intrusion into enterprise network" breach.confidence = "High" # stamp with reporter breach.reporter = InformationSource() breach.reporter.description = "The person who reported it" breach.reporter.time = Time() breach.reporter.time.produced_time = datetime.strptime( "2014-03-11", "%Y-%m-%d") # when they submitted it breach.reporter.identity = Identity() breach.reporter.identity.name = "Sample Investigations, LLC" # set incident-specific timestamps breach.time = incidentTime() breach.title = "Breach of CyberTech Dynamics" breach.time.initial_compromise = datetime.strptime("2012-01-30", "%Y-%m-%d") breach.time.incident_discovery = datetime.strptime("2012-05-10", "%Y-%m-%d") breach.time.restoration_achieved = datetime.strptime( "2012-08-10", "%Y-%m-%d") breach.time.incident_reported = datetime.strptime("2012-12-10", "%Y-%m-%d") # add the impact impact = ImpactAssessment() impact.effects = Effects("Unintended Access") breach.impact_assessment = impact # add the victim victim = Identity() victim.name = "CyberTech Dynamics" breach.add_victim(victim) # add the impact impact = ImpactAssessment() impact.effects = Effects("Financial Loss") breach.impact_assessment = impact stix_package.add_incident(breach) return stix_package
def getSTIXObject(): # setup stix document stix_package = STIXPackage() # add incident and confidence breach = Incident() breach.description = "Parity Wallet Hacked" breach.confidence = "High" # investigators were able to thoroughly validate the incident, Low means not yet validated # stamp with reporter breach.reporter = InformationSource() breach.reporter.description = "https://paritytech.io/blog/security-alert.html" breach.reporter.time = Time() breach.reporter.time.produced_time = datetime.strptime("2017-11-08","%Y-%m-%d") # when they submitted it breach.reporter.identity = Identity() breach.reporter.identity.name = "parity technologies ltd" # set incident-specific timestamps breach.time = incidentTime() breach.title = "The Multi-sig Hack" breach.time.initial_compromise = datetime.strptime("2017-11-06", "%Y-%m-%d") breach.time.incident_discovery = datetime.strptime("2017-11-08", "%Y-%m-%d") #breach.time.restoration_achieved = datetime.strptime("2012-08-10", "%Y-%m-%d") breach.time.incident_reported = datetime.strptime("2017-11-08", "%Y-%m-%d") # add the impact impact = ImpactAssessment() impact.effects = Effects("Estimated Loss of $280m in Ether") breach.impact_assessment = impact # add the victim victim = Identity() victim.name = "Cappasity" breach.add_victim(victim) victim2 = Identity() victim2.name = "Who else ?" breach.add_victim(victim2) # add Information Sources infoSource = InformationSource(); infoSource.add_description("https://news.ycombinator.com/item?id=15642856") infoSource.add_description("https://www.theregister.co.uk/2017/11/10/parity_280m_ethereum_wallet_lockdown_hack/") breach.Information_Source = infoSource; stix_package.add_incident(breach) return stix_package
def to_stix_information_source(obj): from stix.common import InformationSource, Identity mySource = InformationSource() for item in obj.source: for each in item.instances: itemSource = InformationSource() itemSource.time = Time(each.date) itemSource.identity = Identity(name=item.name) itemSource.add_description(each.reference) itemSource.add_description(each.method) mySource.add_contributing_source(itemSource) return mySource
def set_stix_header(self, threat_name, threat_descr, threat_source=None, reference=None): # Create a STIX Package hdr = STIXHeader() hdr.title = threat_name hdr.add_description(threat_descr) hdr.information_source = InformationSource() if threat_source is not None: hdr.information_source.description = threat_source if reference is not None: hdr.information_source.references = fields.TypedField(reference, References) # Set the produced time to now hdr.information_source.time = Time() hdr.information_source.time.produced_time = datetime.utcnow() self._pkg.stix_header = hdr
def execute(self, device_info, data_dir_path, simple_output=False, html_output=False): """ :param device_info: DeviceInfo :param data_dir_path: string """ extracted_data_dir_path = os.path.join(data_dir_path, EXTRACTED_DATA_DIR_NAME) try: os.makedirs(extracted_data_dir_path) except OSError as exception: if exception.errno != errno.EEXIST: raise self.extractor.execute(extracted_data_dir_path, self.param_values) set_id_method(IDGenerator.METHOD_INT if simple_output else IDGenerator.METHOD_UUID) inspected_objects, source_objects = self.inspector.execute(device_info, extracted_data_dir_path) inspected_observables = Observables(inspected_objects) source_observables = Observables(source_objects) tool_info = ToolInformation() tool_info.name = 'Android Inspector' tool_info.version = '1.0' measure_source = MeasureSource() measure_source.tool_type = ToolType.TERM_DIGITAL_FORENSICS measure_source.tools = ToolInformationList([tool_info]) measure_source.time = Time(produced_time=datetime.now().isoformat()) inspected_observables.observable_package_source = measure_source source_observables.observable_package_source = measure_source write_observables_xml_file(inspected_observables, os.path.join(data_dir_path, INSPECTED_DATA_FILE_NAME), simple_output) write_observables_xml_file(source_observables, os.path.join(data_dir_path, SOURCE_DATA_FILE_NAME), simple_output) if html_output: generate_html_files(data_dir_path)
def get_time(self, start_time=None, end_time=None, produced_time=None, received_time=None): return Time(start_time, end_time, produced_time, received_time)
def to_stix(obj, items_to_convert=[], loaded=False, bin_fmt="raw"): """ Converts a CRITs object to a STIX document. The resulting document includes standardized representations of all related objects noted within items_to_convert. :param items_to_convert: The list of items to convert to STIX/CybOX :type items_to_convert: Either a list of CRITs objects OR a list of {'_type': CRITS_TYPE, '_id': CRITS_ID} dicts :param loaded: Set to True if you've passed a list of CRITs objects as the value for items_to_convert, else leave False. :type loaded: bool :param bin_fmt: Specifies the format for Sample data encoding. Options: None (don't include binary data in STIX output), "raw" (include binary data as is), "base64" (base64 encode binary data) :returns: A dict indicating which items mapped to STIX indicators, ['stix_indicators'] which items mapped to STIX observables, ['stix_observables'] which items are included in the resulting STIX doc, ['final_objects'] and the STIX doc itself ['stix_obj']. """ from cybox.common import Time, ToolInformationList, ToolInformation from stix.common import StructuredText, InformationSource from stix.core import STIXPackage, STIXHeader from stix.common.identity import Identity # These lists are used to determine which CRITs objects # go in which part of the STIX document. ind_list = ['Indicator'] obs_list = [ 'Certificate', 'Domain', 'Email', 'IP', 'PCAP', 'RawData', 'Sample' ] actor_list = ['Actor'] # Store message stix_msg = { 'stix_incidents': [], 'stix_indicators': [], 'stix_observables': [], 'stix_actors': [], 'final_objects': [] } if not loaded: # if we have a list of object metadata, load it before processing items_to_convert = [ class_from_id(item['_type'], item['_id']) for item in items_to_convert ] # add self to the list of items to STIXify if obj not in items_to_convert: items_to_convert.append(obj) # add any email attachments attachments = [] for obj in items_to_convert: if obj._meta['crits_type'] == 'Email': for rel in obj.relationships: if rel.relationship == RelationshipTypes.CONTAINS: atch = class_from_id('Sample', rel.object_id) if atch not in items_to_convert: attachments.append(atch) items_to_convert.extend(attachments) # grab ObjectId of items refObjs = {key.id: 0 for key in items_to_convert} relationships = {} stix = [] from stix.indicator import Indicator as S_Ind for obj in items_to_convert: obj_type = obj._meta['crits_type'] if obj_type == class_from_type('Event')._meta['crits_type']: stx, release = to_stix_incident(obj) stix_msg['stix_incidents'].append(stx) elif obj_type in ind_list: # convert to STIX indicators stx, releas = to_stix_indicator(obj) stix_msg['stix_indicators'].append(stx) refObjs[obj.id] = S_Ind(idref=stx.id_) elif obj_type in obs_list: # convert to CybOX observable if obj_type == class_from_type('Sample')._meta['crits_type']: stx, releas = to_cybox_observable(obj, bin_fmt=bin_fmt) else: stx, releas = to_cybox_observable(obj) # wrap in stix Indicator ind = S_Ind() for ob in stx: ind.add_observable(ob) ind.title = "CRITs %s Top-Level Object" % obj_type ind.description = ("This is simply a CRITs %s top-level " "object, not actually an Indicator. " "The Observable is wrapped in an Indicator" " to facilitate documentation of the " "relationship." % obj_type) ind.confidence = 'None' stx = ind stix_msg['stix_indicators'].append(stx) refObjs[obj.id] = S_Ind(idref=stx.id_) elif obj_type in actor_list: # convert to STIX actor stx, releas = to_stix_actor(obj) stix_msg['stix_actors'].append(stx) # get relationships from CRITs objects for rel in obj.relationships: if rel.object_id in refObjs: relationships.setdefault(stx.id_, {}) relationships[stx.id_][rel.object_id] = ( rel.relationship, rel.rel_confidence.capitalize(), rel.rel_type) stix_msg['final_objects'].append(obj) stix.append(stx) # set relationships on STIX objects for stix_obj in stix: for rel in relationships.get(stix_obj.id_, {}): if isinstance(refObjs.get(rel), S_Ind): # if is STIX Indicator stix_obj.related_indicators.append(refObjs[rel]) rel_meta = relationships.get(stix_obj.id_)[rel] stix_obj.related_indicators[-1].relationship = rel_meta[0] stix_obj.related_indicators[-1].confidence = rel_meta[1] # Add any Email Attachments to CybOX EmailMessage Objects if isinstance(stix_obj, S_Ind): if 'EmailMessage' in stix_obj.observable.object_.id_: if rel_meta[0] == 'Contains' and rel_meta[ 2] == 'Sample': email = stix_obj.observable.object_.properties email.attachments.append(refObjs[rel].idref) tool_list = ToolInformationList() tool = ToolInformation("CRITs", "MITRE") tool.version = settings.CRITS_VERSION tool_list.append(tool) i_s = InformationSource(time=Time(produced_time=datetime.now()), identity=Identity(name=settings.COMPANY_NAME), tools=tool_list) if obj._meta['crits_type'] == "Event": stix_desc = obj.description() stix_int = obj.event_type() stix_title = obj.title() else: stix_desc = "STIX from %s" % settings.COMPANY_NAME stix_int = "Collective Threat Intelligence" stix_title = "Threat Intelligence Sharing" header = STIXHeader(information_source=i_s, description=StructuredText(value=stix_desc), package_intents=[stix_int], title=stix_title) stix_msg['stix_obj'] = STIXPackage(incidents=stix_msg['stix_incidents'], indicators=stix_msg['stix_indicators'], threat_actors=stix_msg['stix_actors'], stix_header=header, id_=uuid.uuid4()) return stix_msg
def build(self): self.stix_header.title = self.pulse["name"] self.stix_header.description = self.pulse["description"] self.stix_header.short_description = "%spulse/%s" % ( PULSE_SERVER_BASE, str(self.pulse["id"])) self.stix_header.package_intents.append(PackageIntent.TERM_INDICATORS) self.stix_header.information_source = InformationSource() self.stix_header.information_source.time = Time() self.stix_header.information_source.description = "Alienvault OTX - https://otx.alienvault.com/" self.stix_header.information_source.time.produced_time = self.pulse[ "modified"] self.stix_header.information_source.identity = Identity() self.stix_header.information_source.identity.name = "Alienvault OTX" self.stix_package.stix_header = self.stix_header hashes = [] addresses = [] domains = [] urls = [] mails = [] for p_indicator in self.pulse["indicators"]: if p_indicator["type"] in self.hash_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) file_ = File() hash_ = Hash(p_indicator["indicator"], self.hash_translation[p_indicator["type"]]) file_.add_hash(hash_) observable_ = Observable(file_) elif p_indicator["type"] in self.address_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) ipv4_ = Address.from_dict({ 'address_value': p_indicator["indicator"], 'category': self.address_translation[p_indicator["type"]] }) observable_ = Observable(ipv4_) elif p_indicator["type"] in self.name_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) domain_ = DomainName.from_dict({ 'value': p_indicator["indicator"], 'type': 'FQDN' }) observable_ = Observable(domain_) elif p_indicator["type"] == "URL": new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) url_ = URI.from_dict({ 'value': p_indicator["indicator"], 'type': URI.TYPE_URL }) observable_ = Observable(url_) elif p_indicator["type"] == "email": email_ = Address.from_dict({ 'address_value': p_indicator["indicator"], 'category': Address.CAT_EMAIL }) observable_ = Observable(email_) #elif p_indicator["type"] == "CVE": # vuln_ = Vulnerability() # vuln_.cveid = p_indicator["indicator"].upper() # observable_ = Observable(vuln_) elif p_indicator["type"] == "Mutex": mutex_ = Mutex.from_dict({ 'named': True, 'name': p_indicator["indicator"] }) observable_ = Observable(mutex_) elif p_indicator["type"] == "CIDR": nrange = IP(p_indicator["indicator"]) nrange_values = nrange.strNormal(3).replace("-", ",") ipv4_ = Address.from_dict({ 'address_value': nrange_values, 'category': Address.CAT_IPV4 }) ipv4_.address_value.condition = "InclusiveBetween" observable_ = Observable(ipv4_) else: continue mind = Indicator() mind.description = p_indicator["description"] mind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) observable_.title = "%s - %s" % (p_indicator["type"], p_indicator["indicator"]) mind.add_observable(observable_) self.stix_package.add_indicator(mind)
def doCuckoo(results): malfilename = "" # memstrings = [] print "json dumps %s" % (json.dumps(results['target'])) try: fileitems = results['target']['file'] malfilename = fileitems['name'] malfilesize = fileitems['size'] malmd5 = fileitems['md5'] malsha1 = fileitems['sha1'] malsha256 = fileitems['sha256'] malsha512 = fileitems['sha512'] malssdeep = fileitems['ssdeep'] malfiletype = fileitems["type"] # MD54K - From Chris Hudel malmd54k = doMD54K(fileitems['path']) # memfile = fileitems['path'][0:len(fileitems['path']) - 64] + "../analyses/" + str(results['info']['id']) + "/memory.dmp" # memstrings = doStrings(stringscmd(memfile)) except: fileitems = [] pass staticitems = results['static'] # info = results['info'] # Suspicious PE imports iocimports = [] try: for imports in staticitems['pe_imports']: for item in imports['imports']: if item['name'] in suspiciousimports: iocimports.append(item['name']) except: pass #rsrcentries = [] # PE sectionis badpesections = [] try: for sections in staticitems['pe_sections']: if sections['name'] not in goodpesections: badpesection = [ sections['name'], sections['size_of_data'], str(sections['entropy']) ] badpesections.append(badpesection) except: pass # PE Exports iocexports = [] try: for exportfunc in staticitems['pe_exports']: iocexports.append(exportfunc['name']) except: pass # PE Version Info versioninfo = dict.fromkeys(['LegalCopyright', 'InternalName', 'FileVersion', 'CompanyName', 'PrivateBuild', \ 'LegalTrademarks', 'Comments', 'ProductName', 'SpecialBuild', 'ProductVersion', \ 'FileDescription', 'OriginalFilename']) if 'pe_versioninfo' in staticitems: for item in staticitems['pe_versioninfo']: if item['name'] in versioninfo: versioninfo[item['name']] = item['value'] # Dropped files droppedfiles = [] try: for droppedfile in results['dropped']: droppedfiles.append([droppedfile['name'], droppedfile['size'], droppedfile['md5'], droppedfile['sha1'], \ droppedfile['sha256'], droppedfile['sha512']]) except: pass # Hosts contacted. This will exclude # localhost, broadcast and any other 'noise' # as indicated by excludedips hosts = [] try: for host in results['network']['hosts']: if host not in excludedips: hosts.append(host) except: pass # Mutexes mutexes = [] try: for mutex in results['behavior']['summary']['mutexes']: mutexes.append(mutex) except: pass # Processes processes = [] try: for process in results['behavior']['processes']: processes.append([ process['process_name'], process['process_id'], process['parent_id'] ]) except: pass # grab the string results # currently these are simple # regexes for IPv4 addresses and # emails strings = doStrings(results['strings']) # Registry Keys # This uses modified cuckoo source code to only # pull the Registry keys created, instead # of those created OR just opened regkeys = results['behavior']['summary']['keys'] # Create our metadata dictionary for getting the # metadata values int the IOC metadata = {'malfilename':malfilename, 'malmd5':malmd5, 'malsha1':malsha1, 'malsha256':malsha256, 'malsha512':malsha512, \ 'malmd54k':malmd54k, 'malfilesize':malfilesize, 'malssdeep':malssdeep, 'malfiletype':malfiletype, \ 'iocexports':iocexports, 'iocimports':iocimports, 'badpesections':badpesections, 'versioninfo':versioninfo} dynamicindicators = { "droppedfiles": droppedfiles, "processes": processes, "regkeys": regkeys, 'mutexes': mutexes, 'hosts': hosts } stix_package = STIXPackage() stix_header = STIXHeader() desc = "IOCAware Auto-Generated IOC Document" if len(malfilename) > 0: desc += " " + malfilename stix_header.description = desc stix_header.information_source = InformationSource() stix_header.information_source.time = Time() stix_header.information_source.time.produced_time = datetime.now() stix_package.stix_header = stix_header #wfe = createMetaData(stix_package, metadata) #addStrings(stix_package, wfe, strings) createMetaData(stix_package, metadata, strings) createDynamicIndicators(stix_package, dynamicindicators) filename = IOCLOCATION + "/iocaware_stix_" + str(uuid.uuid4()) + ".xml" stixfile = open(filename, "w") stixfile.write(stix_package.to_xml())
def set_received_time(self, received_time): '''Set the time when this indicator was received''' if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time
def set_produced_time(self, produced_time): '''The produced date variable must be in ISO 8601 format''' if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time
def to_stix(self, username=None): """ Converts a CRITs event to a STIX document. The resulting document includes all related emails, samples, and indicators converted to CybOX Observable objects. Returns the STIX document and releasability constraints. (NOTE: the following statement is untrue until the releasability checking is finished, which includes setting releasability on all CRITs objects.) Raises UnreleasableEventError if the releasability on the relationships and the event do not share any common releasability sources. """ from crits.emails.email import Email from crits.samples.sample import Sample from crits.indicators.indicator import Indicator from cybox.common import Time, ToolInformationList, ToolInformation from cybox.core import Observables from stix.common import StructuredText from stix.core import STIXPackage, STIXHeader from stix.common import InformationSource from stix.common.identity import Identity stix_indicators = [] stix_observables = [] final_objects = [] # create a list of sources to send as part of the results. # list should be limited to the sources this user is allowed to use. # this list should be used along with the list of objects to set the # appropriate source's 'released' key to True for each object. final_sources = [] user_source_list = user_sources(username) for f in self.releasability: if f.name in user_source_list: final_sources.append(f.name) final_sources = set(final_sources) # TODO: eventually we can use class_from_id instead of the if block # but only once we support all CRITs types. for r in self.relationships: obj = None if r.rel_type == Email._meta['crits_type']: obj = Email.objects(id=r.object_id, source__name__in=user_source_list).first() if obj: ind, releas = obj.to_cybox() stix_observables.append(ind[0]) elif r.rel_type == Sample._meta['crits_type']: obj = Sample.objects(id=r.object_id, source__name__in=user_source_list).first() if obj: ind, releas = obj.to_cybox() for i in ind: stix_observables.append(i) elif r.rel_type == Indicator._meta['crits_type']: #NOTE: Currently this will raise an exception if there # are multiple indicators with the same value. # Should be fixed automatically once we transition # indicators to be related based on ObjectId rather # than value. obj = Indicator.objects(id=r.object_id, source__name__in=user_source_list).first() if obj: ind, releas = obj.to_stix_indicator() stix_indicators.append(ind) else: continue #Create a releasability list that is the intersection of # each related item's releasability with the event's # releasability. If the resulting set is empty, raise exception #TODO: Set releasability on all objects so that we actually # get results here instead of always raising an exception. if obj: releas_sources = set([rel.name for rel in releas]) final_sources = final_sources.intersection(releas_sources) #TODO: uncomment the following lines when objects have # releasability set. #if not final_sources: # raise UnreleasableEventError(r.value) # add to the final_objects list to send as part of the results final_objects.append(obj) tool_list = ToolInformationList() tool = ToolInformation("CRITs", "MITRE") tool.version = settings.CRITS_VERSION tool_list.append(tool) i_s = InformationSource( time=Time(produced_time= datetime.datetime.now()), identity = Identity(name=settings.COMPANY_NAME), tools = tool_list ) description = StructuredText(value=self.description) header = STIXHeader(information_source=i_s, description=description, package_intent=self.event_type, title=self.title) return (STIXPackage(indicators=stix_indicators, observables=Observables(stix_observables), stix_header=header, id_=self.event_id), final_sources, final_objects)
from stix.incident.impact_assessment import Effects from stix.common import References # setup stix document stix_package = STIXPackage() # add incident and confidence breach = Incident() breach.description = "Parity Wallet Hacked" breach.confidence = "High" # investigators were able to thoroughly validate the incident, Low means not yet validated # stamp with reporter breach.reporter = InformationSource() breach.reporter.description = "https://paritytech.io/blog/security-alert.html" breach.reporter.time = Time() breach.reporter.time.produced_time = datetime.strptime("2017-11-08","%Y-%m-%d") # when they submitted it breach.reporter.identity = Identity() breach.reporter.identity.name = "parity technologies ltd" # set incident-specific timestamps breach.time = incidentTime() breach.title = "The Multi-sig Hack" breach.time.initial_compromise = datetime.strptime("2017-11-06", "%Y-%m-%d") breach.time.incident_discovery = datetime.strptime("2017-11-08", "%Y-%m-%d") #breach.time.restoration_achieved = datetime.strptime("2012-08-10", "%Y-%m-%d") breach.time.incident_reported = datetime.strptime("2017-11-08", "%Y-%m-%d") # add the impact impact = ImpactAssessment()
def build(self): """Define the STIX report.""" self.stix_header.title = self.pulse["name"] self.stix_header.description = self.pulse["description"] self.stix_header.package_intents = "Indicators" self.stix_header.information_source = InformationSource() self.stix_header.information_source.time = Time() self.stix_header.information_source.time.received_time = self.pulse[ "modified"] self.stix_header.information_source.time.produced_time = self.stix_package.timestamp self.stix_header.information_source.identity = Identity() self.stix_header.information_source.identity.name = IDENTITY_NAME # self.stix_package.stix_header = self.stix_header # self.stix_package.stix_header.handling = self._marking() # self.report = Report() # self.report.header = Header() # self.report.header.title = self.pulse["name"] # self.report.header.descriptions = self.pulse["description"] # self.report.header.intents = "Indicators" # self.report.header.short_description = "%spulse/%s" % ( # PULSE_SERVER_BASE, str(self.pulse["id"])) # self.report.header.information_source = InformationSource() # self.report.header.information_source.time = Time() # self.report.header.information_source.time.received_time = self.pulse[ # "modified"] # self.report.header.information_source.time.produced_time = self.report.timestamp # self.report.header.information_source.identity = Identity() # self.report.header.information_source.identity.name = IDENTITY_NAME hashes = False addresses = False emails = False domains = False urls = False mutex = False hash_indicator = Indicator() hash_indicator.set_producer_identity(IDENTITY_NAME) hash_indicator.set_produced_time(hash_indicator.timestamp) hash_indicator.set_received_time(self.pulse["modified"]) hash_indicator.title = "[OTX] [Files] " + self.pulse["name"] hash_indicator.add_indicator_type("File Hash Watchlist") hash_indicator.confidence = "Low" address_indicator = Indicator() address_indicator.set_producer_identity(IDENTITY_NAME) address_indicator.set_produced_time(address_indicator.timestamp) address_indicator.set_received_time(self.pulse["modified"]) address_indicator.title = "[OTX] [IP] " + self.pulse["name"] address_indicator.add_indicator_type("IP Watchlist") address_indicator.confidence = "Low" domain_indicator = Indicator() domain_indicator.set_producer_identity(IDENTITY_NAME) domain_indicator.set_produced_time(domain_indicator.timestamp) domain_indicator.set_received_time(self.pulse["modified"]) domain_indicator.title = "[OTX] [Domain] " + self.pulse["name"] domain_indicator.add_indicator_type("Domain Watchlist") domain_indicator.confidence = "Low" url_indicator = Indicator() url_indicator.set_producer_identity(IDENTITY_NAME) url_indicator.set_produced_time(url_indicator.timestamp) url_indicator.set_received_time(self.pulse["modified"]) url_indicator.title = "[OTX] [URL] " + self.pulse["name"] url_indicator.add_indicator_type("URL Watchlist") url_indicator.confidence = "Low" email_indicator = Indicator() email_indicator.set_producer_identity(IDENTITY_NAME) email_indicator.set_produced_time(email_indicator.timestamp) email_indicator.set_received_time(self.pulse["modified"]) email_indicator.title = "[OTX] [Email] " + self.pulse["name"] email_indicator.add_indicator_type("Malicious E-mail") email_indicator.confidence = "Low" mutex_indicator = Indicator() mutex_indicator.set_producer_identity(IDENTITY_NAME) mutex_indicator.set_produced_time(mutex_indicator.timestamp) mutex_indicator.set_received_time(self.pulse["modified"]) mutex_indicator.title = "[OTX] [Mutex] " + self.pulse["name"] mutex_indicator.add_indicator_type("Malware Artifacts") mutex_indicator.confidence = "Low" for p_indicator in self.pulse["indicators"]: if p_indicator["type"] in self.hash_translation: file_object = File() file_object.add_hash(Hash(p_indicator["indicator"])) file_object.hashes[0].simple_hash_value.condition = "Equals" file_object.hashes[0].type_.condition = "Equals" file_obs = Observable(file_object) file_obs.title = "File: " + \ str(file_object.hashes[0].type_) + \ " - " + p_indicator["indicator"] hash_indicator.add_observable(file_obs) try: hash_indicator.description = p_indicator["description"] except KeyError: hash_indicator.description = "" hashes = True elif p_indicator["type"] in self.address_translation: ip = Address() ip.address_value = p_indicator["indicator"] ip.category = self.address_translation[p_indicator["type"]] ip.address_value.condition = "Equals" ip_obs = Observable(ip) ip_obs.title = "Address: " + str(ip.address_value) address_indicator.add_observable(ip_obs) try: address_indicator.description = p_indicator["description"] except KeyError: address_indicator.description = "" addresses = True elif p_indicator["type"] in self.name_translation: domain = DomainName() domain.value = p_indicator["indicator"] domain.type_ = "FQDN" domain.value.condition = "Equals" domain_obs = Observable(domain) domain_obs.title = "Domain: " + str(domain.value) domain_indicator.add_observable(domain_obs) try: domain_indicator.description = p_indicator["description"] except KeyError: domain_indicator.description = "" domains = True elif p_indicator["type"] == "URL": url = URI() url.value = p_indicator["indicator"] url.type_ = URI.TYPE_URL url.value.condition = "Equals" url_obs = Observable(url) url_obs.title = "URI: " + str(url.value) url_indicator.add_observable(url_obs) try: url_indicator.description = p_indicator["description"] except KeyError: url_indicator.description = "" urls = True elif p_indicator["type"] == "email": email = Address() email.address_value = p_indicator["indicator"] email.category = "e-mail" email.address_value.condition = "Equals" email_obs = Observable(email) email_obs.title = "Address: " + str(email.address_value) email_indicator.add_observable(email_obs) try: email_indicator.description = p_indicator["indicator"] except KeyError: email_indicator.description = "" emails = True elif p_indicator["type"] == "Mutex": mutex = Mutex() mutex.name = p_indicator["indicator"] mutex.named = True mutex_obs = Observable(mutex) mutex_obs.title = "Mutex: " + str(mutex.name) mutex_indicator.add_observable(mutex_obs) try: mutex_indicator.description = p_indicator["indicator"] except KeyError: mutex_indicator.description = "" mutex = True else: continue if hashes: self.stix_package.add_indicator(hash_indicator) if addresses: self.stix_package.add_indicator(address_indicator) if domains: self.stix_package.add_indicator(domain_indicator) if urls: self.stix_package.add_indicator(url_indicator) if emails: self.stix_package.add_indicator(email_indicator) if mutex: self.stix_package.add_indicator(mutex_indicator)