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_relationship_missing_some_required_fields(): with pytest.raises(ValueError) as excinfo: # relationship_type is checked first, so make sure that is provided relationship = stix2.Relationship(relationship_type='indicates') assert str( excinfo.value ) == "Missing required field(s) for Relationship: (source_ref, target_ref)."
def test_invalid_kwarg_to_relationship(): with pytest.raises(TypeError) as excinfo: relationship = stix2.Relationship(my_custom_property="foo", **RELATIONSHIP_KWARGS) assert str( excinfo.value ) == "unexpected keyword arguments: ['my_custom_property']" in str(excinfo)
def test_relationship_required_properties_target_ref(): with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship(relationship_type='indicates', source_ref=INDICATOR_ID) assert excinfo.value.cls == stix2.Relationship assert excinfo.value.properties == ["target_ref"]
def test_create_relationship_with_positional_args(indicator, malware): relationship = stix2.Relationship(indicator, 'indicates', malware) assert relationship.relationship_type == 'indicates' assert relationship.source_ref == 'indicator--00000000-0000-0000-0000-000000000001' assert relationship.target_ref == 'malware--00000000-0000-0000-0000-000000000002' assert relationship.id == 'relationship--00000000-0000-0000-0000-000000000003'
def test_relationship_required_property_relationship_type(): with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship() assert excinfo.value.cls == stix2.Relationship assert excinfo.value.properties == [ "relationship_type", "source_ref", "target_ref" ]
def produce(self, tc_data: Union[list, dict]) -> Iterable[Visitor]: """Yield visitors that will apply relationship objects to a Stream of STIX data. Args: tc_data: the ThreatConnect data to produce Relationships based on. Yields: Visitors that will create STIX Relationship objects. """ if not isinstance(tc_data, list): tc_data = [tc_data] for data in tc_data: associations = data.pop('associations', []) for association in associations: source_xid = Batch.generate_xid( [data.get('summary'), data.get('ownerName')]) target_xid = Batch.generate_xid( [association.get('summary'), association.get('ownerName')]) yield stix2.Relationship( source_ref=f'indicator--{source_xid}', target_ref=f'indicator--{target_xid}', relationship_type='uses', )
def test_invalid_kwarg_to_relationship(): with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: stix2.Relationship(my_custom_property="foo", **RELATIONSHIP_KWARGS) assert excinfo.value.cls == stix2.Relationship assert excinfo.value.properties == ['my_custom_property'] assert str(excinfo.value) == "Unexpected properties for Relationship: (my_custom_property)."
def test_relationship_type_must_be_relationship(): with pytest.raises(ValueError) as excinfo: relationship = stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS) assert str( excinfo.value ) == "Invalid value for Relationship 'type': must equal 'relationship'."
def test_relationship_id_must_start_with_relationship(): with pytest.raises(ValueError) as excinfo: relationship = stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS) assert str( excinfo.value ) == "Invalid value for Relationship 'id': must start with 'relationship--'."
def test_relationship_id_must_start_with_relationship(): with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo: stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS) assert excinfo.value.cls == stix2.Relationship assert excinfo.value.prop_name == "id" assert excinfo.value.reason == "must start with 'relationship--'." assert str(excinfo.value) == "Invalid value for Relationship 'id': must start with 'relationship--'."
def test_relationship_type_must_be_relationship(): with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo: stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS) assert excinfo.value.cls == stix2.Relationship assert excinfo.value.prop_name == "type" assert excinfo.value.reason == "must equal 'relationship'." assert str(excinfo.value) == "Invalid value for Relationship 'type': must equal 'relationship'."
def test_relationship_required_field_target_ref(): with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: stix2.Relationship(relationship_type='indicates', source_ref=INDICATOR_ID) assert excinfo.value.cls == stix2.Relationship assert excinfo.value.fields == ["target_ref"] assert str(excinfo.value ) == "Missing required field(s) for Relationship: (target_ref)."
def to_relationship(obj1, relation, obj2): if type(obj1) == list: if type(obj2) != list: relationship_list = [] for index in range(len(obj1)): relationship = stix2.Relationship(obj1[index], relation, obj2) relationship_list.append(relationship) return relationship_list else: relationship_list = [] for index in range(len(obj1)): relationship = stix2.Relationship(obj1[index], relation, obj2[index]) relationship_list.append(relationship) return relationship_list else: relationship = stix2.Relationship(obj1, relation, obj2) return relationship
def test_create_relationship_from_objects_rather_than_ids(indicator, malware): relationship = stix2.Relationship( relationship_type="indicates", source_ref=indicator, target_ref=malware, ) assert relationship.relationship_type == 'indicates' assert relationship.source_ref == 'indicator--00000000-0000-0000-0000-000000000001' assert relationship.target_ref == 'malware--00000000-0000-0000-0000-000000000002' assert relationship.id == 'relationship--00000000-0000-0000-0000-000000000003'
def test_relationship_all_required_fields(): now = dt.datetime(2016, 4, 6, 20, 6, 37, tzinfo=pytz.utc) relationship = stix2.Relationship( type='relationship', id=RELATIONSHIP_ID, created=now, modified=now, relationship_type='indicates', source_ref=INDICATOR_ID, target_ref=MALWARE_ID, ) assert str(relationship) == EXPECTED_RELATIONSHIP
def fetch_and_send(self): timestamp = int(time.time()) now = datetime.utcfromtimestamp(timestamp) friendly_name = "Cyber Threat Coalition run @ " + now.strftime( "%Y-%m-%d %H:%M:%S" ) work_id = self.helper.api.work.initiate_work( self.helper.connect_id, friendly_name ) bundle_objects = list() # create an identity for the coalition team organization = stix2.Identity( id=OpenCTIStix2Utils.generate_random_stix_id("identity"), name="Cyber Threat Coalition Team", identity_class="organization", description="Team of Experts collecting and sharing pandemic related " "cyber threat intelligence during the COVID-19 crisis time", ) # add organization in bundle bundle_objects.append(organization) report_object_refs = list() for collection in ["domain", "ip", "url", "hash"]: # fetch backlist url = self.cyber_threat_coalition_base_url + "/" + str(collection) + ".txt" response = requests.get(url=url) if response.status_code != 200: raise Exception( "Unable to fetch {0} blacklist, server returned status: {1}", collection, response.status_code, ) pattern_type = "stix" labels = ["COVID-19", "malicious-activity"] # parse content for data in response.iter_lines(decode_unicode=True): observable_type = None observable_resolver = None if data and not data.startswith("#"): if collection == "domain": observable_resolver = "Domain-Name" observable_type = "Domain-Name" elif collection == "ip": observable_resolver = "IPv4-Addr" observable_type = "IPv4-Addr" elif collection == "url": observable_resolver = "Url" observable_type = "Url" data = urllib.parse.quote(data, "/:") elif collection == "hash": observable_resolver = self.get_hash_type() observable_type = "File" indicator = None if observable_resolver is None or observable_type is None: return if self.cyber_threat_coalition_create_indicators: indicator = stix2.Indicator( id=OpenCTIStix2Utils.generate_random_stix_id("indicator"), name=data, pattern_type=pattern_type, pattern=self._INDICATOR_PATTERN[observable_resolver].format( data ), labels=labels, created_by_ref=organization, object_marking_refs=[stix2.TLP_WHITE], custom_properties={ "x_opencti_main_observable_type": observable_type, }, ) bundle_objects.append(indicator) report_object_refs.append(indicator["id"]) if self.cyber_threat_coalition_create_observables: observable = SimpleObservable( id=OpenCTIStix2Utils.generate_random_stix_id( "x-opencti-simple-observable" ), key=observable_type + "." + ".".join(self._OBSERVABLE_PATH[observable_resolver]), value=data, labels=labels, created_by_ref=organization, object_marking_refs=[stix2.TLP_WHITE], ) bundle_objects.append(observable) report_object_refs.append(observable["id"]) if indicator is not None: relationship = stix2.Relationship( id=OpenCTIStix2Utils.generate_random_stix_id( "relationship" ), relationship_type="based-on", created_by_ref=organization, source_ref=indicator.id, target_ref=observable.id, ) bundle_objects.append(relationship) report_object_refs.append(relationship["id"]) # create a global threat report report_uuid = "report--552b3ae6-8522-409d-8b72-a739bc1926aa" report_external_reference = stix2.ExternalReference( source_name="Cyber Threat Coalition", url="https://www.cyberthreatcoalition.org", external_id="COVID19-CTC", ) if report_object_refs: stix_report = stix2.Report( id=report_uuid, name="COVID-19 Cyber Threat Coalition (CTC) BlackList", type="report", description="This report represents the whole COVID-19 CTC blacklist.", published=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"), created_by_ref=organization, object_marking_refs=[stix2.TLP_WHITE], labels=labels, external_references=[report_external_reference], object_refs=report_object_refs, ) # add report in bundle bundle_objects.append(stix_report) # create stix bundle bundle = stix2.Bundle(objects=bundle_objects) # send data self.helper.send_stix2_bundle( bundle=bundle.serialize(), update=self.update_existing_data, work_id=work_id ) return work_id
def csvtostix(file_type, file_name): count = 0 data = {} labels = "" maldesc = '' malname = '' tot_file_path = '' url = [] domain = [] filename = [] ip = [] md5 = [] registry = [] email = [] indlist = [] rellist = [] sha1 = [] sha256 = [] m = datetime.datetime.now() c = m.strftime("%Y-%m-%d %H:%M:%S.{}".format(str(m).split('.')[1][:3]) + "Z") m = m.strftime("%Y-%m-%d %H:%M:%S.{}".format(str(m).split('.')[1][:3]) + "Z") malware = stix2.Malware(created=c, modified=m, name=malname, labels=labels, description=maldesc) try: each_data = [] if file_type == "-f": each_data = [] with open(file_name, "r") as f: csv_reader = csv.reader(f, delimiter=',') fields = csv_reader.next() tab = -1 for i in fields: #print(i) samp = [] tab += 1 with open(file_name, "r") as f: csv_reader = csv.reader(f, delimiter=',') for lines in csv_reader: if lines[tab].strip(): if lines[tab] not in fields: samp.append(lines[tab].strip()) data[i] = samp #print(data) elif file_type == "-F": each_data = [] indiv_data = [] if os.path.exists(file_name): for eachfile in os.walk(file_name): for each_file in eachfile[2]: with open(file_name + '/' + each_file, "r") as f: csv_reader = csv.reader(f, delimiter=',') fields = csv_reader.next() tab = -1 for i in fields: samp1 = [] tab += 1 with open(file_name, "r") as f: csv_reader = csv.reader(f, delimiter=',') for lines in csv_reader: if lines[tab].strip(): if lines[tab] not in fields: samp1.append( lines[tab].strip()) data[i].extend(samp1) else: print( "please enter a valid folder containing json files with valid folder path" ) print( "Usage : python csvtostix.py <-f>/<-F> file_name/folder_name" ) print(" Example : python csvtostix.py -f APT34.csv") print( " Example : python csvtostix.py -F /home/user/Desktop/IOC_files/" ) print( "Submit the folder, which does not contain any subfolders") sys.exit() else: print( "Please enter the command as -f (for file) or -F (for folder) followed by File name or Folder name with sapce" ) print( "Usage : python csvtostix.py <-f>/<-F> file_name/folder_name") print(" Example : python csvtostix.py -f APT34.csv") print( " Example : python csvtostix.py -F /home/user/Desktop/IOC_files/" ) sys.exit() #print(data) if data: domain = data.get("Domain", "") filepath1 = data.get("FilePath", "") sha1 = data.get("SHA1", "") registry = data.get("RegistryPath", "") filename = data.get("FileName", "") url = data.get("URL", "") ip = data.get("IPAddress", "") filename1 = data.get("FileName", "") #filename = filename1 + filepath1 filename = filename1 sha256 = data.get("SHA256", "") md5 = data.get("MD5", "") for each_ip in ip: indicator = stix2.Indicator(created=c, modified=m, name='IP', description=" ", labels=["malicious-activity"], pattern="[ipv4-addr:value = '" + each_ip.strip() + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_url in url: indicator = stix2.Indicator( created=c, modified=m, name='url', description=" ", labels=["malicious-activity"], pattern="[url:value = 'http://" + each_url.split('//')[-1].split('/')[0].strip("'") + "'" + "]", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_domain in domain: indicator = stix2.Indicator( created=c, modified=m, name='domain-name', description=" ", labels=["malicious-activity"], pattern="[domain-name:value = '" + each_domain.split('//')[-1].split('/')[0].strip("'") + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_filename in filename: tot_file_path = '' exact_name = each_filename.split('\\') split_path_name = each_filename.split('\\')[0:-1] if split_path_name: for path in split_path_name: tot_file_path = tot_file_path + '\\\\' + path if len(exact_name) > 1: indicator = stix2.Indicator( created=c, modified=m, name='file', description=" ", labels=["malicious-activity"], #pattern="[file:name = '" + each_filename.split('\\')[-1].strip("'") + "']", pattern="[file:name = '" + each_filename.split('\\')[-1].strip("'") + "' AND file:parent_directory_ref.path = '" + tot_file_path + "']", valid_from=c) else: indicator = stix2.Indicator(created=c, modified=m, name='file', description=" ", labels=["malicious-activity"], pattern="[file:name = '" + each_filename.strip("'") + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_registry in registry: each_registry = each_registry.replace("\\", "\\\\") indicator = stix2.Indicator( created=c, modified=m, name='win-registry-key', description=" ", labels=["malicious-activity"], pattern="[windows-registry-key:key = '" + each_registry + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_md5 in md5: each_md5 = re.sub(r'[^A-Za-z0-9]+', '', each_md5) indicator = stix2.Indicator(created=c, modified=m, name='MD5', description=" ", labels=["malicious-activity"], pattern="[file:hashes.md5 = '" + each_md5.strip() + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_sha1 in sha1: each_sha1 = re.sub(r'[^A-Za-z0-9]+', '', each_sha1) indicator = stix2.Indicator( created=c, modified=m, name='MD5', description=" ", labels=["malicious-activity"], pattern="[file:hashes.'SHA-1' = '" + each_sha1.strip() + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) for each_sha256 in sha256: each_sha256 = re.sub(r'[^A-Za-z0-9]+', '', each_sha256) indicator = stix2.Indicator( created=c, modified=m, name='MD5', description=" ", labels=["malicious-activity"], pattern="[file:hashes.'SHA-256' = '" + each_sha256.strip() + "']", valid_from=c) if indicator not in indlist: indlist.append(indicator) print(len(indlist)) obj_range = int((len(indlist) / 50)) + 1 ind1 = 0 ind2 = 50 print(obj_range) for num in range(obj_range): new_list = [] if (ind2 - ind1) != 50: new_list = indlist[ind1:] else: new_list = indlist[ind1:ind2] for ind in new_list: print(ind) count += 1 val = 'relationship' + str(count) val = stix2.Relationship(ind, 'indicates', malware) rellist.append(val) IOC = stix2.Bundle(objects=[malware] + rellist + new_list) if IOC: print(type(num)) print(num) num = str(num) if sys.argv[1].split("/")[-1]: with open( sys.argv[1].split("/")[-1].split(".")[0] + '_' + str(int(num) + 1) + '.ioc', 'w') as fp: fp.write(json.dumps(json.loads(str(IOC)), indent=2)) fp.close() elif sys.argv[1].split("/")[-2]: with open( sys.argv[1].split("/")[-2].split(".")[0] + '_' + str(int(num) + 1) + '+.ioc', 'w') as fp: fp.write(json.dumps(json.loads(str(IOC)), indent=2)) fp.close() else: with open( sys.argv[1].split("/")[0].split(".")[0] + '_' + str(int(num) + 1) + '+.ioc', 'w') as fp: fp.write(json.dumps(json.loads(str(IOC)), indent=2)) fp.close() else: pass ind1 = ind1 + 50 ind2 = ind2 + 50 rellist = [] else: print( "please enter a valid file/folder containing json files containing indicator data" ) print( "Usage : python csvtostix.py <-f>/<-F> file_name/folder_name") print(" Example : python csvtostix.py -f APT34.csv") print( " Example : python csvtostix.py -F /home/user/Desktop/IOC_files/" ) except IOError as err: print( "please enter a valid folder containing csv files with valid folder path" ) print("Usage : python csvtostix.py <-f>/<-F> file_name/folder_name") print(" Example : python csvtostix.py -f APT34.csv") print( " Example : python csvtostix.py -F /home/user/Desktop/IOC_files/") print("Submit the folder, which does not contain any subfolders") except Exception as e: print(traceback.format_exc()) print(e) return
malware = stix2.Malware(id="malware--d1c612bc-146f-4b65-b7b0-9a54a14150a4", created="2015-04-23T11:12:34.760Z", modified="2015-04-23T11:12:34.760Z", name="Poison Ivy Variant d1c6", labels=["remote-access-trojan"], kill_chain_phases=[init_comp]) ref = stix2.ExternalReference( source_name="capec", description="phishing", url="https://capec.mitre.org/data/definitions/98.html", external_id="CAPEC-98") attack_pattern = stix2.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]) relationship1 = stix2.Relationship(threat_actor, 'uses', malware) relationship2 = stix2.Relationship(threat_actor, 'uses', attack_pattern) relationship3 = stix2.Relationship(threat_actor, 'attributed-to', identity) bundle = stix2.Bundle(objects=[ threat_actor, malware, attack_pattern, identity, relationship1, relationship2, relationship3 ])
def test_relationship_missing_some_required_fields(): with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: stix2.Relationship(relationship_type='indicates') assert str( excinfo.value ) == "Missing required field(s) for Relationship: (source_ref, target_ref)."
def generate_report(): istihbarat_no = 0 cyber_threads_infos = [] attack_patterns = [] sti_list = [] records = get_all_records(settings.traffic_table_name, settings.prediction_column_name) unique_records = unique_lists_from_multidimensional_array(records) identity = stiv.Identity( name= "Veri Madenciligi Temelli Siber Tehdit Istihbarati Tez Calismasi Onerilen Sistemin Uygulamasi - Suleyman Muhammed ARIKAN", identity_class="individual") sti_list.append(identity) predictions = [record[1] for record in unique_records] unique_predictions = set(predictions) for attack in unique_predictions: attact_pattern = stiv.AttackPattern(name=attack, created_by_ref=identity.id) attack_patterns.append(attact_pattern) sti_list.append(attact_pattern) cyber_threads_infos.append( "intelligence_id-prediction-source_host-source_port-destination_port-protocol" + "\n") for record in records: if str(record[1]) != settings.unknown_class_value: cyber_thread_info = str(record[1]) + "-" + str( record[5]) + "-" + str(int(float(record[3]))) + "-" + str( int(float(record[4]))) + "-" + settings.protocols_list[ int(record[8]) - 1] + "\n" cyber_threads_infos.append(cyber_thread_info) istihbarat_no = istihbarat_no + 1 indicator_name = str( istihbarat_no) + " numaralı istihbarat - " + str(record[5]) indicator_label = ["malicious-activity"] indicator_pattern = "[network-traffic:src_ref.type = 'ipv4-addr' AND " indicator_pattern = indicator_pattern + "network-traffic:src_ref.value = '" + str( record[5]) + "' AND " indicator_pattern = indicator_pattern + "network-traffic:src_port = " + str( int(float(record[3]))) + " AND " indicator_pattern = indicator_pattern + "network-traffic:dst_port = " + str( int(float(record[4]))) + " AND " indicator_pattern = indicator_pattern + "network-traffic:protocols[*] = '" + settings.protocols_list[ int(record[8]) - 1] + "']" indicator = stiv.Indicator(name=indicator_name, labels=indicator_label, pattern=indicator_pattern, created_by_ref=identity.id) sti_list.append(indicator) attack_pattern = get_attack_pattern(attack_patterns, str(record[1])) relationship = stiv.Relationship(relationship_type='indicates', source_ref=indicator.id, target_ref=attack_pattern.id) sti_list.append(relationship) stiv_bundle = stiv.Bundle(sti_list) file_name = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f") fo = open("raporlar/" + file_name + ".txt", "x") istihbarat_no = 0 for cti in cyber_threads_infos: if (istihbarat_no != 0): cti = str(istihbarat_no) + "-" + cti fo.write(cti) istihbarat_no = istihbarat_no + 1 fo.close() fo_stiv = open("raporlar/" + file_name + ".json", "x") fo_stiv.write(stiv_bundle.serialize()) fo_stiv.close() return file_name
import stix2 indicator = stix2.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.", labels=["malicious-activity"], pattern="[url:value = 'http://x4z9arb.cn/4712/']", valid_from="2014-06-29T13:49:37.079000Z") foothold = stix2.KillChainPhase( kill_chain_name="mandiant-attack-lifecycle-model", phase_name="establish-foothold") malware = stix2.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", labels=["backdoor", "remote-access-trojan"], description= "This malware attempts to download remote files after establishing a foothold as a backdoor.", kill_chain_phases=[foothold]) relationship = stix2.Relationship(indicator, 'indicates', malware) bundle = stix2.Bundle(objects=[indicator, malware, relationship])
def relationship(uuid4, clock): return stix2.Relationship(**RELATIONSHIP_KWARGS)
def test_relationship_missing_some_required_properties(): with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship(relationship_type='indicates') assert excinfo.value.cls == stix2.Relationship assert excinfo.value.properties == ["source_ref", "target_ref"]
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")
def test_relationship_required_field_target_ref(): with pytest.raises(ValueError) as excinfo: relationship = stix2.Relationship(relationship_type='indicates', source_ref=INDICATOR_ID) assert str(excinfo.value ) == "Missing required field(s) for Relationship: (target_ref)."
def run(self): self.helper.log_info("Fetching data CYBERCRIME-TRACKER.NET...") tlp = self.helper.api.marking_definition.read( filters=[ {"key": "definition", "values": "TLP:{}".format(self.connector_tlp)} ] ) while True: try: # Get the current timestamp and check timestamp = int(time.time()) current_state = self.helper.get_state() if current_state is not None and "last_run" in current_state: last_run = current_state["last_run"] self.helper.log_info( "Connector last run: {}".format( datetime.datetime.utcfromtimestamp(last_run).strftime( "%Y-%m-%d %H:%M:%S" ) ) ) else: last_run = None self.helper.log_info("Connector has never run") # Run if it is the first time or we are past the interval if last_run is None or ((timestamp - last_run) > self.interval): self.helper.log_info("Connector will run!") now = datetime.datetime.utcfromtimestamp(timestamp) friendly_name = "MITRE run @ " + now.strftime("%Y-%m-%d %H:%M:%S") work_id = self.helper.api.work.initiate_work( self.helper.connect_id, friendly_name ) # Get Feed Content feed = feedparser.parse(self.feed_url) self.helper.log_info( "Found: {} entries.".format(len(feed["entries"])) ) self.feed_summary = { "Source": feed["feed"]["title"], "Date": self._time_to_datetime( feed["feed"]["published_parsed"] ), "Details": feed["feed"]["subtitle"], "Link": feed["feed"]["link"], } # Create the bundle bundle_objects = list() organization = stix2.Identity( id=OpenCTIStix2Utils.generate_random_stix_id("identity"), name="CYBERCRIME-TRACKER.NET", identity_class="organization", description="Tracker collecting and sharing daily updates of C2 IPs/Urls. http://cybercrime-tracker.net", ) bundle_objects.append(organization) for entry in feed["entries"]: parsed_entry = self.parse_feed_entry(entry) external_reference = stix2.ExternalReference( source_name="{}".format(self.feed_summary["Source"]), url=parsed_entry["ext_link"], ) indicator_pattern = self.gen_indicator_pattern(parsed_entry) malware = stix2.Malware( id=OpenCTIStix2Utils.generate_random_stix_id("malware"), is_family=True, name=parsed_entry["type"], description="{} malware.".format(parsed_entry["type"]), ) bundle_objects.append(malware) indicator = None if self.create_indicators: indicator = stix2.Indicator( id=OpenCTIStix2Utils.generate_random_stix_id( "indicator" ), name=parsed_entry["url"], description="C2 URL for: {}".format( parsed_entry["type"] ), labels=["C2 Server"], pattern_type="stix", pattern=indicator_pattern, valid_from=parsed_entry["date"], created=parsed_entry["date"], modified=parsed_entry["date"], created_by_ref=organization.id, object_marking_refs=[tlp["standard_id"]], external_references=[external_reference], custom_properties={ "x_opencti_main_observable_type": "Url" }, ) bundle_objects.append(indicator) relation = stix2.Relationship( id=OpenCTIStix2Utils.generate_random_stix_id( "relationship" ), source_ref=indicator.id, target_ref=malware.id, relationship_type="indicates", start_time=self._time_to_datetime( entry["published_parsed"] ), stop_time=self._time_to_datetime( entry["published_parsed"] ) + datetime.timedelta(0, 3), description="URLs associated to: " + parsed_entry["type"], confidence=self.confidence_level, created_by_ref=organization.id, object_marking_refs=[tlp["standard_id"]], created=parsed_entry["date"], modified=parsed_entry["date"], external_references=[external_reference], ) bundle_objects.append(relation) if self.create_observables: observable_url = SimpleObservable( id=OpenCTIStix2Utils.generate_random_stix_id( "x-opencti-simple-observable" ), key="Url.value", labels=["C2 Server"], value=parsed_entry["url"], created_by_ref=organization.id, object_marking_refs=[tlp["standard_id"]], external_references=[external_reference], ) bundle_objects.append(observable_url) observable_ip = SimpleObservable( id=OpenCTIStix2Utils.generate_random_stix_id( "x-opencti-simple-observable" ), key="IPv4-Addr.value", labels=["C2 Server"], value=parsed_entry["ip"], created_by_ref=organization.id, object_marking_refs=[tlp["standard_id"]], external_references=[external_reference], ) bundle_objects.append(observable_ip) observable_domain = None if "domain" in parsed_entry.keys(): observable_domain = SimpleObservable( id=OpenCTIStix2Utils.generate_random_stix_id( "x-opencti-simple-observable" ), key="Domain-Name.value", labels=["C2 Server"], value=parsed_entry["domain"], created_by_ref=organization.id, object_marking_refs=[tlp["standard_id"]], external_references=[external_reference], ) bundle_objects.append(observable_domain) if indicator is not None: relationship_1 = stix2.Relationship( id=OpenCTIStix2Utils.generate_random_stix_id( "relationship" ), relationship_type="based-on", created_by_ref=organization.id, source_ref=indicator.id, target_ref=observable_url.id, ) bundle_objects.append(relationship_1) relationship_2 = stix2.Relationship( id=OpenCTIStix2Utils.generate_random_stix_id( "relationship" ), relationship_type="based-on", created_by_ref=organization.id, source_ref=indicator.id, target_ref=observable_ip.id, ) bundle_objects.append(relationship_2) if observable_domain is not None: relationship_3 = stix2.Relationship( id=OpenCTIStix2Utils.generate_random_stix_id( "relationship" ), relationship_type="based-on", created_by_ref=organization.id, source_ref=indicator.id, target_ref=observable_domain.id, ) bundle_objects.append(relationship_3) # create stix bundle bundle = stix2.Bundle(objects=bundle_objects) # send data self.helper.send_stix2_bundle( bundle=bundle.serialize(), update=self.update_existing_data, work_id=work_id, ) # Store the current timestamp as a last run message = ( "Connector successfully run, storing last_run as: {}".format( str(timestamp) ) ) self.helper.log_info(message) self.helper.set_state({"last_run": timestamp}) self.helper.api.work.to_processed(work_id, message) self.helper.log_info( "Last_run stored, next run in: {} seconds.".format( str(round(self.interval, 2)) ) ) time.sleep(60) else: new_interval = self.interval - (timestamp - last_run) self.helper.log_info( "Connector will not run. \ Next run in: {} seconds.".format( str(round(new_interval, 2)) ) ) time.sleep(60) except (KeyboardInterrupt, SystemExit): self.helper.log_info("Connector stop") exit(0) except Exception as e: self.helper.log_error(str(e)) time.sleep(60)
def test_relationship_required_field_relationship_type(): with pytest.raises(ValueError) as excinfo: relationship = stix2.Relationship() assert str( excinfo.value ) == "Missing required field(s) for Relationship: (relationship_type, source_ref, target_ref)."
def relationship_maker(source, type, target): relationship = stix2.Relationship(source, type, target) itemtofile(relationship) return relationship
import stix2 threat_actor = stix2.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.", labels=["crime-syndicate"], aliases=["Equipo del Discoteca"], roles=["agent"], goals=["Steal Credit Card Information"], sophistication="expert", resource_level="organization", primary_motivation="personal-gain") identity = stix2.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 = stix2.Relationship(threat_actor, 'attributed-to', identity) bundle = stix2.Bundle(objects=[threat_actor, identity, relationship])