Exemple #1
0
def generateEmailAttachmentObject(indicator, filename):
    file_object = File()
    file_object.file_name = filename
    email = EmailMessage()
    email.attachments = Attachments()
    email.add_related(file_object, "Contains", inline=True)
    email.attachments.append(file_object.parent.id_)
    indicator.observable = email
Exemple #2
0
def generateEmailAttachmentObject(indicator, attribute):
    file_object = File()
    file_object.file_name = attribute["value"]
    file_object.file_name.condition = "Equals"
    email = EmailMessage()
    email.attachments = Attachments()
    email.add_related(file_object, "Contains", inline=True)
    file_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":file-" + attribute["uuid"]
    email.attachments.append(file_object.parent.id_)
    email.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":EmailMessage-" + attribute["uuid"]
    observable = Observable(email)
    observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-" + attribute["uuid"]
    indicator.observable = observable
Exemple #3
0
 def generate_email_attachment_object(self, indicator, attribute):
     attribute_uuid = attribute.uuid
     file_object = File()
     file_object.file_name = attribute.value
     file_object.file_name.condition = "Equals"
     file_object.parent.id_ = "{}:FileObject-{}".format(self.namespace_prefix, attribute_uuid)
     email = EmailMessage()
     email.attachments = Attachments()
     email.add_related(file_object, "Contains", inline=True)
     email.attachments.append(file_object.parent.id_)
     email.parent.id_ = "{}:EmailMessageObject-{}".format(self.namespace_prefix, attribute_uuid)
     observable = Observable(email)
     observable.id_ = "{}:observable-{}".format(self.namespace_prefix, attribute_uuid)
     indicator.observable = observable
Exemple #4
0
    def __parse_email_message(self, msg):
        """ Parses the supplied message
        Returns a map of message parts expressed as cybox objects.

        Keys: 'message', 'files', 'urls'
        """
        
        files       = []
        url_list    = []
        domain_list = []
        message     = EmailMessage()

        # Headers are required (for now)
        message.header = self.__create_cybox_headers(msg)

        if self.include_attachments:
            files = self.__create_cybox_files(msg)
            message.attachments = Attachments()
            for f in files:
                message.attachments.append(f.parent.id_)
                f.add_related(message, "Contained_Within", inline=False)

        if self.include_raw_headers:
            raw_headers_str = self.__get_raw_headers(msg).strip()
            if raw_headers_str:
                message.raw_header = String(raw_headers_str)

        # need this for parsing urls AND raw body text
        raw_body = "\n".join(self.__get_raw_body_text(msg)).strip()

        if self.include_raw_body and raw_body:
            message.raw_body = String(raw_body)

        if self.include_urls:
            (url_list, domain_list) = self.__parse_urls(raw_body)
            if url_list:
                links = Links()
                for u in url_list:
                    links.append(LinkReference(u.parent.id_))
                if links:
                    message.links = links

        # Return a list of all objects we've built
        return [message] + files + url_list + domain_list
 def test_round_trip_list(self):
     a = Attachments()
     a.append("example:File-A1")
     a.append("example:File-A3")
     a2 = cybox.test.round_trip(a, list_=True)
     self.assertEqual(a.to_list(), a2.to_list())
Exemple #6
0
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)
Exemple #7
0
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)
Exemple #8
0
 def test_round_trip_list(self):
     a = Attachments()
     a.append("example:File-A1")
     a.append("example:File-A3")
     a2 = cybox.test.round_trip(a, list_=True)
     self.assertEqual(a.to_list(), a2.to_list())
Exemple #9
0
def main():
    # get args
    parser = argparse.ArgumentParser ( description = "Parse a given CSV and output STIX XML" 
    , formatter_class=argparse.ArgumentDefaultsHelpFormatter )

    parser.add_argument("--infile","-f", help="input CSV", default = "in.csv")

    args = parser.parse_args()

    # setup header
    contain_pkg = STIXPackage()
    stix_header = STIXHeader()
    stix_header.title = "Indicators"
    stix_header.add_package_intent ("Indicators")
    # XXX add Information_Source and Handling
    contain_pkg.stix_header = stix_header


    # create kill chain with three options (pre, post, unknown), relate as needed
    pre = KillChainPhase(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee", name="Pre-infection indicator", ordinality=1)
    post = KillChainPhase(phase_id="stix:KillChainPhase-d5459305-1a27-4f50-9875-23793d75e4fe", name="Post-infection indicator", ordinality=2)
    chain = KillChain(id_="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d", name="Degenerate Cyber Kill Chain"  )
    chain.definer = "U5"

    chain.kill_chain_phases = [pre, post]
    contain_pkg.ttps.kill_chains.append(chain)

    # read input data
    fd = open (args.infile, "rb") 
    infile = csv.DictReader(fd)

    for row in infile:
        # create indicator for each row
        error = False
        ind = Indicator()
        ind.add_alternative_id(row['ControlGroupID'])
        ind.title = "Indicator with ID " + row['IndicatorID'] 
        ind.description = row['Notes']
        ind.producer = InformationSource()
        ind.producer.description = row['Reference']

        # XXX unknown purpose for 'Malware' field - omitted
            # if the field denotes a specific malware family, we might relate as 'Malware TTP' to the indicator

        # set chain phase
        if 'Pre' in row['Infection Type']:
            ind.kill_chain_phases.append(KillChainPhaseReference(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee",kill_chain_id="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d"))
        elif 'Post' in row['Infection Type']:
            ind.kill_chain_phases.append(KillChainPhaseReference(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee",kill_chain_id="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d"))
 

        ind_type = row['Indicator Type']
        if 'IP' in ind_type:
            
            ind.add_indicator_type( "IP Watchlist")
            ind_obj = SocketAddress()
            ind_obj.ip_address = row['Indicator']
            ind_obj.ip_address.condition= "Equals"
            if row['indValue']:
                port = Port()
                # pull port out, since it's in form "TCP Port 42"
                port.port_value = row['indValue'].split()[-1] 
                port.layer4_protocol = row['indValue'].split()[0] 
                port.port_value.condition= "Equals"
                ind_obj.port = port


        elif 'Domain' in ind_type:
            ind.add_indicator_type ("Domain Watchlist")
            ind_obj = DomainName()
            ind_obj.value = row['Indicator']
            ind_obj.value.condition= "Equals"

        elif 'Email' in ind_type:
            # parse out which part of the email is being
            # i.e. "Sender: attach | Subject: whatever"
            tag = row['Indicator'].split(':')[0]
            val = row['Indicator'].split(':')[1]
            ind.add_indicator_type ("Malicious E-mail")
            ind_obj = EmailMessage()
            
            if "Subject" in tag:
                ind_obj.subject = val
                ind_obj.subject.condition= "Equals"
            elif "Sender" in tag:
                ind_obj.sender = val
                ind_obj.sender.condition= "Equals"
            
            elif "Attachment" in tag:
                # make inline File to store filename 
                file_obj = File()
                file_obj.id_ = cybox.utils.create_id(prefix="File")
                file_obj.file_name = val
                file_obj.file_name.condition = "Equals"
                ind_obj.add_related(file_obj, "Contains")
                
                attach = Attachments()
                attach.append(file_obj.id_)
                
                ind_obj.attachments = attach
                
        elif 'User Agent' in ind_type:
            ind.add_indicator_type( VocabString(row['Indicator Type']))
            
            fields = HTTPRequestHeaderFields()
            fields.user_agent = row['Indicator']
            fields.user_agent.condition = "Equals"
            header = HTTPRequestHeader()
            header.parsed_header = fields

            thing = HTTPRequestResponse()
            thing.http_client_request = HTTPClientRequest()
            thing.http_client_request.http_request_header = header

            ind_obj = HTTPSession()
            ind_obj.http_request_response = [thing]
            
        elif 'URI' in ind_type:
            ind.add_indicator_type( VocabString(row['Indicator Type']))
    
            thing = HTTPRequestResponse()
            thing.http_client_request = HTTPClientRequest()
            thing.http_client_request.http_request_line = HTTPRequestLine()
            thing.http_client_request.http_request_line.http_method = row['Indicator'].split()[0]
            thing.http_client_request.http_request_line.http_method.condition = "Equals" 
            thing.http_client_request.http_request_line.value = row['Indicator'].split()[1]
            thing.http_client_request.http_request_line.value.condition = "Equals" 

            ind_obj = HTTPSession()
            ind_obj.http_request_response = [thing]


        elif 'File' in ind_type:
            ind.add_indicator_type( VocabString(row['Indicator Type']))
            ind_obj = File()
            ind_obj.file_name = row['Indicator']
            ind_obj.file_name.condition = "Equals"
            digest = Hash()
            # XXX assumes that hash digests are stored in this field in real data
            digest.simple_hash_value = row['indValue'].strip()
            digest.simple_hash_value.condition = "Equals"
            digest.type_.condition = "Equals"

            ind_obj.add_hash(digest)

        elif 'Registry' in ind_type:
            ind.add_indicator_type( VocabString(row['Indicator Type']))
            
            ind_obj = WinRegistryKey()
            keys = RegistryValues()
            key = RegistryValue()
            key.name = row['Indicator']
            key.name.condition = "Equals"
            key.data = row['indValue']
            key.data.condition = "Equals"
            keys.append(key)
            ind_obj.values = keys

        elif 'Mutex' in ind_type:
            ind.add_indicator_type (VocabString(row['Indicator Type']))
            ind_obj = Mutex()
            ind_obj.name = row['Indicator']
            ind_obj.name.condition= "Equals"

        else:
            print "ERR type not supported: " + ind_type + " <- will be omitted from output"
            error = True

        # finalize indicator
        if not error:
            ind.add_object(ind_obj)
            contain_pkg.add_indicator(ind)

    # DONE looping

    print contain_pkg.to_xml() 
Exemple #10
0
    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
Exemple #11
0
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))
Exemple #12
0
    def to_cybox_observable(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.sender, 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 'x_mailer' not in exclude:
            obj.header.x_mailer = String(self.x_mailer)

        if 'boundary' not in exclude:
            obj.header.boundary = String(self.boundary)

        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)

        obj.attachments = Attachments()

        observables.append(Observable(obj))
        return (observables, self.releasability)
Exemple #13
0
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
Exemple #14
0
            # get all comments for the current attachment objectid
            comments = db.comments.find({'obj_id': ObjectId(yid)})
            for comment in comments:
                # check if the comments contain string 'analyst note'
                if comment['comment'].lower().startswith('analyst note'):
                    acomment = re.sub(r'\banalyst note\b',
                                      '',
                                      comment['comment'],
                                      flags=re.IGNORECASE)
        else:
            # no comments
            acomment = 'none'

        # 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 = xfilename
        attached_file_object.file_name.condition = "Equals"

        file_attachment_object.add_related(attached_file_object,
                                           "Contains",
                                           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"