def rel_mem_store(): cam = Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS) idy = Identity(id=IDENTITY_ID, **IDENTITY_KWARGS) ind = Indicator(id=INDICATOR_ID, **INDICATOR_KWARGS) mal = Malware(id=MALWARE_ID, **MALWARE_KWARGS) rel1 = Relationship(ind, 'indicates', mal, id=RELATIONSHIP_IDS[0]) rel2 = Relationship(mal, 'targets', idy, id=RELATIONSHIP_IDS[1]) rel3 = Relationship(cam, 'uses', mal, id=RELATIONSHIP_IDS[2]) stix_objs = [cam, idy, ind, mal, rel1, rel2, rel3] yield MemoryStore(stix_objs)
def createDNSObs(self, DNSOBJ): DNSObs = [] DNSRel = [] for host in DNSOBJ: IP = IPv4Address(value=host["ip"]) DNS = DomainName( value=host["domain"] ) # , resolves_to_refs=IP.id) ref https://github.com/OpenCTI-Platform/client-python/issues/155 Rel = Relationship( source_ref=DNS.id, target_ref=IP.id, relationship_type="resolves-to" ) if self.CreateIndicator: STIXPattern = self.getStixPattern(host["domain"], "FQDN") DNSind = Indicator( name=host["domain"], pattern=STIXPattern, pattern_type="stix" ) STIXPattern = self.getStixPattern(host["ip"], "ipv4") IPind = Indicator( name=host["ip"], pattern=STIXPattern, pattern_type="stix" ) DNSObs.append(DNSind) DNSObs.append(IPind) DNSObs.append(IP) DNSObs.append(DNS) DNSRel.append(Rel) return [DNSObs, DNSRel]
def createPrimaryBinary(self, file: cuckooReportDropped, external_references): hashes = { "MD5": file.md5.upper(), "SHA-1": file.sha1.upper(), "SHA-256": file.sha256.upper(), "SHA-512": file.sha512.upper(), "SSDEEP": file.ssdeep.upper(), } STIXPattern = self.getStixPattern(file.sha256, "sha256") size = 0 try: if file.size: size = file.size except: pass Filex = File(hashes=hashes, size=size, name=file.name, mime_type=file.type) ind = Indicator( name=file.name, pattern=STIXPattern, pattern_type="stix", external_references=external_references, ) rel = Relationship( source_ref=Filex.id, relationship_type="based-on", target_ref=ind.id ) return [Filex, ind, rel]
def processAndSubmit(self): # Create SDO's / Cyber Obs ext_ref = ExternalReference( source_name=f"Cuckoo Sandbox Report {str(self.report.info.id)}", url=f"{self.cuckoo_url}/analysis/{str(self.report.info.id)}/summary", external_id=str(self.report.info.id), ) if self.report.network.hosts: ips = self.createIPObs(self.report.network.hosts) else: ips = [] if self.report.network.domains: fqdns = self.createDNSObs(self.report.network.domains) else: fqdns = [[], []] if self.report.process: processes = self.createProcessObs(self.report.process) else: processes = [] if self.EnableRegKeys: if self.report.behavior: if self.report.behavior.regkey_written: registry_keys = self.createRegKeysObs( self.report.behavior.regkey_written ) else: registry_keys = None else: registry_keys = None else: registry_keys = None if self.EnableNetTraffic: if self.report.network: network_traffic = self.createNetTrafficObs(self.report.network) else: network_traffic = None else: network_traffic = None if self.report.dropped: dropped_binaries = self.createBinarieObs(self.report.dropped) else: dropped_binaries = [] if self.report.signatures: AttackPatterns = self.getAttackPatterns(self.report.signatures) else: AttackPatterns = [] self.helper.log_info(fqdns) # Get all IDs from ATPs/CyberObs IDs = self.get_related( ips, fqdns[0], processes, network_traffic, dropped_binaries, AttackPatterns, registry_keys, ) # Create Main binary and link All ATPs/Cyber Obs payload = self.createPrimaryBinary(self.report.target.file, ext_ref) payload_relations = [] bundle_ids = [] for ID in IDs: try: IDx = ID.id bundle_ids.append( ID ) # Get list for bundle w/o Attack Patterns that exisit except: IDx = ID payload_relations.append( Relationship( relationship_type="related-to", source_ref=payload[0].id, target_ref=IDx, ) ) for ATP in AttackPatterns: payload_relations.append( Relationship( relationship_type="related-to", source_ref=payload[0].id, target_ref=ATP, ) ) IDs.append(payload[0]) # Add Observeable IDs.append(payload[1]) # Add Indicator bundle_ids.append(payload[0]) bundle_ids.append(payload[1]) payload_relations.append(payload[2]) if int(self.report.info.score) >= self.ReportScore: # Create Report and link All ATPs/Cyber Obs/Payload report = self.createCuckooReport(self.report, IDs, ext_ref) b = Bundle( report, bundle_ids, payload_relations, fqdns[1] ) # fqdns[1] is the Resolves-to relations else: b = Bundle(bundle_ids, payload_relations, fqdns[1]) self.helper.send_stix2_bundle(b.serialize()) return None
type="intrusion-set", spec_version="2.1", id="intrusion-set--ed69450a-f067-4b51-9ba2-c4616b9a6713", created="2016-08-08T15:50:10.983Z", modified="2016-08-08T15:50:10.983Z", name="APT BPP", description= "An advanced persistent threat that seeks to disrupt Branistan's election with multiple attacks.", first_seen="2016-01-08T12:50:40.123Z", resource_level="government", primary_motivation="ideology", goals=["Influence the Branistan election", "Disrupt the BPP"], secondary_motivations=["dominance"], aliases=["Bran-teaser"]) relationship1 = Relationship(campaign1, 'attributed-to', threat_actor) relationship2 = Relationship(campaign2, 'attributed-to', threat_actor) relationship3 = Relationship(campaign1, 'attributed-to', intrusionset) relationship4 = Relationship(campaign2, 'attributed-to', intrusionset) relationship5 = Relationship(intrusionset, 'attributed-to', threat_actor) relationship6 = Relationship(intrusionset, 'targets', identity2) relationship7 = Relationship(intrusionset, 'uses', attack_pattern1) relationship8 = Relationship(intrusionset, 'uses', attack_pattern2) relationship9 = Relationship(campaign1, 'targets', identity2) relationship10 = Relationship(campaign2, 'targets', identity2) relationship11 = Relationship(campaign1, 'uses', attack_pattern1) relationship12 = Relationship(campaign2, 'uses', attack_pattern2) relationship13 = Relationship(threat_actor, 'impersonates', identity2) relationship14 = Relationship(threat_actor, 'targets', identity2) relationship15 = Relationship(threat_actor, 'attributed-to', identity1) relationship16 = Relationship(campaign2, 'targets', identity2)
def simulate(actors, orgs, tools, malwares, fs, start_date, td): """ Run one round of attacks and defenses with the given data set. Each threat actor in the 'actors' parameter takes an opportunity to choose and attack a target. The actor chooses a tool (and possibly malware) from the specified STIX data sets, and generates a random indicator. The attack is either successful or unsuccessful. Parameters ---------- actors : list of ThreatActor objects orgs : list of Identity objects STIX formatted Identity set filtered for identity_class=organization tools : list of Tool objects STIX formatted tool set to choose from malwares : list of Malware objects STIX formatted malware set to choose from fs : FileSystemStore Data store to save events start_date : datetime Start date for the events in the current round of the simulation td : time delta Time between each cyber event """ # Reference to convert the agent's sophistication level to an integer skill_levels = { "minimal": 1, "intermediate": 2, "advanced": 3, "expert": 4, "innovator": 5, "strategic": 6 } for agent in actors: # Pick a random target @TODO - make this more logical later target_id = np.random.choice([org.id for org in orgs]) target = [org for org in orgs if org['id'] == target_id][0] success = np.random.choice([True, False]) tool = tools[np.random.randint(0, len(tools))] tool_rels = fs.query([ Filter('type', '=', 'relationship'), Filter('source_ref', '=', agent.id), Filter('target_ref', '=', tool.id) ]) if len(tool_rels) == 0: fs.add(Relationship(agent, 'uses', tool)) indicator_type = np.random.choice(['IPv4 address', 'domain name']) used_malware = np.random.choice(['yes', 'no'], p=[.25, .75]) if used_malware == 'yes': malware = malwares[np.random.randint(0, len(malwares))] mw_rels = fs.query([ Filter('type', '=', 'relationship'), Filter('source_ref', '=', agent.id), Filter('target_ref', '=', malware.id) ]) if len(mw_rels) == 0: fs.add(Relationship(agent, 'uses', malware.id)) target_description = json.loads(target.description) description = f'On {str(start_date)[:10]}, ' if success is True: description += 'an attacker successfully attacked a company named ' else: description += 'an attack was attempted against a company named ' description += ( f'{target.name.upper()} located in the country of ' f'{target_description["Background"]["headquarters"]}. The ' f'attacker used the tool, {tool.name}, during its attack. ') if hasattr(agent, 'goals'): description += (f'It is believed the goal of the attack was to ' f'{np.random.choice(agent.goals)}.') description += ( f' One of the indicators discovered was the {indicator_type}, ' f'{random_indicator(indicator_type)}.') if used_malware == 'yes': description += (f' The attacker also attempted to use the malware ' f'{malware.name}.') fs.add( Sighting(description=description, first_seen=start_date, sighting_of_ref=agent.id)) start_date += timedelta(td)
from stix2.v21 import (ThreatActor, Identity, Relationship, Bundle) threat_actor = ThreatActor( id="threat-actor--dfaa8d77-07e2-4e28-b2c8-92e9f7b04428", created="2014-11-19T23:39:03.893Z", modified="2014-11-19T23:39:03.893Z", name="Disco Team Threat Actor Group", description= "This organized threat actor group operates to create profit from all types of crime.", threat_actor_types=["crime-syndicate"], aliases=["Equipo del Discoteca"], roles=["agent"], goals=["Steal Credit Card Information"], sophistication="expert", resource_level="organization", primary_motivation="personal-gain") identity = Identity( id="identity--733c5838-34d9-4fbf-949c-62aba761184c", created="2016-08-23T18:05:49.307Z", modified="2016-08-23T18:05:49.307Z", name="Disco Team", description= "Disco Team is the name of an organized threat actor crime-syndicate.", identity_class="organization", contact_information="*****@*****.**") relationship = Relationship(threat_actor, 'attributed-to', identity) bundle = Bundle(objects=[threat_actor, identity, relationship])
malware_types=["remote-access-trojan"], kill_chain_phases=[init_comp], spec_version="2.1", type="malware", is_family="false") ref = ExternalReference(source_name="capec", description="phishing", url="https://capec.mitre.org/data/definitions/98.html", external_id="CAPEC-98") attack_pattern = AttackPattern( id="attack-pattern--8ac90ff3-ecf8-4835-95b8-6aea6a623df5", created="2015-05-07T14:22:14.760Z", modified="2015-05-07T14:22:14.760Z", name="Phishing", description="Spear phishing used as a delivery mechanism for malware.", kill_chain_phases=[init_comp], external_references=[ref], spec_version="2.1", type="attack-pattern") relationship1 = Relationship(threat_actor, 'uses', malware) relationship2 = Relationship(threat_actor, 'uses', attack_pattern) relationship3 = Relationship(threat_actor, 'attributed-to', identity) bundle = Bundle(objects=[ threat_actor, malware, attack_pattern, identity, relationship1, relationship2, relationship3 ])
def create_threatactor(stix, nouns, adjectives, countries, fs): """ Create a basic threat actor profile, including country attribution, and save to the given data store. Parameters ---------- stix : dictionary Seed vocabulary for APT profiles nouns : list Words available for first word in APT name adjectives : list Words avialables for second word in APT name countries : list List of country objects (for setting attribution) fs : FileSystemStore object Where to locate the APT data """ # Create the name, but don't reuse nouns/adjs already chosen actors = fs.query(Filter('type', '=', 'threat-actor')) names_taken = [ta.name for ta in actors] adj = np.random.choice(adjectives) while adj in [name.split(' ')[0] for name in names_taken]: adj = np.random.choice(adjectives) noun = np.random.choice(nouns) while noun in [name.split(' ')[1] for name in names_taken]: noun = np.random.choice(nouns) agent_name = adj + " " + noun sophistication = str(np.random.choice(stix['threat-actor-sophistication'])) actor_type = np.random.choice( list(stix["threat-actor-type"].keys()), p=list(stix["threat-actor-type"].values())) # target sectors sectors = list(np.random.choice( stix['sectors'], np.random.randint(2, 4), False)) description = { 'sophistication': sophistication, 'actor_type': actor_type, 'target_sectors': sectors } aliases = [f"APT {1000+(len(actors))}"] aliases_taken = [] for ta in actors: aliases_taken.extend(ta.aliases) alias = ( f"{np.random.choice(stix['colors'])} " f"{np.random.choice(stix['animals'])}") while alias in aliases_taken: alias = ( f'{np.random.choice(stix["colors"])} ' f'{np.random.choice(stix["animals"])}') aliases.append(alias) first_seen = date.fromordinal(np.random.randint( date.today().replace(year=date.today().year-10).toordinal(), date.today().toordinal())) last_seen = date.fromordinal(np.random.randint( date.today().replace(year=date.today().year-1).toordinal(), date.today().toordinal())) while last_seen < first_seen: last_seen = date.fromordinal(np.random.randint( date.today().replace(year=date.today().year-1).toordinal(), date.today().toordinal())) resource_level = "government" motivations = list(np.random.choice( stix['attack-motivation'], np.random.randint(2, 4), replace=False)) primary_motivation = str(motivations[0]) secondary_motivations = motivations[1:] goals = list( np.random.choice(stix['goals'], np.random.randint(2, 4), False)) apt = IntrusionSet( name=agent_name, aliases=aliases, first_seen=first_seen, last_seen=last_seen, resource_level=resource_level, description=json.dumps(description), primary_motivation=primary_motivation, secondary_motivations=secondary_motivations, goals=goals ) fs.add(apt) # Find countries most likely to host threat actors relationships = fs.query([ Filter("type", "=", "relationship"), Filter("relationship_type", "=", "located-at"), Filter("source_ref", "contains", "intrusion-set")]) have_actors = [country.name for country in fs.query([ Filter("type", "=", "location"), Filter("id", "in", [r.target_ref for r in relationships])])] if actor_type == "terrorist": attr_countries = [ country.name for country in countries if hasattr(country, 'terrorism') and country.name not in have_actors] elif actor_type == "nation-state": attr_countries = [ (country.name, country.percent_GDP_on_military) for country in countries if hasattr(country, 'international_disputes') and country.name not in have_actors] attr_countries.sort(key=lambda x: x[1]) attr_countries = [country[0] for country in attr_countries] else: attr_countries = [ country.name for country in countries if country.name not in have_actors] if len(attr_countries) == 0: attr_countries = [ country.name for country in countries if country.name not in have_actors] if len(attr_countries) == 0: # all of the countries already have at least one actor attr_countries = [country.name for country in countries] # Set attribution country = fs.query([ Filter("type", "=", "location"), Filter("name", "=", attr_countries.pop())]) fs.add(Relationship(apt, 'located-at', country[0]))
def create_organization(stix, fs, country, org_names, assessment): """ Generate a company profile and save to the STIX data store Parameters ---------- stix : dictionary Seed vocabulary for organization profiles fs : FileSystemStore object Data store to save organization information country : string Name of country with which to associate organization org_names : list organization names to choose from assessment : dictionary representation of NIST 800-171 assessment table """ name = np.random.choice(org_names) revenue = int(np.random.chisquare(1) * 10000) while revenue == 0: revenue = int(np.random.chisquare(1) * 10000) sector = np.random.choice(stix['sectors']) description = { "Background": { "headquarters": country.name, "number of employees": "{:,}".format( np.random.randint(500, 15000)), "annual revenue": "$"+"{:,}".format(revenue)+" million" }, "Network": { "size": np.random.randint(1, 100) } } score = 0 vulns = [] dist = np.random.beta(2, 2) # overall scoring distribution while dist == 0: dist = np.random.beta(2, 2) for cat in assessment: for r in assessment[cat]: pf = np.random.choice(a=['Yes', 'No'], p=[dist, 1-dist]) if pf == 'Yes': score += r['Value'] else: vulns.append(r['Requirement']) description["Security Posture"] = { "vulnerability": int(score/313 * 100), "vulns": vulns } # Add asset to the STIX data store organization = Identity( name=name, identity_class='organization', sectors=sector, description=json.dumps(description) ) fs.add(organization) # Tie organization to country (headquarters) country_id = fs.query([ Filter('type', '=', 'location'), Filter("name", "=", country.name)])[0].id fs.add(Relationship(organization, 'located-at', country_id))
processes = list(set([a.strip() for a in f.read().split()])) with open("emails.txt") as f: emails = list(set([a.strip() for a in f.read().split()])) res = [] malware = Malware(name="Pegasus", is_family=False, description="IOCs for Pegasus") res.append(malware) for d in domains: i = Indicator(indicator_types=["malicious-activity"], pattern="[domain-name:value='{}']".format(d), pattern_type="stix") res.append(i) res.append(Relationship(i, 'indicates', malware)) for p in processes: i = Indicator(indicator_types=["malicious-activity"], pattern="[process:name='{}']".format(p), pattern_type="stix") res.append(i) res.append(Relationship(i, 'indicates', malware)) for f in filenames: i = Indicator(indicator_types=["malicious-activity"], pattern="[file:name='{}']".format(f), pattern_type="stix") res.append(i) res.append(Relationship(i, 'indicates', malware))
type="threat-actor") indicator = Indicator( id="indicator--1ed8caa7-a708-4706-b651-f1186ede6ca1", created="2017-04-27T16:18:24.318Z", modified="2017-04-27T16:18:24.318Z", created_by_ref="identity--b38dfe21-7477-40d1-aa90-5c8671ce51ca", name="Fake email address", description="Known to be used by The Joker.", indicator_types=["malicious-activity", "attribution"], pattern= "[email-message:from_ref.value MATCHES '.+\\\\banking@g0thamnatl\\\\.com$']", pattern_type="stix", valid_from="2017-04-27T16:18:24.318Z", granular_markings=[granular_red, granular_amber, granular_green], spec_version="2.1", type="indicator") rel = Relationship( id="relationship--3d1dd3cc-eb47-4704-9c77-ceff2971b95c", created="2017-04-27T16:18:24.318Z", modified="2017-04-27T16:18:24.318Z", relationship_type='indicates', source_ref="indicator--1ed8caa7-a708-4706-b651-f1186ede6ca1", target_ref="threat-actor--8b6297fe-cae7-47c6-9256-5584b417849c", object_marking_refs=[TLP_RED], spec_version="2.1", type="relationship") bundle = Bundle(objects=[identity, indicator, threat_actor, rel])
indicator = Indicator( id="indicator--d81f86b9-975b-4c0b-875e-810c5ad45a4f", created="2014-06-29T13:49:37.079Z", modified="2014-06-29T13:49:37.079Z", name="Malicious site hosting downloader", description= "This organized threat actor group operates to create profit from all types of crime.", indicator_types=["malicious-activity"], pattern="[url:value = 'http://x4z9arb.cn/4712/']", pattern_type="stix", valid_from="2014-06-29T13:49:37.079000Z") foothold = KillChainPhase(kill_chain_name="mandiant-attack-lifecycle-model", phase_name="establish-foothold") malware = Malware( id="malware--162d917e-766f-4611-b5d6-652791454fca", created="2014-06-30T09:15:17.182Z", modified="2014-06-30T09:15:17.182Z", name="x4z9arb backdoor", malware_types=["backdoor", "remote-access-trojan"], description= "This malware attempts to download remote files after establishing a foothold as a backdoor.", kill_chain_phases=[foothold], is_family="false") relationship = Relationship(indicator, 'indicates', malware) bundle = Bundle(objects=[indicator, malware, relationship])