Esempio n. 1
0
 def forwarded_email(self, pseudofile: BytesIO):
     '''Extracts all possible indicators out of an email and create a MISP event out of it.
     * Gets all relevant Headers
     * Attach the body
     * Create MISP file objects (uses lief if possible)
     * Set all references
     '''
     email_object = EMailObject(pseudofile=pseudofile,
                                attach_original_mail=True,
                                standalone=False)
     if email_object.attachments:
         # Create file objects for the attachments
         for attachment_name, attachment in email_object.attachments:
             if not (self.ignore_nullsize_attachments
                     and attachment.getbuffer().nbytes == 0):
                 if not attachment_name:
                     attachment_name = 'NameMissing.txt'
                 if self.config_from_email_body.get(
                         'attachment'
                 ) == self.config.m2m_benign_attachment_keyword:
                     a = self.misp_event.add_attribute(
                         'attachment',
                         value=attachment_name,
                         data=attachment)
                     email_object.add_reference(a.uuid, 'related-to',
                                                'Email attachment')
                 else:
                     f_object, main_object, sections = make_binary_objects(
                         pseudofile=attachment,
                         filename=attachment_name,
                         standalone=False)
                     if self.config.vt_key:
                         try:
                             vt_object = VTReportObject(
                                 self.config.vt_key,
                                 f_object.get_attributes_by_relation(
                                     'sha256')[0].value,
                                 standalone=False)
                             self.misp_event.add_object(vt_object)
                             f_object.add_reference(vt_object.uuid,
                                                    'analysed-with')
                         except InvalidMISPObject as e:
                             print(e)
                             pass
                     self.misp_event.add_object(f_object)
                     if main_object:
                         self.misp_event.add_object(main_object)
                         for section in sections:
                             self.misp_event.add_object(section)
                     email_object.add_reference(f_object.uuid, 'related-to',
                                                'Email attachment')
     self.process_body_iocs(email_object)
     if self.config.spamtrap or self.config.attach_original_mail or self.config_from_email_body.get(
             'attach_original_mail'):
         self.misp_event.add_object(email_object)
     return email_object
def handler(q=False):
    if q is False:
        return False

    # Decode and parse email
    request = json.loads(q)
    # request data is always base 64 byte encoded
    data = base64.b64decode(request["data"])

    email_object = EMailObject(pseudofile=BytesIO(data),
                               attach_original_mail=True,
                               standalone=False)

    # Check if we were given a configuration
    config = request.get("config", {})
    # Don't be picky about how the user chooses to say yes to these
    acceptable_config_yes = ['y', 'yes', 'true', 't']

    # Do we unzip attachments we find?
    unzip = config.get("unzip_attachments", None)
    if (unzip is not None and unzip.lower() in acceptable_config_yes):
        unzip = True

    # Do we try to find passwords for protected zip files?
    zip_pass_crack = config.get("guess_zip_attachment_passwords", None)
    if (zip_pass_crack is not None
            and zip_pass_crack.lower() in acceptable_config_yes):
        zip_pass_crack = True
        password_list = get_zip_passwords(email_object.email)

    # Do we extract URL's from the email.
    extract_urls = config.get("extract_urls", None)
    if (extract_urls is not None
            and extract_urls.lower() in acceptable_config_yes):
        extract_urls = True

    file_objects = []  # All possible file objects
    # Get Attachments
    # Get file names of attachments
    for attachment_name, attachment in email_object.attachments:
        # Create file objects for the attachments
        if not attachment_name:
            attachment_name = 'NameMissing.txt'

        temp_filename = Path(attachment_name)
        zipped_files = [
            "doc", "docx", "dot", "dotx", "xls", "xlsx", "xlm", "xla", "xlc",
            "xlt", "xltx", "xlw", "ppt", "pptx", "pps", "ppsx", "pot", "potx",
            "potx", "sldx", "odt", "ods", "odp", "odg", "odf", "fodt", "fods",
            "fodp", "fodg", "ott", "uot"
        ]
        # Attempt to unzip the attachment and return its files
        if unzip and temp_filename.suffix[1:] not in zipped_files:
            try:
                unzip_attachement(attachment_name, attachment, email_object,
                                  file_objects)
            except RuntimeError:  # File is encrypted with a password
                if zip_pass_crack is True:
                    password = test_zip_passwords(attachment, password_list)
                    if password:
                        unzip_attachement(attachment_name, attachment,
                                          email_object, file_objects, password)
                    else:  # Inform the analyst that we could not crack password
                        f_object, main_object, sections = make_binary_objects(
                            pseudofile=attachment,
                            filename=attachment_name,
                            standalone=False)
                        f_object.comment = "Encrypted Zip: Password could not be cracked from message"
                        file_objects.append(f_object)
                        file_objects.append(main_object)
                        file_objects += sections
                        email_object.add_reference(f_object.uuid, 'includes',
                                                   'Email attachment')
            except zipfile.BadZipFile:  # Attachment is not a zipfile
                # Just straight add the file
                f_object, main_object, sections = make_binary_objects(
                    pseudofile=attachment,
                    filename=attachment_name,
                    standalone=False)
                file_objects.append(f_object)
                file_objects.append(main_object)
                file_objects += sections
                email_object.add_reference(f_object.uuid, 'includes',
                                           'Email attachment')
        else:
            # Just straight add the file
            f_object, main_object, sections = make_binary_objects(
                pseudofile=attachment,
                filename=attachment_name,
                standalone=False)
            file_objects.append(f_object)
            file_objects.append(main_object)
            file_objects += sections
            email_object.add_reference(f_object.uuid, 'includes',
                                       'Email attachment')

    mail_body = email_object.email.get_body(preferencelist=('html', 'plain'))
    if extract_urls:
        if mail_body:
            charset = mail_body.get_content_charset()
            if mail_body.get_content_type() == 'text/html':
                url_parser = HTMLURLParser()
                url_parser.feed(
                    mail_body.get_payload(decode=True).decode(charset,
                                                              errors='ignore'))
                urls = url_parser.urls
            else:
                urls = re.findall(
                    r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+',
                    mail_body.get_payload(decode=True).decode(charset,
                                                              errors='ignore'))
            for url in urls:
                if not url:
                    continue
                url_object = URLObject(url, standalone=False)
                file_objects.append(url_object)
                email_object.add_reference(url_object.uuid, 'includes',
                                           'URL in email body')

    objects = [email_object.to_json()]
    if file_objects:
        objects += [o.to_json() for o in file_objects if o]
    r = {'results': {'Object': [json.loads(o) for o in objects]}}
    return r