def test_remove_custom_stix_no_custom(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = stix2.utils.remove_custom_stix(campaign_v1) assert len(campaign_v1.keys()) == len(campaign_v2.keys()) assert campaign_v1.id == campaign_v2.id assert campaign_v1.description == campaign_v2.description
def test_versioning_error_invalid_property(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) with pytest.raises(stix2.exceptions.UnmodifiablePropertyError) as excinfo: campaign_v1.new_version(type="threat-actor") assert str( excinfo.value ) == "These properties cannot be changed when making a new version: type."
def ds(): cam = stix2.Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS) idy = stix2.Identity(id=IDENTITY_ID, **IDENTITY_KWARGS) ind = stix2.Indicator(id=INDICATOR_ID, **INDICATOR_KWARGS) mal = stix2.Malware(id=MALWARE_ID, **MALWARE_KWARGS) rel1 = stix2.Relationship(ind, 'indicates', mal, id=RELATIONSHIP_IDS[0]) rel2 = stix2.Relationship(mal, 'targets', idy, id=RELATIONSHIP_IDS[1]) rel3 = stix2.Relationship(cam, 'uses', mal, id=RELATIONSHIP_IDS[2]) stix_objs = [cam, idy, ind, mal, rel1, rel2, rel3] yield stix2.MemoryStore(stix_objs)
def test_versioning_error_revoke_of_revoked(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.revoke() with pytest.raises(stix2.exceptions.RevokeError) as excinfo: campaign_v2.revoke() assert str(excinfo.value) == "Cannot revoke an already revoked object." assert excinfo.value.called_by == "revoke" assert str(excinfo.value) == "Cannot revoke an already revoked object."
def test_campaign_add_markings(): campaign = stix2.Campaign( id="campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f", created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff", created="2016-04-06T20:03:00Z", modified="2016-04-06T20:03:00Z", name="Green Group Attacks Against Finance", description="Campaign by Green Group against a series of targets in the financial services sector.", ) campaign = campaign.add_markings(TLP_WHITE) assert campaign.object_marking_refs[0] == TLP_WHITE.id
def test_campaign_with_markings_example(): campaign = stix2.Campaign( id="campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f", created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff", created="2016-04-06T20:03:00Z", modified="2016-04-06T20:03:00Z", name="Green Group Attacks Against Finance", description= "Campaign by Green Group against a series of targets in the financial services sector.", object_marking_refs=TLP_WHITE) assert str(campaign) == EXPECTED_CAMPAIGN_WITH_OBJECT_MARKING
def test_making_new_version_with_unset(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.new_version(description=None) assert campaign_v1.id == campaign_v2.id assert campaign_v1.created_by_ref == campaign_v2.created_by_ref assert campaign_v1.created == campaign_v2.created assert campaign_v1.name == campaign_v2.name with pytest.raises(AttributeError): assert campaign_v2.description assert campaign_v1.modified < campaign_v2.modified
def test_making_new_version(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.new_version(name="fred") assert campaign_v1.id == campaign_v2.id assert campaign_v1.created_by_ref == campaign_v2.created_by_ref assert campaign_v1.created == campaign_v2.created assert campaign_v1.name != campaign_v2.name assert campaign_v2.name == "fred" assert campaign_v1.description == campaign_v2.description assert campaign_v1.modified < campaign_v2.modified
def test_versioning_error_new_version_of_revoked(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.revoke() with pytest.raises(stix2.exceptions.RevokeError) as excinfo: campaign_v2.new_version(name="barney") assert str( excinfo.value) == "Cannot create a new version of a revoked object." assert excinfo.value.called_by == "new_version" assert str( excinfo.value) == "Cannot create a new version of a revoked object."
def test_versioning_error_usetting_required_property(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: campaign_v1.new_version(name=None) assert excinfo.value.cls == stix2.Campaign assert excinfo.value.properties == ["name"] msg = "No values for required properties for {0}: ({1})." msg = msg.format(stix2.Campaign.__name__, "name") assert str(excinfo.value) == msg
def test_revoke(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.revoke() assert campaign_v1.id == campaign_v2.id assert campaign_v1.created_by_ref == campaign_v2.created_by_ref assert campaign_v1.created == campaign_v2.created assert campaign_v1.name == campaign_v2.name assert campaign_v1.description == campaign_v2.description assert campaign_v1.modified < campaign_v2.modified assert campaign_v2.revoked
def test_campaign_with_granular_markings_example(): campaign = stix2.Campaign( id="campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f", created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff", created="2016-04-06T20:03:00Z", modified="2016-04-06T20:03:00Z", name="Green Group Attacks Against Finance", description="Campaign by Green Group against a series of targets in the financial services sector.", granular_markings=[ stix2.GranularMarking( marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9", selectors=["description"]) ]) assert str(campaign) == EXPECTED_CAMPAIGN_WITH_GRANULAR_MARKINGS
def test_versioning_error_bad_modified_value(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo: campaign_v1.new_version(modified="2015-04-06T20:03:00.000Z") assert excinfo.value.cls == stix2.Campaign assert excinfo.value.prop_name == "modified" assert excinfo.value.reason == "The new modified datetime cannot be before the current modified datatime." msg = "Invalid value for {0} '{1}': {2}" msg = msg.format( stix2.Campaign.__name__, "modified", "The new modified datetime cannot be before the current modified datatime." ) assert str(excinfo.value) == msg
def test_versioning_error_bad_modified_value(): campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS) with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo: campaign_v1.new_version(modified="2015-04-06T20:03:00.000Z") assert excinfo.value.cls == stix2.Campaign assert excinfo.value.prop_name == "modified" assert excinfo.value.reason == "The new modified datetime cannot be before than or equal to the current modified datetime." \ "It cannot be equal, as according to STIX 2 specification, objects that are different " \ "but have the same id and modified timestamp do not have defined consumer behavior." msg = "Invalid value for {0} '{1}': {2}" msg = msg.format( stix2.Campaign.__name__, "modified", "The new modified datetime cannot be before than or equal to the current modified datetime." "It cannot be equal, as according to STIX 2 specification, objects that are different " "but have the same id and modified timestamp do not have defined consumer behavior." ) assert str(excinfo.value) == msg
def test_making_new_version_with_embedded_object(): campaign_v1 = stix2.Campaign(external_references=[{ "source_name": "capec", "external_id": "CAPEC-163" }], **CAMPAIGN_MORE_KWARGS) campaign_v2 = campaign_v1.new_version( external_references=[{ "source_name": "capec", "external_id": "CAPEC-164" }]) assert campaign_v1.id == campaign_v2.id assert campaign_v1.created_by_ref == campaign_v2.created_by_ref assert campaign_v1.created == campaign_v2.created assert campaign_v1.name == campaign_v2.name assert campaign_v1.description == campaign_v2.description assert campaign_v1.modified < campaign_v2.modified assert campaign_v1.external_references[ 0].external_id != campaign_v2.external_references[0].external_id
def stix_bundle(objs, mask=True): objects = () for obj in objs: oid = obj.object_id.object_id dscr = "" if not mask and hasattr(obj, "description"): dscr = obj.description if obj.object_type.name == 'attack-pattern': a = stix2.AttackPattern( id=oid, name=obj.name, description=dscr, created=obj.created, modified=obj.modified, kill_chain_phases=stix2killchain(obj), ) objects += (a, ) elif obj.object_type.name == 'campaign': c = stix2.Campaign( id=oid, name=obj.name, description=dscr, aliases=[str(a.name) for a in obj.aliases.all()], created=obj.created, modified=obj.modified, first_seen=obj.first_seen, last_seen=obj.last_seen, ) objects += (c, ) elif obj.object_type.name == 'course-of-action': c = stix2.CourseOfAction( id=oid, name=obj.name, description=dscr, created=obj.created, modified=obj.modified, ) objects += (c, ) elif obj.object_type.name == 'identity': name = obj.name if mask: name = oid label = obj.labels.all() if label.count() >= 1: name = str(obj.id) if label[0].alias: name += '-' + label[0].alias else: name += '-' + label[0].value i = stix2.Identity( id=oid, name=name, identity_class=obj.identity_class, description=dscr, sectors=[str(s.value) for s in obj.sectors.all()], labels=[str(l.value) for l in obj.labels.all()], created=obj.created, modified=obj.modified, ) objects += (i, ) elif obj.object_type.name == 'indicator': pattern = "[]" if not mask and obj.pattern: pattern = obj.pattern.pattern i = stix2.Indicator( id=oid, name=obj.name, description=dscr, labels=[str(l.value) for l in obj.labels.all()], pattern=pattern, created=obj.created, modified=obj.modified, valid_from=obj.valid_from, valid_until=obj.valid_until, ) objects += (i, ) elif obj.object_type.name == 'intrusion-set': i = stix2.IntrusionSet( id=oid, name=obj.name, description=dscr, aliases=[str(a.name) for a in obj.aliases.all()], created=obj.created, modified=obj.modified, first_seen=obj.first_seen, #last_seen=obj.last_seen, ) objects += (i, ) elif obj.object_type.name == 'malware': m = stix2.Malware( id=oid, name=obj.name, description=dscr, labels=[str(l.value) for l in obj.labels.all()], created=obj.created, modified=obj.modified, kill_chain_phases=stix2killchain(obj), ) objects += (m, ) elif obj.object_type.name == 'observed-data': obs = {} for o in obj.observable_objects.all(): ob = None if o.type.name == "file": f = FileObject.objects.get(id=o.id) ob = stix2.File(name=f.name) elif o.type.name == "ipv4-addr": i = IPv4AddressObject.objects.get(id=o.id) ob = stix2.IPv4Address(value=i.value) elif o.type.name == "url": u = URLObject.objects.get(id=o.id) ob = stix2.URL(value=u.value) elif o.type.name == "domain-name": dn = DomainNameObject.objects.get(id=o.id) ob = stix2.DomainName(value=dn.value) if ob and not mask: obs[str(o.id)] = json.loads(str(ob)) od = stix2.ObservedData( id=oid, created=obj.created, modified=obj.modified, first_observed=obj.first_observed, last_observed=obj.last_observed, number_observed=obj.number_observed, objects=obs, ) objects += (od, ) elif obj.object_type.name == 'report': created_by = None if obj.created_by_ref: created_by = obj.created_by_ref.object_id r = stix2.Report( id=oid, labels=[str(l.value) for l in obj.labels.all()], name=obj.name, description=dscr, published=obj.published, object_refs=[str(r.object_id) for r in obj.object_refs.all()], created_by_ref=created_by, created=obj.created, modified=obj.modified, ) objects += (r, ) elif obj.object_type.name == 'threat-actor': t = stix2.ThreatActor( id=oid, name=obj.name, description=dscr, labels=[str(l.value) for l in obj.labels.all()], aliases=[str(a.name) for a in obj.aliases.all()], created=obj.created, modified=obj.modified, ) objects += (t, ) elif obj.object_type.name == 'tool': t = stix2.Tool( id=oid, name=obj.name, description=dscr, labels=[str(l.value) for l in obj.labels.all()], created=obj.created, modified=obj.modified, kill_chain_phases=stix2killchain(obj), ) objects += (t, ) elif obj.object_type.name == 'vulnerability': v = stix2.Vulnerability( id=oid, name=obj.name, description=dscr, created=obj.created, modified=obj.modified, ) objects += (v, ) elif obj.object_type.name == 'relationship': r = stix2.Relationship( id=oid, relationship_type=obj.relationship_type.name, description=dscr, source_ref=obj.source_ref.object_id, target_ref=obj.target_ref.object_id, created=obj.created, modified=obj.modified, ) objects += (r, ) elif obj.object_type.name == 'sighting': s = stix2.Sighting( id=oid, sighting_of_ref=obj.sighting_of_ref.object_id, where_sighted_refs=[ str(w.object_id.object_id) for w in obj.where_sighted_refs.all() ], observed_data_refs=[ str(od.object_id.object_id) for od in obj.observed_data_refs.all() ], first_seen=obj.first_seen, last_seen=obj.last_seen, created=obj.created, modified=obj.modified, ) objects += (s, ) bundle = stix2.Bundle(*objects) return bundle
def campaign_maker(**kwargs): campaign = stix2.Campaign(**kwargs) flag = itemtofile(campaign) return flag, campaign
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")
external_references=[ref_capec1] ) attack_pattern2 = stix2.AttackPattern( id="attack-pattern--f6050ea6-a9a3-4524-93ed-c27858d6cb3c", created="2016-08-08T15:50:10.983Z", modified="2017-01-30T21:15:04.127Z", name="HTTP Flood", external_references=[ref_capec2] ) campaign1 = stix2.Campaign( id="campaign--e5268b6e-4931-42f1-b379-87f48eb41b1e", created="2016-08-08T15:50:10.983Z", modified="2016-08-08T15:50:10.983Z", name="Operation Bran Flakes", description="A concerted effort to insert false information into the BPP's web pages.", aliases=["OBF"], first_seen="2016-01-08T12:50:40.123Z", objective="Hack www.bpp.bn" ) campaign2 = stix2.Campaign( id="campaign--1d8897a7-fdc2-4e59-afc9-becbe04df727", created="2016-08-08T15:50:10.983Z", modified="2016-08-08T15:50:10.983Z", name="Operation Raisin Bran", description="A DDOS campaign to flood BPP web servers.", aliases=["ORB"], first_seen="2016-02-07T19:45:32.126Z", objective="Flood www.bpp.bn" )
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 = raw_input("Insert Title Ioc:") # La description strutturiamola come segue # <IOC PRODUCER> - <Descrizione della minaccia/campagna> - <URL (if any)> DESCRIPTION = raw_input("Insert Decription:") # La sorgente che ha generato l'IoC con riferimento a Cyber Saiyan Community IDENTITY = raw_input("Insert User Identity:") # File degli IoC IOCFILE = raw_input("Add IoC Source File:") # Prefisso STIX output files STIX 1.2 e STIX 2 OUTFILEPREFIX = "package" # Short Description - UNUSED #SHORT = "Emotet" ###################################################################### VERBOSE = 0 # UTF8 encode TITLE = TITLE.encode('utf8') DESCRIPTION = DESCRIPTION.encode('utf8') IDENTITY = IDENTITY.encode('utf8') print "\nStix File generation in progress...." #print (TITLE) #"TITLE: " + TITLE #print (DESCRIPTION) #"DESCRIPTION: " + DESCRIPTION #print (IDENTITY) #"IDENTITY: " + IDENTITY #print (IOCFILE) #"IOC FILE: " + IOCFILE #print "---------------------" ######################## # Commond data timestamp = datetime.datetime.fromtimestamp( time.time()).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) # 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.MarkingDefinition(definition_type="tlp", definition={"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 ioc = loaddata(IOCFILE) if (VERBOSE): print "Reading IoC file " + IOCFILE + "..." 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: # STIX 1.2 filei = File() filei.add_hash(Hash(ioc)) obsi = Observable(filei) indicatorHASH.add_observable(obsi) if (VERBOSE): print "SHA256: " + ioc notfound = 0 # STIX 2 pattern_sha256.append("[file:hashes.'SHA-256' = '" + ioc + "'] OR ") #md5 p = re.compile(r"^[0-9a-f]{32}$", re.IGNORECASE) m = p.match(ioc) if m and notfound: # STIX 1.2 filej = File() filej.add_hash(Hash(ioc)) obsj = Observable(filej) indicatorHASH.add_observable(obsj) if (VERBOSE): print "MD5: " + ioc notfound = 0 # STIX 2 pattern_md5.append("[file:hashes.'MD5' = '" + ioc + "'] OR ") #sha1 p = re.compile(r"^[0-9a-f]{40}$", re.IGNORECASE) m = p.match(ioc) if m and notfound: # STIX 1.2 filek = File() filek.add_hash(Hash(ioc)) obsk = Observable(filek) indicatorHASH.add_observable(obsk) if (VERBOSE): print "SHA1: " + ioc notfound = 0 # STIX 2 pattern_sha1.append("[file:hashes.'SHA1' = '" + ioc + "'] OR ") #domains if validators.domain(ioc) and notfound: # 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 notfound = 0 # STIX 2 pattern_domain.append("[domain-name:value = '" + ioc + "'] OR ") #url if validators.url(ioc) and notfound: # 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 notfound = 0 # STIX 2 pattern_url.append("[url:value = '" + ioc + "'] OR ") #ip if validators.ipv4(ioc) and notfound: # STIX 1.2 ip = Address() ip.address_value = ioc obsu = Observable(ip) indiIP.add_observable(obsu) if (VERBOSE): print "IP: " + ioc notfound = 0 # STIX 2 pattern_ip.append("[ipv4-addr:value = '" + ioc + "'] OR ") #email if validators.email(ioc) and notfound: # STIX 1.2 email = EmailAddress() email.address_value = ioc obsu = Observable(email) indiEMAIL.add_observable(obsu) if (VERBOSE): print "Email: " + ioc notfound = 0 # STIX 2 pattern_email.append("[email-message:from_ref.value = '" + ioc + "'] 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 bundle = stix2.Bundle(objects=bundle_objects) ######################## # save to STIX 1.2 file print print "Writing STIX 1.2 package: " + OUTFILEPREFIX + ".stix" f = open(OUTFILEPREFIX + ".stix", "w") f.write(wrapper.to_xml()) f.close() ######################## # save to STIX 2 file print "Writing STIX 2 package: " + OUTFILEPREFIX + ".stix2" g = open(OUTFILEPREFIX + ".stix2", "w") sys.stdout = g print bundle
TOOL_KWARGS = dict(type='tool', id=TOOL_ID, labels=["remote-access"], name="VNC", created_by_ref=IDENTITY_ID, interoperability=True) VULNERABILITY_KWARGS = dict(type='vulnerability', id=VULNERABILITY_ID, name="Heartbleed", created_by_ref=IDENTITY_ID) if __name__ == '__main__': attack_pattern = stix2.AttackPattern(**ATTACK_PATTERN_KWARGS, interoperability=True) campaign = stix2.Campaign(**CAMPAIGN_KWARGS, interoperability=True) course_of_action = stix2.CourseOfAction(**COURSE_OF_ACTION_KWARGS, interoperability=True) identity = stix2.Identity(**IDENTITY_KWARGS, interoperability=True) indicator = stix2.Indicator(**INDICATOR_KWARGS, interoperability=True) intrusion_set = stix2.IntrusionSet(**INTRUSION_SET_KWARGS, interoperability=True) malware = stix2.Malware(**MALWARE_KWARGS, interoperability=True) marking_definition = stix2.MarkingDefinition(**MARKING_DEFINITION_KWARGS, interoperability=True) observed_data = stix2.ObservedData(**OBSERVED_DATA_KWARGS, interoperability=True) relationship = stix2.Relationship(**RELATIONSHIP_KWARGS, interoperability=True) sighting = stix2.Sighting(**SIGHTING_KWARGS, interoperability=True) threat_actor = stix2.ThreatActor(**THREAT_ACTOR_KWARGS,