def test_sender_TypedField(self): h = EmailHeader() a = "*****@*****.**" # Set using actual object h.sender = Address(a, Address.CAT_EMAIL) # In this case, the type is Address, not EmailAddress, but we don't # care since EmailAddress.istypeof(h.sender) is True self.assertNotEqual(EmailAddress, type(h.sender)) self.assertEqual(Address, type(h.sender)) self.assertTrue(EmailAddress.istypeof(h.sender)) # Set using "aliased" object h.sender = EmailAddress(a) # In this case it is actually an EmailAddress, not just an Address # (but isinstance returns True) self.assertEqual(EmailAddress, type(h.sender)) self.assertNotEqual(Address, type(h.sender)) self.assertTrue(isinstance(h.sender, Address)) self.assertTrue(EmailAddress.istypeof(h.sender)) h.sender = a self.assertTrue(EmailAddress.istypeof(h.sender)) bad_object = 42 self.assertRaises(ValueError, setattr, h, 'sender', bad_object) # Just because it's an Address isn't good enough. It needs to have # the right category. ipv4_object = Address(a, Address.CAT_IPV4) self.assertRaises(ValueError, setattr, h, 'sender', ipv4_object)
def test_list_of_dates_in_email_header(self): from cybox.objects.email_message_object import EmailHeader hdr = EmailHeader() hdr.date = [datetime.datetime.now(), datetime.datetime.now()] hdr.date.condition = "Equals" hdr_xml = hdr.to_xml() self.assertTrue(b'EmailMessageObj:Date condition="Equals"' in hdr_xml) self.assertTrue(b"##comma##" in hdr_xml)
def resolveEmailObservable(attribute): new_object = EmailMessage() email_header = EmailHeader() if (attribute["type"] == "email-src"): email_header.from_ = attribute["value"] elif (attribute["type"] == "email-dst"): email_header.to = attribute["value"] else: email_header.subject = attribute["value"] new_object.header = email_header return new_object
def resolveEmailObservable(attribute): new_object = EmailMessage() email_header = EmailHeader() if (attribute["type"] == "email-src"): email_header.from_ = attribute["value"] elif(attribute["type"] == "email-dst"): email_header.to = attribute["value"] else: email_header.subject = attribute["value"] new_object.header = email_header return new_object
def resolveEmailObservable(indicator, attribute): indicator.add_indicator_type("Malicious E-mail") new_object = EmailMessage() email_header = EmailHeader() if (attribute["type"] == "email-src"): email_header.from_ = attribute["value"] elif (attribute["type"] == "email-dst"): email_header.to = attribute["value"] else: email_header.subject = attribute["value"] new_object.header = email_header return new_object
def resolveEmailObservable(indicator, attribute): indicator.add_indicator_type("Malicious E-mail") new_object = EmailMessage() email_header = EmailHeader() if (attribute["type"] == "email-src"): email_header.from_ = attribute["value"] elif(attribute["type"] == "email-dst"): email_header.to = attribute["value"] else: email_header.subject = attribute["value"] new_object.header = email_header return new_object
def test_subject_TypedField(self): h = EmailHeader() # Set using actual object h.subject = String("Howdy") self.assertEqual(String, type(h.subject)) # Set using implied cast h.subject = "Howdy" self.assertEqual(String, type(h.subject)) s = "http://badsubject.com" bad_object = URI(s) self.assertRaises(ValueError, setattr, h, 'subject', bad_object)
def test_creation(self): header = EmailHeader() self.assertEqual(None, header.subject) header.subject = "Howdy" self.assertEqual(String, type(header.subject)) self.assertEqual(None, header.date) header.date = "2010-12-10T14:15:30+02:00" self.assertEqual(DateTime, type(header.date)) self.assertEqual(datetime.datetime, type(header.date.value)) self.assertEqual(None, header.message_id) header.message_id = "<*****@*****.**>" self.assertEqual(String, type(header.message_id))
def add_email_observable(self, headers): e = EmailMessage() h = EmailHeader.from_dict(headers) e.header = h self.__emails.add(e) email_observable = Observable(e) self.email_indicator.add_observable(email_observable)
def resolve_email_observable(indicator, attribute): attribute_type = attribute.type indicator.add_indicator_type("Malicious E-mail") new_object = EmailMessage() email_header = EmailHeader() if attribute_type == 'email-src': email_header.from_ = attribute.value email_header.from_.condition = "Equals" if attribute_type == 'email-dst': email_header.to = attribute.value email_header.to.condition = "Equals" else: email_header.subject = attribute.value email_header.subject.condition = "Equals" new_object.header = email_header return new_object
def to_cybox(self, exclude=None): """ Convert an email to a CybOX Observables. Pass parameter exclude to specify fields that should not be included in the returned object. Returns a tuple of (CybOX object, releasability list). To get the cybox object as xml or json, call to_xml() or to_json(), respectively, on the resulting CybOX object. """ if exclude == None: exclude = [] observables = [] obj = EmailMessage() # Assume there is going to be at least one header obj.header = EmailHeader() if 'message_id' not in exclude: obj.header.message_id = String(self.message_id) if 'subject' not in exclude: obj.header.subject = String(self.subject) if 'sender' not in exclude: obj.header.sender = Address(self.reply_to, Address.CAT_EMAIL) if 'reply_to' not in exclude: obj.header.reply_to = Address(self.reply_to, Address.CAT_EMAIL) if 'x_originating_ip' not in exclude: obj.header.x_originating_ip = Address(self.x_originating_ip, Address.CAT_IPV4) if 'raw_body' not in exclude: obj.raw_body = self.raw_body if 'raw_header' not in exclude: obj.raw_header = self.raw_header #copy fields where the names differ between objects if 'helo' not in exclude and 'email_server' not in exclude: obj.email_server = String(self.helo) if ('from_' not in exclude and 'from' not in exclude and 'from_address' not in exclude): obj.header.from_ = EmailAddress(self.from_address) if 'date' not in exclude and 'isodate' not in exclude: obj.header.date = DateTime(self.isodate) observables.append(Observable(obj)) return (observables, self.releasability)
def test_roundtrip(self): d = { 'received_lines': [{'from': "a", 'by': "b"}], 'to': [{'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}], 'cc': [{'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}], 'bcc': [{'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}], 'from': {'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}, 'subject': "This is not a malicious email", 'in_reply_to': "<*****@*****.**>", 'date': self.datetime_str, 'message_id': "<*****@*****.**>", 'sender': {'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}, 'reply_to': {'address_value': "*****@*****.**", 'category': Address.CAT_EMAIL, 'xsi:type': Address._XSI_TYPE}, 'errors_to': "/dev/null", 'boundary': "----MIME_BOUNDARY------", 'content_type': "mime/multi-part", 'mime_version': "1.0", 'precedence': "High", 'user_agent': "Outlook_Express1.0", 'x_mailer': "Outlook Express", 'x_originating_ip': {'address_value': "1.2.3.4", 'category': Address.CAT_IPV4, 'xsi:type': Address._XSI_TYPE}, 'x_priority': 3, } self.maxDiff = None header = EmailHeader.from_dict(d) self.assertEqual(DateTime, type(header.date)) d2 = cybox.test.round_trip_dict(EmailHeader, d) self.assertEqual(d, d2)
def main(iocs=iocs): stix_header = STIXHeader(title=iocs['title'], description=iocs['desc'], package_intents=["Indicators - Watchlist"]) stix_package = STIXPackage(stix_header=stix_header) # add indicator - file hash if iocs.get('hash'): indicator_file_hash = Indicator(title="Malicious File") indicator_file_hash.add_indicator_type("File Hash Watchlist") for file_hash in iocs['hash']: file_object = File() file_object.add_hash(Hash(file_hash)) file_object.hashes[0].simple_hash_value.condition = "Equals" file_object.hashes[0].type_.condition = "Equals" indicator_file_hash.add_observable(file_object) stix_package.add_indicator(indicator_file_hash) # add indicator - file name if iocs.get('fname'): indicator_filename = Indicator(title="Malicious File Name") for file in iocs['fname']: file_object = File() file_object.file_name = file indicator_filename.add_observable(file_object) stix_package.add_indicator(indicator_filename) # add indicator - ip address if iocs.get('ips'): indicator_ip = Indicator(title="Malicious IP Address") indicator_ip.add_indicator_type("IP Watchlist") for ip in iocs['ips']: addr = Address(address_value=ip, category=Address.CAT_IPV4) addr.condition = "Equals" indicator_ip.add_observable(addr) stix_package.add_indicator(indicator_ip) # add indicator - domains if iocs.get('domains'): indicator_domains = Indicator(title="Malicious Domains") indicator_domains.add_indicator_type("Domain Watchlist") for domain in iocs['domains']: domain_name = DomainName() domain_name.value = domain indicator_domains.add_observable(domain_name) stix_package.add_indicator(indicator_domains) # add indicator - url if iocs.get('urls'): indicator_url = Indicator(title='Malicious URL') indicator_url.add_indicator_type("URL Watchlist") for _url in iocs['urls']: url = URI() url.value = _url url.type_ = URI.TYPE_URL url.value.condition = "Equals" # url.value.condition = "Contains" indicator_url.add_observable(url) stix_package.add_indicator(indicator_url) # add indicator - email subject if iocs.get('subject'): indicator_email_subject = Indicator(title='Malicious E-mail Subject') indicator_email_subject.add_indicator_type("Malicious E-mail") for subject in iocs['subject']: email_subject_object = EmailMessage() email_subject_object.header = EmailHeader() email_subject_object.header.subject = subject email_subject_object.header.subject.condition = "StartsWith" indicator_email_subject.add_observable(email_subject_object) stix_package.add_indicator(indicator_email_subject) # add indicator - email sender if iocs.get('senders'): indicator_email_sender = Indicator(title='Malicious E-mail Sender') indicator_email_sender.add_indicator_type("Malicious E-mail") for sender in iocs['senders']: email_sender_object = EmailMessage() email_sender_object.header = EmailHeader() email_sender_object.header.sender = sender email_sender_object.header.sender.condition = "Equals" indicator_email_sender.add_observable(email_sender_object) stix_package.add_indicator(indicator_email_sender) # print(stix_package.to_xml(encoding=None)) # print(type(stix_package.to_xml(encoding=None))) return stix_package.to_xml(encoding=None)
def __create_cybox_headers(self, msg): """ Returns a CybOX EmailHeaderType object """ if self.__verbose_output: sys.stderr.write("** parsing headers\n") headers = EmailHeader() if 'received' in self.headers: headers.received_lines = self._parse_received_headers(msg) if 'to' in self.headers: headers.to = _get_email_recipients(msg['to']) if 'cc' in self.headers: headers.cc = _get_email_recipients(msg['cc']) if 'bcc' in self.headers: headers.bcc = _get_email_recipients(msg['bcc']) if 'from' in self.headers: headers.from_ = _get_single_email_address(msg['from']) if 'sender' in self.headers: headers.sender = _get_single_email_address(msg['sender']) if 'reply-to' in self.headers: headers.reply_to = _get_single_email_address(msg['reply-to']) if 'subject' in self.headers: headers.subject = String(msg['subject']) if 'in-reply-to' in self.headers: headers.in_reply_to = String(msg['in-reply-to']) if 'errors-to' in self.headers: headers.errors_to = String(msg['errors-to']) if 'date' in self.headers: headers.date = DateTime(msg['date']) if 'message-id' in self.headers: headers.message_id = String(msg['message-id']) if 'boundary' in self.headers: headers.boundary = String(msg['boundary']) if 'content-type' in self.headers: headers.content_type = String(msg['content-type']) if 'mime-version' in self.headers: headers.mime_version = String(msg['mime-version']) if 'precedence' in self.headers: headers.precedence = String(msg['precedence']) if 'user-agent' in self.headers: headers.user_agent = String(msg['user-agent']) if 'x-mailer' in self.headers: headers.x_mailer = String(msg['x-mailer']) if 'x-originating-ip' in self.headers: headers.x_originating_ip = Address(msg['x-originating-ip'], Address.CAT_IPV4) if 'x-priority' in self.headers: headers.x_priority = String(msg['x-priority']) return headers
def __create_cybox_headers(self, msg): """ Returns a CybOX EmailHeaderType object """ if self.__verbose_output: sys.stderr.write("** parsing headers\n") headers = EmailHeader() if 'received' in self.headers: lines = self._parse_received_headers(msg) if lines: headers.received_lines = lines if 'to' in self.headers: headers.to = _get_email_recipients(msg['to']) if msg['delivered-to'] and not headers.to: headers.to = _get_email_recipients(msg['delivered-to']) if 'cc' in self.headers: headers.cc = _get_email_recipients(msg['cc']) if 'bcc' in self.headers: headers.bcc = _get_email_recipients(msg['bcc']) if 'from' in self.headers: headers.from_ = _get_single_email_address(msg['from']) if 'sender' in self.headers: headers.sender = _get_single_email_address(msg['sender']) if 'reply-to' in self.headers: headers.reply_to = _get_single_email_address(msg['reply-to']) if 'subject' in self.headers and 'subject' in msg: headers.subject = String(msg['subject']) if 'in-reply-to' in self.headers and 'in-reply-to' in msg: headers.in_reply_to = String(msg['in-reply-to']) if 'errors-to' in self.headers and 'errors-to' in msg: headers.errors_to = String(msg['errors-to']) if 'date' in self.headers and 'date' in msg: headers.date = DateTime(msg['date']) if 'message-id' in self.headers and 'message-id' in msg: headers.message_id = String(msg['message-id']) if 'boundary' in self.headers and 'boundary' in msg: headers.boundary = String(msg['boundary']) if 'content-type' in self.headers and 'content-type' in msg: headers.content_type = String(msg['content-type']) if 'mime-version' in self.headers and 'mime-version' in msg: headers.mime_version = String(msg['mime-version']) if 'precedence' in self.headers and 'precedence' in msg: headers.precedence = String(msg['precedence']) if 'user-agent' in self.headers and 'user-agent' in msg: headers.user_agent = String(msg['user-agent']) if 'x-mailer' in self.headers and 'x-mailer' in msg: headers.x_mailer = String(msg['x-mailer']) if 'x-originating-ip' in self.headers and msg['x-originating-ip']: headers.x_originating_ip = Address(msg['x-originating-ip'], Address.CAT_IPV4) if 'x-priority' in self.headers and 'x-priority' in msg: #Must be a digit - pull one out of anything that could be a string such as 3 (Normal) import re priority = '' for p in re.findall(r'\d+',msg['x-priority']): if p.isdigit(): priority = p if priority: headers.x_priority = String(priority) return headers
def convert_email_message_c_o(em20, em1x, obs20_id): em1x.header = EmailHeader() convert_obj(em20, em1x, EMAIL_MESSAGE_MAP, obs20_id) if "from_ref" in em20: if em20["from_ref"] in _STIX1X_OBJS: em1x.header.from_ = _STIX1X_OBJS[em20["from_ref"]] else: warn("%s is not an index found in %s, property 'from_ref'", 306, em20["from_ref"], obs20_id) if "sender_ref" in em20: if em20["sender_ref"] in _STIX1X_OBJS: em1x.header.sender = _STIX1X_OBJS[em20["sender_ref"]] else: warn("%s is not an index found in %s, property 'sender_refs'", 306, em20["sender_ref"], obs20_id) if "to_refs" in em20: to_address_objects = [] for to_ref in em20["to_refs"]: if to_ref in _STIX1X_OBJS: to_address_objects.append(_STIX1X_OBJS[to_ref]) em1x.header.to = to_address_objects else: warn("%s is not an index found in %s, property 'to_refs'", 306, to_ref, obs20_id) if "cc_refs" in em20: cc_address_objects = [] for cc_ref in em20["cc_refs"]: if cc_ref in _STIX1X_OBJS: cc_address_objects.append(_STIX1X_OBJS[cc_ref]) em1x.header.cc = cc_address_objects else: warn("%s is not an index found in %s, property 'cc_refs'", 306, cc_ref, obs20_id) if "bcc_refs" in em20: bcc_address_objects = [] for bcc_ref in em20["bcc_refs"]: if bcc_ref in _STIX1X_OBJS: bcc_address_objects.append(_STIX1X_OBJS[bcc_ref]) em1x.header.bcc = bcc_address_objects else: warn("%s is not an index found in %s, property 'bcc_refs'", 306, bcc_ref, obs20_id) if "content_type" in em20: em1x.header.content_type = em20["content_type"] if "received_lines" in em20: em1x.header.received_lines = ReceivedLineList() for rl20 in em20["received_lines"]: rl1x = ReceivedLine() em1x.header.received_lines.append(rl1x) populate_received_line(rl20, rl1x, obs20_id) if "additional_header_fields" in em20: populate_other_header_fields(em20["additional_header_fields"], em1x.header, obs20_id) if "raw_email_refs" in em20: warn( "STIX 1.x can only store the body and headers of an email message in %s independently", 523, obs20_id) if "body" in em20: if em20["is_multipart"]: warn( "The is_multipart property in %s should be 'false' if the body property is present", 313, obs20_id) em1x.raw_body = em20["body"] else: if em20["is_multipart"]: warn( "The is_multipart property in %s should be 'true' if the body property is not present", 313, obs20_id) if "body_multipart" in em20: if not em20["is_multipart"]: warn( "The is_multipart property in %s should be 'true' if the body_multipart property is present", 313, obs20_id) attachments = [] for part in em20["body_multipart"]: # content_disposition is optional, so we can't depend upon it # if "content_disposition" in part and part["content_disposition"].find("attachment"): if "body_raw_ref" in part: if part["body_raw_ref"] in _STIX1X_OBJS: obj = _STIX1X_OBJS[part["body_raw_ref"]] # TODO: can we handle other object/content types? if isinstance(obj, File) or isinstance(obj, Artifact): attachments.append(obj) else: warn("%s is not an index found in %s", 306, part["body_raw_ref"], obs20_id) if "body" in part: em1x.raw_body = part["body"] if attachments: em1x.attachments = Attachments() for a in attachments: em1x.add_related(a, "Contains", inline=True) em1x.attachments.append(a.parent.id_) else: if em20["is_multipart"]: warn( "The is_multipart property in %s should be 'false' if the body_multipart property is not present", 313, obs20_id)
def main(): stix_package = STIXPackage() ttp = TTP(title="Phishing") stix_package.add_ttp(ttp) # Create the indicator for just the subject email_subject_object = EmailMessage() email_subject_object.header = EmailHeader() email_subject_object.header.subject = "[IMPORTANT] Please Review Before" email_subject_object.header.subject.condition = "StartsWith" email_subject_indicator = Indicator() email_subject_indicator.title = "Malicious E-mail Subject Line" email_subject_indicator.add_indicator_type("Malicious E-mail") email_subject_indicator.observable = email_subject_object email_subject_indicator.confidence = "Low" # Create the indicator for just the attachment file_attachment_object = EmailMessage() file_attachment_object.attachments = Attachments() attached_file_object = File() attached_file_object.file_name = "Final Report" attached_file_object.file_name.condition = "StartsWith" attached_file_object.file_extension = "doc.exe" attached_file_object.file_extension.condition = "Equals" file_attachment_object.add_related(attached_file_object, "Contains", inline=True) file_attachment_object.attachments.append(attached_file_object.parent.id_) indicator_attachment = Indicator() indicator_attachment.title = "Malicious E-mail Attachment" indicator_attachment.add_indicator_type("Malicious E-mail") indicator_attachment.observable = file_attachment_object indicator_attachment.confidence = "Low" # Create the combined indicator w/ both subject an attachment full_email_object = EmailMessage() full_email_object.attachments = Attachments() # Add the previously referenced file as another reference rather than define it again: full_email_object.attachments.append(attached_file_object.parent.id_) full_email_object.header = EmailHeader() full_email_object.header.subject = "[IMPORTANT] Please Review Before" full_email_object.header.subject.condition = "StartsWith" combined_indicator = Indicator(title="Malicious E-mail") combined_indicator.add_indicator_type("Malicious E-mail") combined_indicator.confidence = Confidence(value="High") combined_indicator.observable = full_email_object email_subject_indicator.add_indicated_ttp(TTP(idref=ttp.id_)) indicator_attachment.add_indicated_ttp(TTP(idref=ttp.id_)) combined_indicator.add_indicated_ttp(TTP(idref=ttp.id_)) stix_package.add_indicator(combined_indicator) stix_package.add_indicator(email_subject_indicator) stix_package.add_indicator(indicator_attachment) print(stix_package.to_xml(encoding=None))
def test_datetime(self): header = EmailHeader.from_dict(self._full_dict) self.assertEqual(DateTime, type(header.date))
def home(request): """ Name: home Desc: Main GUI view """ # Forms:Job,target and relay creation create_job_form = CreateJob(request=request, prefix="create_job") create_target_form = CreateTarget(request=request, prefix="create_target") create_relay_form = CreateRelay(request=request, prefix="create_relay") if request.method == "POST": # Remove a relay if "delete_relay_id" in request.POST: try: Relay.objects.get(pk=request.POST["delete_relay_id"]).delete() except ObjectDoesNotExist, e: pass # Create new relay if "create_relay-name" in request.POST: # Actuator creation create_relay_form = CreateRelay(request.POST, request=request, prefix="create_relay") if create_relay_form.is_valid(): host = create_relay_form.save() host.save() # TODO - Call a sync here # Job Creations if "create_job-raw_message" in request.POST: new_job = Job(capability=Capability.objects.get( pk=request.POST["create_job-capability"]), target=Target.objects.get( pk=request.POST["create_job-target"]), raw_message="Pending", status=JobStatus.objects.get(status="Pending"), created_by=request.user) new_job.save() # Now we have a pk - update the id command = json.loads(request.POST["create_job-raw_message"]) command["modifiers"]["command-ref"] = new_job.id logger.info("Job Created\n%s" % json.dumps(command)) new_job.raw_message = json.dumps(command, sort_keys=True, indent=4).replace( "\t", u'\xa0\xa0\xa0\xa0\xa0') new_job.save() # Target Creations namespace_url = getattr(settings, "NAMESPACE_URL", None) namespace_id = getattr(settings, "NAMESPACE_ID", None) set_id_namespace(Namespace(namespace_url, namespace_id)) if "create_target-cybox_type" in request.POST: cybox_type = CybOXType.objects.get( pk=request.POST["create_target-cybox_type"]) if cybox_type.identifier == "cybox:NetworkConnectionObjectType": obs = NetworkConnection() # Source sock = SocketAddress() sock.ip_address = request.POST["create_target-source_address"] sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" sport = Port() sport.port_value = int( request.POST["create_target-source_port"]) sock.port = sport obs.source_socket_address = sock # Dest sock = SocketAddress() sock.ip_address = request.POST[ "create_target-destination_address"] sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" dport = Port() dport.port_value = int( request.POST["create_target-destination_port"]) sock.port = dport obs.destination_socket_address = sock name = "Network Connection %s:%s -> %s:%s (%s)" % ( request.POST["create_target-source_address"], request.POST["create_target-source_port"], request.POST["create_target-destination_address"], request.POST["create_target-destination_port"], request.POST["create_target-protocol"]) raw_message = Observable(item=obs, title=name).to_json() elif cybox_type.identifier == "cybox:AddressObjectType": name = "Address %s " % (request.POST["create_target-address"]) raw_message = Observable(item=Address( address_value=request.POST["create_target-address"], category=Address.CAT_IPV4), title=name).to_json() elif cybox_type.identifier == "cybox:URIObjectType": name = "URI %s " % (request.POST["create_target-uri"]) obs = URI() obs.value = request.POST["create_target-uri"] obs.type_ = URI.TYPE_URL obs.condition = "Equals" raw_message = Observable(item=obs, title=name).to_json() elif cybox_type.identifier == "cybox:EmailMessageObjectType": name = "Email %s " % ( request.POST["create_target-email_subject"]) obs = EmailMessage() obs.raw_body = request.POST["create_target-email_message"] obs.header = EmailHeader() obs.header.subject = request.POST[ "create_target-email_subject"] obs.header.subject.condition = "StartsWith" obs.header.to = request.POST["create_target-email_to"] obs.header.from_ = request.POST["create_target-email_from"] raw_message = Observable(item=obs, title=name).to_json() else: # Should never reach here raw_message = {} name = "Undefined Object" create_target_form = CreateTarget(request.POST, request=request, prefix="create_target") if create_target_form.is_valid(): target = create_target_form.save(commit=False) target.name = name target.raw_message = raw_message target.save()
def gen_stix_observable_sample(config, target=None, datatype=None, title='random test data', description='random test data', package_intents='Indicators - Watchlist', tlp_color='WHITE'): '''generate sample stix data comprised of indicator_count indicators of type datatype''' # setup the xmlns... xmlns_url = config['edge']['sites'][target]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][target]['stix']['xmlns_name'] set_stix_id_namespace({xmlns_url: xmlns_name}) set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) # construct a stix package... stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = title stix_header.description = description stix_header.package_intents = package_intents marking = MarkingSpecification() marking.controlled_structure = '../../../../descendant-or-self::node()' tlp_marking = TLPMarkingStructure() tlp_marking.color = tlp_color marking.marking_structures.append(tlp_marking) stix_package.stix_header = stix_header stix_package.stix_header.handling = Marking() stix_package.stix_header.handling.add_marking(marking) # ...and stuff it full of random sample data :-) if datatype == 'ip': addr = Address(address_value=datagen.generate_random_ip_address(), category='ipv4-addr') addr.condition = 'Equals' stix_package.add_observable(Observable(addr)) elif datatype == 'domain': domain = DomainName() domain.type_ = 'FQDN' domain.value = datagen.generate_random_domain(config) domain.condition = 'Equals' stix_package.add_observable(Observable(domain)) elif datatype == 'filehash': file_object = File() file_object.file_name = str(uuid.uuid4()) + '.exe' hashes = datagen.generate_random_hashes() for hash in hashes.keys(): file_object.add_hash(Hash(hashes[hash], type_=hash.upper())) for i in file_object.hashes: i.simple_hash_value.condition = "Equals" stix_package.add_observable(Observable(file_object)) elif datatype == 'email': try: msg = datagen.get_random_spam_msg(config) email = EmailMessage() email.header = EmailHeader() header_map = { 'Subject': 'subject', 'To': 'to', 'Cc': 'cc', 'Bcc': 'bcc', 'From': 'from_', 'Sender': 'sender', 'Date': 'date', 'Message-ID': 'message_id', 'Reply-To': 'reply_to', 'In-Reply-To': 'in_reply_to', 'Content-Type': 'content_type', 'Errors-To': 'errors_to', 'Precedence': 'precedence', 'Boundary': 'boundary', 'MIME-Version': 'mime_version', 'X-Mailer': 'x_mailer', 'User-Agent': 'user_agent', 'X-Originating-IP': 'x_originating_ip', 'X-Priority': 'x_priority' } # TODO handle received_lines for key in header_map.keys(): val = msg.get(key, None) if val: email.header.__setattr__(header_map[key], val) email.header.__getattribute__(header_map[key]).condition = \ 'Equals' # TODO handle email bodies (it's mostly all there except for # handling weird text encoding problems that were making # libcybox stacktrace) # body = get_email_payload(random_spam_msg) # if body: # email.raw_body = body stix_package.add_observable(Observable(email)) except: return (None) observable_id = stix_package.observables.observables[0].id_ return (observable_id, stix_package)
def to_cybox_observable(obj, exclude=None, bin_fmt="raw"): """ Convert a CRITs TLO to a CybOX Observable. :param obj: The TLO to convert. :type obj: :class:`crits.core.crits_mongoengine.CRITsBaseAttributes` :param exclude: Attributes to exclude. :type exclude: list :param bin_fmt: The format for the binary (if applicable). :type bin_fmt: str """ type_ = obj._meta['crits_type'] if type_ == 'Certificate': custom_prop = Property( ) # make a custom property so CRITs import can identify Certificate exports custom_prop.name = "crits_type" custom_prop.description = "Indicates the CRITs type of the object this CybOX object represents" custom_prop._value = "Certificate" obje = File() # represent cert information as file obje.md5 = obj.md5 obje.file_name = obj.filename obje.file_format = obj.filetype obje.size_in_bytes = obj.size obje.custom_properties = CustomProperties() obje.custom_properties.append(custom_prop) obs = Observable(obje) obs.description = obj.description data = obj.filedata.read() if data: # if cert data available a = Artifact(data, Artifact.TYPE_FILE) # create artifact w/data a.packaging.append(Base64Encoding()) obje.add_related(a, "Child_Of") # relate artifact to file return ([obs], obj.releasability) elif type_ == 'Domain': obje = DomainName() obje.value = obj.domain obje.type_ = obj.record_type return ([Observable(obje)], obj.releasability) elif type_ == 'Email': if exclude == None: exclude = [] observables = [] obje = EmailMessage() # Assume there is going to be at least one header obje.header = EmailHeader() if 'message_id' not in exclude: obje.header.message_id = String(obj.message_id) if 'subject' not in exclude: obje.header.subject = String(obj.subject) if 'sender' not in exclude: obje.header.sender = Address(obj.sender, Address.CAT_EMAIL) if 'reply_to' not in exclude: obje.header.reply_to = Address(obj.reply_to, Address.CAT_EMAIL) if 'x_originating_ip' not in exclude: obje.header.x_originating_ip = Address(obj.x_originating_ip, Address.CAT_IPV4) if 'x_mailer' not in exclude: obje.header.x_mailer = String(obj.x_mailer) if 'boundary' not in exclude: obje.header.boundary = String(obj.boundary) if 'raw_body' not in exclude: obje.raw_body = obj.raw_body if 'raw_header' not in exclude: obje.raw_header = obj.raw_header #copy fields where the names differ between objects if 'helo' not in exclude and 'email_server' not in exclude: obje.email_server = String(obj.helo) if ('from_' not in exclude and 'from' not in exclude and 'from_address' not in exclude): obje.header.from_ = EmailAddress(obj.from_address) if 'date' not in exclude and 'isodate' not in exclude: obje.header.date = DateTime(obj.isodate) obje.attachments = Attachments() observables.append(Observable(obje)) return (observables, obj.releasability) elif type_ == 'Indicator': observables = [] obje = make_cybox_object(obj.ind_type, obj.value) observables.append(Observable(obje)) return (observables, obj.releasability) elif type_ == 'IP': obje = Address() obje.address_value = obj.ip if obj.ip_type == IPTypes.IPv4_ADDRESS: obje.category = "ipv4-addr" elif obj.ip_type == IPTypes.IPv6_ADDRESS: obje.category = "ipv6-addr" elif obj.ip_type == IPTypes.IPv4_SUBNET: obje.category = "ipv4-net" elif obj.ip_type == IPTypes.IPv6_SUBNET: obje.category = "ipv6-subnet" return ([Observable(obje)], obj.releasability) elif type_ == 'PCAP': obje = File() obje.md5 = obj.md5 obje.file_name = obj.filename obje.file_format = obj.contentType obje.size_in_bytes = obj.length obs = Observable(obje) obs.description = obj.description art = Artifact(obj.filedata.read(), Artifact.TYPE_NETWORK) art.packaging.append(Base64Encoding()) obje.add_related(art, "Child_Of") # relate artifact to file return ([obs], obj.releasability) elif type_ == 'RawData': obje = Artifact(obj.data.encode('utf-8'), Artifact.TYPE_FILE) obje.packaging.append(Base64Encoding()) obs = Observable(obje) obs.description = obj.description return ([obs], obj.releasability) elif type_ == 'Sample': if exclude == None: exclude = [] observables = [] f = File() for attr in ['md5', 'sha1', 'sha256']: if attr not in exclude: val = getattr(obj, attr, None) if val: setattr(f, attr, val) if obj.ssdeep and 'ssdeep' not in exclude: f.add_hash(Hash(obj.ssdeep, Hash.TYPE_SSDEEP)) if 'size' not in exclude and 'size_in_bytes' not in exclude: f.size_in_bytes = UnsignedLong(obj.size) if 'filename' not in exclude and 'file_name' not in exclude: f.file_name = obj.filename # create an Artifact object for the binary if it exists if 'filedata' not in exclude and bin_fmt: data = obj.filedata.read() if data: # if sample data available a = Artifact(data, Artifact.TYPE_FILE) # create artifact w/data if bin_fmt == "zlib": a.packaging.append(ZlibCompression()) a.packaging.append(Base64Encoding()) elif bin_fmt == "base64": a.packaging.append(Base64Encoding()) f.add_related(a, "Child_Of") # relate artifact to file if 'filetype' not in exclude and 'file_format' not in exclude: #NOTE: this doesn't work because the CybOX File object does not # have any support built in for setting the filetype to a # CybOX-binding friendly object (e.g., calling .to_dict() on # the resulting CybOX object fails on this field. f.file_format = obj.filetype observables.append(Observable(f)) return (observables, obj.releasability) else: return (None, None)
def cybox_object_email(obj): e = EmailMessage() e.raw_body = obj.raw_body e.raw_header = obj.raw_header # Links e.links = Links() for link in obj.links.all(): pass # Attachments e.attachments = Attachments() attachment_objects = [] for att in obj.attachments.all(): for meta in att.file_meta.all(): fobj = cybox_object_file(att, meta) e.attachments.append(fobj.parent.id_) fobj.add_related(e, "Contained_Within", inline=False) attachment_objects.append(fobj) # construct header information h = EmailHeader() h.subject = obj.subject h.date = obj.email_date h.message_id = obj.message_id h.content_type = obj.content_type h.mime_version = obj.mime_version h.user_agent = obj.user_agent h.x_mailer = obj.x_mailer # From for from_ in obj.from_string.all(): from_address = EmailAddress(from_.sender) from_address.is_spoofed = from_.is_spoofed from_address.condition = from_.condition h.from_ = from_address # Sender for sender in obj.sender.all(): sender_address = EmailAddress(sender.sender) sender_address.is_spoofed = sender.is_spoofed sender_address.condition = sender.condition h.sender.add(sender_address) # To recipients = EmailRecipients() for recipient in obj.recipients.all(): rec_address = EmailAddress(recipient.recipient) rec_address.is_spoofed = recipient.is_spoofed rec_address.condition = recipient.condition recipients.append(rec_address) h.to = recipients # CC recipients = EmailRecipients() for recipient in obj.recipients_cc.all(): rec_address = EmailAddress(recipient.recipient) rec_address.is_spoofed = recipient.is_spoofed rec_address.condition = recipient.condition recipients.append(rec_address) h.cc = recipients # BCC recipients = EmailRecipients() for recipient in obj.recipients_bcc.all(): rec_address = EmailAddress(recipient.recipient) rec_address.is_spoofed = recipient.is_spoofed rec_address.condition = recipient.condition recipients.append(rec_address) h.bcc = recipients e.header = h return e, attachment_objects
def json2observable(config, src, dest, endpoint, json_, crits_id): # TODO split into smaller functions '''transform crits observables into cybox''' try: set_id_method(IDGenerator.METHOD_UUID) xmlns_url = config['edge']['sites'][dest]['stix']['xmlns_url'] xmlns_name = config['edge']['sites'][dest]['stix']['xmlns_name'] set_cybox_id_namespace(Namespace(xmlns_url, xmlns_name)) if endpoint == 'ips': crits_types = { 'Address - cidr': 'cidr', 'Address - ipv4-addr': 'ipv4-addr', 'Address - ipv4-net': 'ipv4-net', 'Address - ipv4-net-mask': 'ipv4-netmask', 'Address - ipv6-addr': 'ipv6-addr', 'Address - ipv6-net': 'ipv6-net', 'Address - ipv6-net-mask': 'ipv6-netmask' } addr = Address(address_value=json_['ip'], category=crits_types[json_['type']]) addr.condition = 'Equals' observable_ = Observable(addr) elif endpoint == 'domains': domain = DomainName() domain.type_ = 'FQDN' domain.value = json_['domain'] domain.condition = 'Equals' observable_ = Observable(domain) elif endpoint == 'samples': crits_types = { 'md5': 'MD5', 'sha1': 'SHA1', 'sha224': 'SHA224', 'sha256': 'SHA256', 'sha384': 'SHA384', 'sha512': 'SHA512', 'ssdeep': 'SSDEEP' } file_object = File() file_object.file_name = json_['filename'] for hash in crits_types.keys(): if hash in json_: file_object.add_hash( Hash(json_[hash], type_=crits_types[hash])) for i in file_object.hashes: i.simple_hash_value.condition = "Equals" observable_ = Observable(file_object) elif endpoint == 'emails': crits_types = { 'subject': 'subject', 'to': 'to', 'cc': 'cc', 'from_address': 'from_', 'sender': 'sender', 'date': 'date', 'message_id': 'message_id', 'reply_to': 'reply_to', 'boundary': 'boundary', 'x_mailer': 'x_mailer', 'x_originating_ip': 'x_originating_ip' } email = EmailMessage() email.header = EmailHeader() for k in crits_types.keys(): val = json_.get(k, None) if val: email.header.__setattr__(crits_types[k], val) email.header.__getattribute__(crits_types[k]).condition = \ 'Equals' observable_ = Observable(email) else: config['logger'].error( log.log_messages['unsupported_object_error'].format( type_='crits', obj_type=endpoint, id_=crits_id)) return (None) observable_.id = xmlns_name + ':observable-' + crits_id observable_.id_ = observable_.id return (observable_) except: e = sys.exc_info()[0] config['logger'].error(log.log_messages['obj_convert_error'].format( src_type='crits', src_obj='observable', id_=crits_id, dest_type='cybox', dest_obj='observable')) config['logger'].exception(e) return (None)
inline=True) file_attachment_object.attachments.append( attached_file_object.parent.id_) attachdescription = "Phishing email attachment\nFrom: %s\nSubj: %s\n Filename: %s\nSize: %s\nMD5: %s\nSHA1: %s\nSHA256: %s\nSSDEEP: %s\nAnalyst Notes: %s\n"\ %(xfrom,xsubject,xfilename,xfilesize,xmd5,xsha1,xsha256,xssdeep,acomment) indicator_attachment = Indicator(description=attachdescription) indicator_attachment.title = "Phishing E-mail Attachment" indicator_attachment.add_indicator_type("Malicious E-mail") indicator_attachment.observable = file_attachment_object indicator_attachment.confidence = "High" full_email_object.attachments = Attachments() # Add the previously referenced file as another reference rather than define it again: full_email_object.attachments.append(attached_file_object.parent.id_) full_email_object.header = EmailHeader() full_email_object.header.date = xdate full_email_object.header.date.condition = "Equals" full_email_object.header.From = xfrom full_email_object.header.sender = xsender full_email_object.header.sender.condition = "Equals" full_email_object.header.reply_to = xreplyto full_email_object.header.reply_to.condition = "Equals" full_email_object.header.subject = xsubject full_email_object.header.subject.condition = "Equals" full_email_object.header.x_originating_ip = xoriginatingip full_email_object.header.x_originating_ip.condition = "Equals" full_email_object.header.x_mailer = xmailer full_email_object.header.x_mailer.condition = "Equals" full_email_object.raw_body = xbody
def __check_set_email_header(self, cybox_email): if not cybox_email.header: cybox_email.header = EmailHeader()
def execute(self, device_info, extracted_data_dir_path): original_app_path = '/data/data/com.android.email' headers_db_rel_file_path = os.path.join('databases', 'EmailProvider.db') bodies_db_rel_file_path = os.path.join('databases', 'EmailProviderBody.db') original_headers_db_file_path = os.path.join(original_app_path, headers_db_rel_file_path) original_bodies_db_file_path = os.path.join(original_app_path, bodies_db_rel_file_path) headers_db_file_path = os.path.join(extracted_data_dir_path, headers_db_rel_file_path) bodies_db_file_path = os.path.join(extracted_data_dir_path, bodies_db_rel_file_path) source_objects = [ create_file_object(headers_db_file_path, original_headers_db_file_path), create_file_object(bodies_db_file_path, original_bodies_db_file_path) ] inspected_objects = {} cursor, conn = execute_query(headers_db_file_path, 'SELECT * FROM message') for row in cursor: header = EmailHeader() header.to = row['toList'] header.cc = row['ccList'] header.bcc = row['bccList'] header.from_ = row['fromList'] header.subject = row['subject'] header.in_reply_to = row['replyToList'] header.date = datetime.fromtimestamp(row['timeStamp'] / 1000) # Convert from milliseconds to seconds header.message_id = row['messageId'] email = EmailMessage() email.header = header email.add_related(source_objects[0], ObjectRelationship.TERM_EXTRACTED_FROM, inline=False) # Add the email to the inspected_objects dict using its _id value as key. email_id = row['_id'] inspected_objects[email_id] = email cursor.close() conn.close() # Add full raw body to emails. cursor, conn = execute_query(bodies_db_file_path, 'SELECT _id, htmlContent, textContent FROM body') for row in cursor: email_id = row['_id'] email = inspected_objects.get(email_id) if email is not None: if row['htmlContent'] != '': email.raw_body = row['htmlContent'] email.header.content_type = 'text/html' else: email.raw_body = row['textContent'] email.header.content_type = 'text/plain' email.add_related(source_objects[1], ObjectRelationship.TERM_EXTRACTED_FROM, inline=False) cursor.close() # Add attachments to emails. cursor, conn = execute_query(headers_db_file_path, 'SELECT messageKey, contentUri FROM attachment') # Iteration over attachments for row in cursor: # Get current attachment email_id. email_id = row['messageKey'] # Find email in inspected_objects. email = inspected_objects.get(email_id) # If email has non attachments, initialize them. if email.attachments is None: email.attachments = Attachments() # Using contentUri, get attachment folder_prefix and file_name. attachment_rel_path_dirs = re.search('.*//.*/(.*)/(.*)/.*', row['contentUri']) # Group(1): contains attachment folder. # Group(2): contains attachment file_name. attachment_rel_file_path = os.path.join('databases', attachment_rel_path_dirs.group(1) + '.db_att', attachment_rel_path_dirs.group(2)) # Build attachment absolute file path in extracted_data. attachment_file_path = os.path.join(extracted_data_dir_path, attachment_rel_file_path) # Build attachment original file_path in device. original_attachment_file_path = os.path.join(original_app_path, attachment_rel_file_path) # Create attachment source_file. attachment = create_file_object(attachment_file_path, original_attachment_file_path) # Add attachment to email's attachments. email.attachments.append(attachment.parent.id_) # Add relation between attachment and it's email. attachment.add_related(email, ObjectRelationship.TERM_CONTAINED_WITHIN, inline=False) source_objects.append(attachment) cursor.close() conn.close() return inspected_objects.values(), source_objects