def create_stix(self, event, user): stix_package = STIXPackage() stix_package.id_ = 'ce1sus:Event-{0}'.format(event.uuid) stix_header = self.__map_stix_header(event) stix_package.stix_header = stix_header event_permissions = self.event_controller.get_event_user_permissions( event, user) # observables if event.observables: for observable in event.get_observables_for_permissions( event_permissions, user): cybox_obs = self.create_observable(observable, event_permissions, user) stix_package.add_observable(cybox_obs) # indicators if event.indicators: indicators = event.get_indicators_for_permissions( event_permissions, user) else: # generate indicators indicators = self.indicator_controller.get_generic_indicators( event, user) for indicator in indicators: stix_indicator = self.create_indicator(indicator, event_permissions, user) stix_package.add_indicator(stix_indicator) return stix_package
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 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 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 main(): stix_package = STIXPackage() addr1 = Observable(Address(address_value="198.51.100.2", category=Address.CAT_IPV4)) addr2 = Observable(Address(address_value="198.51.100.17", category=Address.CAT_IPV4)) addr3 = Observable(Address(address_value="203.0.113.19", category=Address.CAT_IPV4)) stix_package.add_observable(addr1) stix_package.add_observable(addr2) stix_package.add_observable(addr3) obs_addr1 = Observable() obs_addr2 = Observable() obs_addr3 = Observable() obs_addr1.id_ = None obs_addr2.id_ = None obs_addr3.id_ = None obs_addr1.idref = addr1.id_ obs_addr2.idref = addr2.id_ obs_addr3.idref = addr3.id_ infrastructure = Infrastructure() infrastructure.observable_characterization = Observables([obs_addr1, obs_addr2, obs_addr3]) resource = Resource() resource.infrastructure = infrastructure ttp = TTP(title="Malware C2 Channel") ttp.resources = resource stix_package.add_ttp(ttp) print stix_package.to_xml()
def stix_pkg(config, src, endpoint, payload, title='random test data', description='random test data', package_intents='Indicators - Watchlist', tlp_color='WHITE', dest=None): '''package observables''' # setup the xmlns... xmlns_url = config['edge']['sites'][dest]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][dest]['stix']['xmlns_name'] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = '../../../../descendant-or-self::node()' tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) if isinstance(payload, Observable): stix_package.add_observable(payload) elif isinstance(payload, Indicator): stix_package.add_indicator(payload) elif isinstance(payload, Incident): stix_package.add_incident(payload) return(stix_package)
def export_stix(iocs): """ Export the tagged items in STIX format. BROKE! """ observables_doc = None stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = filename stix_package.stix_header = stix_header for ioc in iocs['md5']: observable = cybox_helper.create_file_hash_observable('', value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) if t == 'ipv4': if not value in indicators: observable = cybox_helper.create_ipv4_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'domain': if not value in indicators: observable = cybox_helper.create_domain_name_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'url': if not value in indicators: observable = cybox_helper.create_url_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'email': if not value in indicators: observable = cybox_helper.create_email_address_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) if len(observables) > 0: if not filename.endswith('.xml'): filename = "%s.xml" % filename #add .xml extension if missing # end if with open(filename, "wb") as f: stix_xml = stix_package.to_xml() f.write(stix_xml)
def main(): shv = Hash() shv.simple_hash_value = "4EC0027BEF4D7E1786A04D021FA8A67F" f = File() h = Hash(shv, Hash.TYPE_MD5) f.add_hash(h) stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = "Example 03" stix_package.stix_header = stix_header stix_package.add_observable(f) print(stix_package.to_xml())
def main(): shv = Hash() shv.simple_hash_value = "4EC0027BEF4D7E1786A04D021FA8A67F" f = File() h = Hash(shv, Hash.TYPE_MD5) f.add_hash(h) stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = "Example 03" stix_package.stix_header = stix_header stix_package.add_observable(f) print(stix_package.to_xml())
def main(): stix_package = STIXPackage() addr1 = Observable( Address(address_value="198.51.100.2", category=Address.CAT_IPV4)) addr2 = Observable( Address(address_value="198.51.100.17", category=Address.CAT_IPV4)) addr3 = Observable( Address(address_value="203.0.113.19", category=Address.CAT_IPV4)) stix_package.add_observable(addr1) stix_package.add_observable(addr2) stix_package.add_observable(addr3) obs_addr1 = Observable() obs_addr2 = Observable() obs_addr3 = Observable() obs_addr1.id_ = None obs_addr2.id_ = None obs_addr3.id_ = None obs_addr1.idref = addr1.id_ obs_addr2.idref = addr2.id_ obs_addr3.idref = addr3.id_ vocab_string = VocabString(value='Malware C2') infrastructure = Infrastructure() infrastructure.observable_characterization = Observables( [obs_addr1, obs_addr2, obs_addr3]) infrastructure.add_type(vocab_string) resource = Resource() resource.infrastructure = infrastructure ttp = TTP(title="Malware C2 Channel") ttp.resources = resource stix_package.add_ttp(ttp) print(stix_package.to_xml())
def _generate_stix_package(packages): compiled_package = STIXPackage() for package in packages: sio = IOhandler(package.content) sp = STIXPackage.from_xml(sio) if sp.indicators: [compiled_package.add_indicator(ind) for ind in sp.indicators] if sp.observables: [ compiled_package.add_observable(obs) for obs in sp.observables ] return compiled_package
def alta_informacion(request): #""" #When in GET method return all the Content Blocks. #When in POST method, given a content binding id, a title, description and content we create a Content Block. #""" logger = logging.getLogger('TAXIIApplication.rest.views.alta_informacion') logger.debug('Entering alta_informacion') logger.debug(request.method) if request.method == 'GET': content = ContentBlock.objects.all() serializer = ContentBlockSerializer(content, many=True) return Response(serializer.data) elif request.method == 'POST': cont = request.DATA.get('content') c = StringIO.StringIO(cont) logger.debug(request.DATA.get('content_binding')) observables_obj = cybox_core_binding.parse(c) observables = Observables.from_obj(observables_obj) logger.debug(str(observables)) stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = request.DATA.get('description') stix_header.title = request.DATA.get('title') stix_package.stix_header = stix_header stix_package.add_observable(observables) content_binding = ContentBindingId.objects.get(id=1) cb = ContentBlock(title=request.DATA.get('title'), description=request.DATA.get('description') ,content_binding=content_binding, content=stix_package.to_xml()) cb.save() df = DataFeed.objects.get(name='default') df.content_blocks.add(cb) return Response(status=status.HTTP_201_CREATED)
def stix_pkg(config, src, endpoint, payload, title='random test data', description='random test data', package_intents='Indicators - Watchlist', tlp_color='WHITE', dest=None): '''package observables''' # setup the xmlns... xmlns_url = config['edge']['sites'][dest]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][dest]['stix']['xmlns_name'] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = '../../../../descendant-or-self::node()' tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) if isinstance(payload, Observable): stix_package.add_observable(payload) elif isinstance(payload, Indicator): stix_package.add_indicator(payload) elif isinstance(payload, Incident): stix_package.add_incident(payload) return (stix_package)
coa.efficacy = HighMediumLow('High') coa.stage = COAStage('Response') coa.type_ = CourseOfActionType('Perimeter Blocking') # Related Observable (by id) addr = Address(address_value=ip, category=Address.CAT_IPV4) observable = Observable(addr) coa.parameter_observables = Observables(observables=Observable( idref=observable.id_)) # Related CoA (basic; by id) coa2 = CourseOfAction(title='Block domain traffic to {}'.format(domain)) related_coa = RelatedCOA(CourseOfAction(idref=coa2.id_)) coa.related_coas.append(related_coa) # Indicator indicator = Indicator(title='Indicator') domain_name = DomainName() domain_name.value = domain indicator.add_observable(domain_name) indicator.suggested_coas.append(CourseOfAction(idref=coa2.id_)) # Generate STIX Package stix_package = STIXPackage() stix_package.add_observable(observable) stix_package.add_course_of_action(coa) stix_package.add_course_of_action(coa2) stix_package.add_indicator(indicator) print(stix_package.to_xml().decode())
def gen_stix_observable_sample( config, target=None, datatype=None, title="random test data", description="random test data", package_intents="Indicators - Watchlist", tlp_color="WHITE", ): """generate sample stix data comprised of indicator_count indicators of type datatype""" # setup the xmlns... xmlns_url = config["edge"]["sites"][target]["stix"]["xmlns_url"] xmlns_name = config["edge"]["sites"][target]["stix"]["xmlns_name"] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = "../../../../descendant-or-self::node()" tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) # ...and stuff it full of random sample data :-) if datatype == "ip": addr = Address(address_value=datagen_.generate_random_ip_address(), category="ipv4-addr") addr.condition = "Equals" stix_package.add_observable(Observable(addr)) elif datatype == "domain": domain = DomainName() domain.type_ = "FQDN" domain.value = datagen_.generate_random_domain(config) domain.condition = "Equals" stix_package.add_observable(Observable(domain)) elif datatype == "filehash": file_object = File() file_object.file_name = str(uuid.uuid4()) + ".exe" hashes = datagen_.generate_random_hashes() for hash in hashes.keys(): file_object.add_hash(Hash(hashes[hash], type_=hash.upper())) for i in file_object.hashes: i.simple_hash_value.condition = "Equals" stix_package.add_observable(Observable(file_object)) elif datatype == "email": try: msg = datagen_.get_random_spam_msg(config) email = EmailMessage() email.header = EmailHeader() header_map = { "Subject": "subject", "To": "to", "Cc": "cc", "Bcc": "bcc", "From": "from_", "Sender": "sender", "Date": "date", "Message-ID": "message_id", "Reply-To": "reply_to", "In-Reply-To": "in_reply_to", "Content-Type": "content_type", "Errors-To": "errors_to", "Precedence": "precedence", "Boundary": "boundary", "MIME-Version": "mime_version", "X-Mailer": "x_mailer", "User-Agent": "user_agent", "X-Originating-IP": "x_originating_ip", "X-Priority": "x_priority", } # TODO handle received_lines for key in header_map.keys(): val = msg.get(key, None) if val: email.header.__setattr__(header_map[key], val) email.header.__getattribute__(header_map[key]).condition = "Equals" # TODO handle email bodies (it's mostly all there except for # handling weird text encoding problems that were making # libcybox stacktrace) # body = get_email_payload(random_spam_msg) # if body: # email.raw_body = body stix_package.add_observable(Observable(email)) except: return None observable_id = stix_package.observables.observables[0].id_ return (observable_id, stix_package)
def adptrTransform_Dict2Obj(srcData, data=None): sNAMEFUNC = 'adptrTransform_Dict2Obj' sndMSG('Called...', 'INFO', sNAMEFUNC) if not srcData: return (None) #srcData can not be empty from stix.core import STIXPackage from stix.common import InformationSource, Identity from stix.data_marking import Marking from stix.ttp import TTP ### Build Package objMarkingSpecification = genObject_MarkingSpecification(data) objMarkingSpecification.controlled_structure = "//node()" objHdr = genData_STIXHeader(data) objHdr.handling = Marking(objMarkingSpecification) objHdr.information_source = InformationSource(identity=Identity( name=srcData.pkgLink)) objTTP = genObject_TTP(data) objTTP.information_source = InformationSource(identity=Identity( name=srcData.pkgLink)) objPkg = STIXPackage() objPkg.stix_header = objHdr objPkg.add_ttp(objTTP) for sKey in data['data']: obsList = [] ### Build Observables obsURI = genObject_URI(data['data'][sKey]['src']) try: obsURI.id_ = data['data'][sKey]['meta']['uri'] except: data['data'][sKey]['meta'].update({'uri': obsURI.id_}) ### Srt: Stupid test to make sure URL be output via STIX.to_xml() try: testPkg = STIXPackage() testPkg.add_observable(obsURI) testPkg.to_xml() except: sNAMEFUNC = 'adptrTransform_Dict2Obj' sndMSG('Error Parsing URL for this key: [' + sKey + ']', 'INFO', sNAMEFUNC) testPkg = None continue ### End: Stupid test objPkg.add_observable(obsURI) obsList.append(genRefObs(obsURI)) ### Build Indicators objInd = genObject_Indicator(data['data'][sKey]['src']) try: obsURI.id_ = data['data'][sKey]['meta']['ind'] except: data['data'][sKey]['meta'].update({'ind': objInd.id_}) objInd.producer = InformationSource(identity=Identity( name=srcData.pkgLink)) objInd.observables = obsList objInd.indicator_types = ["URL Watchlist"] objInd.observable_composition_operator = "OR" objInd.set_received_time(data['data'][sKey]['meta']['dateDL']) try: objInd.set_produced_time( data['data'][sKey]['src']['verification_time']) except: pass if not data['data'][sKey]['src']['target'] == 'Other': from stix.ttp import TTP objVictimTargeting = genData_VictimTargeting( data['data'][sKey]['src']) if obsURI: objVictimTargeting.targeted_technical_details = genRefObs( obsURI) objTTP_vic = TTP() objTTP_vic.title = "Targeting: " + data['data'][sKey]['src'][ 'target'] objTTP_vic.victim_targeting = objVictimTargeting objInd.add_indicated_ttp(objTTP_vic) objInd.add_indicated_ttp(TTP(idref=objTTP.id_)) objPkg.add_indicator(objInd) #updateDB_local(data,srcData) return (objPkg)
def gen_stix_observable_sample(config, target=None, datatype=None, title='random test data', description='random test data', package_intents='Indicators - Watchlist', tlp_color='WHITE'): '''generate sample stix data comprised of indicator_count indicators of type datatype''' # setup the xmlns... xmlns_url = config['edge']['sites'][target]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][target]['stix']['xmlns_name'] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = '../../../../descendant-or-self::node()' tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) # ...and stuff it full of random sample data :-) if datatype == 'ip': addr = Address(address_value=datagen.generate_random_ip_address(), category='ipv4-addr') addr.condition = 'Equals' stix_package.add_observable(Observable(addr)) elif datatype == 'domain': domain = DomainName() domain.type_ = 'FQDN' domain.value = datagen.generate_random_domain(config) domain.condition = 'Equals' stix_package.add_observable(Observable(domain)) elif datatype == 'filehash': file_object = File() file_object.file_name = str(uuid.uuid4()) + '.exe' hashes = datagen.generate_random_hashes() for hash in hashes.keys(): file_object.add_hash(Hash(hashes[hash], type_=hash.upper())) for i in file_object.hashes: i.simple_hash_value.condition = "Equals" stix_package.add_observable(Observable(file_object)) elif datatype == 'email': try: msg = datagen.get_random_spam_msg(config) email = EmailMessage() email.header = EmailHeader() header_map = { 'Subject': 'subject', 'To': 'to', 'Cc': 'cc', 'Bcc': 'bcc', 'From': 'from_', 'Sender': 'sender', 'Date': 'date', 'Message-ID': 'message_id', 'Reply-To': 'reply_to', 'In-Reply-To': 'in_reply_to', 'Content-Type': 'content_type', 'Errors-To': 'errors_to', 'Precedence': 'precedence', 'Boundary': 'boundary', 'MIME-Version': 'mime_version', 'X-Mailer': 'x_mailer', 'User-Agent': 'user_agent', 'X-Originating-IP': 'x_originating_ip', 'X-Priority': 'x_priority' } # TODO handle received_lines for key in header_map.keys(): val = msg.get(key, None) if val: email.header.__setattr__(header_map[key], val) email.header.__getattribute__(header_map[key]).condition = \ 'Equals' # TODO handle email bodies (it's mostly all there except for # handling weird text encoding problems that were making # libcybox stacktrace) # body = get_email_payload(random_spam_msg) # if body: # email.raw_body = body stix_package.add_observable(Observable(email)) except: return (None) observable_id = stix_package.observables.observables[0].id_ return (observable_id, stix_package)
def gen_stix_observable_sample(config, target=None, datatype=None, title='random test data', description='random test data', package_intents='Indicators - Watchlist', tlp_color='WHITE'): '''generate sample stix data comprised of indicator_count indicators of type datatype''' # setup the xmlns... xmlns_url = config['edge']['sites'][target]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][target]['stix']['xmlns_name'] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = '../../../../descendant-or-self::node()' tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) # ...and stuff it full of random sample data :-) if datatype == 'ip': addr = Address(address_value=datagen.generate_random_ip_address(), category='ipv4-addr') addr.condition = 'Equals' stix_package.add_observable(Observable(addr)) elif datatype == 'domain': domain = DomainName() domain.type_ = 'FQDN' domain.value = datagen.generate_random_domain(config) domain.condition = 'Equals' stix_package.add_observable(Observable(domain)) elif datatype == 'filehash': file_object = File() file_object.file_name = str(uuid.uuid4()) + '.exe' hashes = datagen.generate_random_hashes() for hash in hashes.keys(): file_object.add_hash(Hash(hashes[hash], type_=hash.upper())) for i in file_object.hashes: i.simple_hash_value.condition = "Equals" stix_package.add_observable(Observable(file_object)) elif datatype == 'email': try: msg = datagen.get_random_spam_msg(config) email = EmailMessage() email.header = EmailHeader() header_map = {'Subject': 'subject', 'To': 'to', 'Cc': 'cc', 'Bcc': 'bcc', 'From': 'from_', 'Sender': 'sender', 'Date': 'date', 'Message-ID': 'message_id', 'Reply-To': 'reply_to', 'In-Reply-To': 'in_reply_to', 'Content-Type': 'content_type', 'Errors-To': 'errors_to', 'Precedence': 'precedence', 'Boundary': 'boundary', 'MIME-Version': 'mime_version', 'X-Mailer': 'x_mailer', 'User-Agent': 'user_agent', 'X-Originating-IP': 'x_originating_ip', 'X-Priority': 'x_priority'} # TODO handle received_lines for key in header_map.keys(): val = msg.get(key, None) if val: email.header.__setattr__(header_map[key], val) email.header.__getattribute__(header_map[key]).condition = \ 'Equals' # TODO handle email bodies (it's mostly all there except for # handling weird text encoding problems that were making # libcybox stacktrace) # body = get_email_payload(random_spam_msg) # if body: # email.raw_body = body stix_package.add_observable(Observable(email)) except: return(None) observable_id = stix_package.observables.observables[0].id_ return(observable_id, stix_package)
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg = STIXPackage() pkg.title = "Examples of Observable Composition" # USE CASE: single obj with single condition obs = File() obs.file_name = "foo.exe" obs.file_name.condition = "Contains" pkg.add_observable(obs) # USE CASE: single obj with multiple conditions obs = File() obs.file_name = "foo" obs.file_name.condition = "Contains" obs.size_in_bytes = '1896000' obs.size_in_bytes.condition = "Equals" pkg.add_observable(obs) # USE CASE: multiple obj with individual conditions obs = EmailMessage() obs.subject = "Syria strategic plans leaked" obs.subject.condition = "Equals" file_obj = File() file_obj.file_name = "bombISIS.pdf" file_obj.file_name.condition = "Equals" obs.add_related(file_obj, "Contains") pkg.add_observable(obs) # USE CASE: multiple objects with complex condition like (A OR B) AND C # orcomp = either of a mutex or file are present orcomp = ObservableComposition() orcomp.operator = "OR" obs = Mutex() obs.name = 'foo' obs.name.condition = "Contains" orcomp.add(obs) obs = File() obs.file_name = "barfoobar" obs.file_name.condition = "Equals" orcomp.add(obs) # andcomp = the above is true AND a network connection is present andcomp = ObservableComposition() andcomp.operator = "AND" andcomp.add(orcomp) obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock andcomp.add(obs) pkg.add_observable(andcomp) # USE CASE: single object, one property with multiple values obs = SocketAddress() obs.ip_address = ['10.0.0.0', '10.0.0.1', '10.0.0.2'] # comma delimiter automagically added obs.ip_address.condition = "Equals" obs.ip_address.apply_condition = "ANY" pkg.add_observable(obs) print pkg.to_xml()
def parse(self, argument_log): """ Parses Suricata IDS log lines into STIX/CybOX format. :param argument_log: The log line to try and identify :return: STIX Incident """ argument_log = " ".join(argument_log.split(" ")[5:]) parsed_suricata_log = {} for regex in self._regex: try: parsed_suricata_log[regex] = re.match(self._regex[regex], argument_log).group(1) except: print "Failed to parse %s" % (regex) return False #TODO: Time Zones parsed_suricata_log["unix_timestamp"] = time.mktime(datetime.datetime.strptime(parsed_suricata_log["time"], "%m/%d/%Y-%H:%M:%S").timetuple()) # Find IP's of interest if IPAddress(parsed_suricata_log["source_ip"]).is_private() == False or IPAddress(parsed_suricata_log["destination_ip"]).is_private() == False: # Name Space stix.utils.idgen.set_id_namespace(Namespace(self._config["NAMESPACE"]["url"], self._config["NAMESPACE"]["name"],"")) stix_package = STIXPackage() # If the source is public if not IPAddress(parsed_suricata_log["source_ip"]).is_private() and IPAddress(parsed_suricata_log["destination_ip"]).is_private(): incident = Incident(title="[IDS Alert] "+parsed_suricata_log["text"]+" From "+ parsed_suricata_log["source_ip"]) addr = Address(address_value=parsed_suricata_log["source_ip"], category=Address.CAT_IPV4) elif IPAddress(parsed_suricata_log["source_ip"]).is_private() and not IPAddress(parsed_suricata_log["destination_ip"]).is_private(): incident = Incident(title="[IDS Alert] "+parsed_suricata_log["text"]+" To "+ parsed_suricata_log["destination_ip"]) addr = Address(address_value=parsed_suricata_log["destination_ip"], category=Address.CAT_IPV4) else: #public to public - i can't tell who the bad guy is return False observable = Observable(item=addr, title="[IP Associated To IDS Alert] "+parsed_suricata_log["text"], description="""This ip address was seen to be involved in triggering the IDS alert %s if seen from multiple sources, this is a good indicator of a potential threat actor or compromised host""" % (parsed_suricata_log["text"])) stix_package.add_observable(observable) incident.time = Time() incident.time.first_malicious_action = parsed_suricata_log["time"] related_observable = RelatedObservable(Observable(idref=observable.id_)) incident.related_observables.append(related_observable) stix_package.add_incident(incident) return stix_package.to_xml()
def export_stix(): """ Export the tagged items in STIX format. This prompts the user to determine which file they want the STIX saved out too. """ filename = asksaveasfilename(title="Save As", filetypes=[("xml file",".xml"),("All files",".*")]) observables_doc = None stix_package = STIXPackage() stix_header = STIXHeader() stix_header.description = filename stix_package.stix_header = stix_header if filename: observables = [] for t in tags: indicators = [] myhighlights = text.tag_ranges(t) mystart = 0 for h in myhighlights: if mystart == 0: mystart = h else: mystop = h value = text.get(mystart,mystop).replace('[.]','.').replace('[@]','@') if t == 'md5': value = value.upper() if value not in indicators: observable = cybox_helper.create_file_hash_observable('', value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'ipv4': if not value in indicators: observable = cybox_helper.create_ipv4_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'domain': if not value in indicators: observable = cybox_helper.create_domain_name_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'url': if not value in indicators: observable = cybox_helper.create_url_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) elif t == 'email': if not value in indicators: observable = cybox_helper.create_email_address_observable(value) observables.append(observable) stix_package.add_observable(observable) indicators.append(value) mystart = 0 # end if # end for # end for if len(observables) > 0: if not filename.endswith('.xml'): filename = "%s.xml" % filename #add .xml extension if missing # end if with open(filename, "wb") as f: stix_xml = stix_package.to_xml() f.write(stix_xml)
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg = STIXPackage() pkg.title="Examples of Observable Composition" # USE CASE: single obj with single condition obs = File() obs.file_name = "foo.exe" obs.file_name.condition = "Contains" pkg.add_observable(obs) # USE CASE: single obj with multiple conditions obs = File() obs.file_name = "foo" obs.file_name.condition = "Contains" obs.size_in_bytes = '1896000' obs.size_in_bytes.condition = "Equals" pkg.add_observable(obs) # USE CASE: multiple obj with individual conditions obs = EmailMessage() obs.subject = "Syria strategic plans leaked" obs.subject.condition= "Equals" file_obj = File() file_obj.file_name = "bombISIS.pdf" file_obj.file_name.condition = "Equals" obs.add_related(file_obj, "Contains") pkg.add_observable(obs) # USE CASE: multiple objects with complex condition like (A OR B) AND C # orcomp = either of a mutex or file are present orcomp = ObservableComposition() orcomp.operator = "OR" obs = Mutex() obs.name = 'foo' obs.name.condition= "Contains" orcomp.add(obs) obs = File() obs.file_name = "barfoobar" obs.file_name.condition = "Equals" orcomp.add(obs) # andcomp = the above is true AND a network connection is present andcomp = ObservableComposition() andcomp.operator = "AND" andcomp.add(orcomp) obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock andcomp.add (obs) pkg.add_observable(andcomp) # USE CASE: single object, one property with multiple values obs = SocketAddress() obs.ip_address = ['10.0.0.0','10.0.0.1','10.0.0.2'] # comma delimiter automagically added obs.ip_address.condition = "Equals" obs.ip_address.apply_condition = "ANY" pkg.add_observable(obs) print pkg.to_xml()
def main(): # get args parser = argparse.ArgumentParser ( description = "Parse a given CSV from Shadowserver and output STIX XML to stdout" , formatter_class=argparse.ArgumentDefaultsHelpFormatter ) parser.add_argument("--infile","-f", help="input CSV with bot data", default = "bots.csv") args = parser.parse_args() # setup stix document stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = "Bot Server IP addresses" stix_header.description = "IP addresses connecting to bot control servers at a given port" stix_header.add_package_intent ("Indicators - Watchlist") # add marking mark = Marking() markspec = MarkingSpecification() markstruct = SimpleMarkingStructure() markstruct.statement = "Usage of this information, including integration into security mechanisms implies agreement with the Shadowserver Terms of Service available at https://www.shadowserver.org/wiki/pmwiki.php/Shadowserver/TermsOfService" markspec.marking_structures.append(markstruct) mark.add_marking(markspec) stix_header.handling = mark # include author info stix_header.information_source = InformationSource() stix_header.information_source.time = Time() stix_header.information_source.time.produced_time =datetime.now(tzutc()) stix_header.information_source.tools = ToolInformationList() stix_header.information_source.tools.append("ShadowBotnetIP-STIXParser") stix_header.information_source.identity = Identity() stix_header.information_source.identity.name = "MITRE STIX Team" stix_header.information_source.add_role(VocabString("Format Transformer")) src = InformationSource() src.description = "https://www.shadowserver.org/wiki/pmwiki.php/Services/Botnet-CCIP" srcident = Identity() srcident.name = "shadowserver.org" src.identity = srcident src.add_role(VocabString("Originating Publisher")) stix_header.information_source.add_contributing_source(src) stix_package.stix_header = stix_header # add TTP for overall indicators bot_ttp = TTP() bot_ttp.title = 'Botnet C2' bot_ttp.resources = Resource() bot_ttp.resources.infrastructure = Infrastructure() bot_ttp.resources.infrastructure.title = 'Botnet C2' stix_package.add_ttp(bot_ttp) # read input data fd = open (args.infile, "rb") infile = csv.DictReader(fd) for row in infile: # split indicators out, may be 1..n with positional storage, same port and channel, inconsistent delims domain = row['Domain'].split() country = row['Country'].split() region = row['Region'].split('|') state = row['State'].split('|') asn = row['ASN'].split() asname = row['AS Name'].split() asdesc = row['AS Description'].split('|') index = 0 for ip in row['IP Address'].split(): indicator = Indicator() indicator.title = "IP indicator for " + row['Channel'] indicator.description = "Bot connecting to control server" # point to overall TTP indicator.add_indicated_ttp(TTP(idref=bot_ttp.id_)) # add our IP and port sock = SocketAddress() sock.ip_address = ip # add sighting sight = Sighting() sight.timestamp = "" obs = Observable(item=sock.ip_address) obsref = Observable(idref=obs.id_) sight.related_observables.append(obsref) indicator.sightings.append(sight) stix_package.add_observable(obs) # add pattern for indicator sock_pattern = SocketAddress() sock_pattern.ip_address = ip port = Port() port.port_value = row['Port'] sock_pattern.port = port sock_pattern.ip_address.condition= "Equals" sock_pattern.port.port_value.condition= "Equals" indicator.add_object(sock_pattern) stix_package.add_indicator(indicator) # add domain domain_obj = DomainName() domain_obj.value = domain[index] domain_obj.add_related(sock.ip_address,"Resolved_To", inline=False) stix_package.add_observable(domain_obj) # add whois obs whois_obj = WhoisEntry() registrar = WhoisRegistrar() registrar.name = asname[index] registrar.address = state[index] + region[index] + country[index] whois_obj.registrar_info = registrar whois_obj.add_related(sock.ip_address,"Characterizes", inline=False) stix_package.add_observable(whois_obj) # add ASN obj asn_obj = AutonomousSystem() asn_obj.name = asname[index] asn_obj.number = asn[index] asn_obj.handle = "AS" + str(asn[index]) asn_obj.add_related(sock.ip_address,"Contains", inline=False) stix_package.add_observable(asn_obj) # iterate index = index + 1 print stix_package.to_xml()