Пример #1
0
 def test_rating_50(self, f_links, f_settings, f_mail_fields_dict):
     """Test email with link (which is already in db three times) 
     and username in body_plain"""
     push_into_db(self.settings1)
     self.f_link4 = Link(self.link2, 3, 60)
     push_into_db(self.f_link4)
     self.mail_fields_dict5 = {
         "text": " ".join([self.body_plain1, self.username1, self.link2]),
         "html": "",
         "subject": self.subject1,
         "from": self.email1,
         "from_name": "",
         "to": [(self.email2, "")],
         "date": 1587322973.484211,
         "attachmentFileName": [],
         "links": [self.link2],
     }
     self.mail_fields_dict5["len"] = (
         len(self.mail_fields_dict5["html"]) +
         len(self.mail_fields_dict5["subject"]) +
         len(self.mail_fields_dict5["text"]))
     self.mail_fields_dict5["ssdeep"] = get_fuzzy_hash(
         self.mail_fields_dict5)
     rating = conclude(self.mail_fields_dict5, self.fake_eml_file,
                       self.fake_mail_request)
     assert rating == 50
Пример #2
0
 def test_rating_30(self, f_settings, f_mail_fields_dict):
     """Test email with the username in body_plain, body_plain is very long"""
     push_into_db(self.settings1)
     self.body_plain5 = (self.generator.paragraph() + "\n" +
                         self.generator.paragraph())
     self.mail_fields_dict5 = {
         "text": " ".join([self.body_plain5, self.username1]),
         "html": "",
         "subject": self.subject1,
         "from": self.email1,
         "from_name": "",
         "to": [(self.email2, "")],
         "date": 1587322973.484211,
         "attachmentFileName": [],
         "links": [],
     }
     self.mail_fields_dict5["len"] = (
         len(self.mail_fields_dict5["html"]) +
         len(self.mail_fields_dict5["subject"]) +
         len(self.mail_fields_dict5["text"]))
     self.mail_fields_dict5["ssdeep"] = get_fuzzy_hash(
         self.mail_fields_dict5)
     rating = conclude(self.mail_fields_dict5, self.fake_eml_file,
                       self.fake_mail_request)
     assert rating == 30
Пример #3
0
def prepare_testing_env():
    Path("./queue").mkdir(parents=True, exist_ok=True)
    Path("./queue/new").mkdir(parents=True, exist_ok=True)
    Path("./undeliverable").mkdir(parents=True, exist_ok=True)
    Path("./attachments").mkdir(parents=True, exist_ok=True)
    settings1 = Settings(username="******", password="******")
    push_into_db(settings1)
    utils.import_settings(True, boot_module="testing_boot")
Пример #4
0
 def test_rating_100_1(self, f_password):
     """Test email with the password in body_plain"""
     self.password4 = "changeme"
     self.username4 = "changeme"
     self.settings4 = Settings(username=self.username4,
                               password=self.password4)
     push_into_db(self.settings4)
     mail_request = MailRequest(self.eml_file1, None, None,
                                self.eml_content(self.eml_file1))
     mail_fields = process_email(self.eml_file1, mail_request)
     rating = conclude(mail_fields, self.eml_file1, mail_request)
     assert rating == 100
Пример #5
0
 def test_db_link_read(self, f_links):
     assert self.f_link1.link == self.link1
     for link in self.links_list:
         push_into_db(link)
     links = get_links()
     assert links[0].link == self.f_link1.link
     assert links[1].link == self.f_link2.link
     assert links[2].rating == 60
     link = get_link_by_name(self.f_link1.link)
     assert link.counter == 1
     update_link_counter(self.f_link2)
     link = get_link_by_name(self.f_link2.link)
     assert link.counter == 3
Пример #6
0
 def test_db_settings_read(self, f_settings):
     for settings in self.settings_list:
         push_into_db(settings)
     db_passwords = get_passwords()
     db_usernames = get_usernames()
     assert are_credentials_in_db(self.settings1.username,
                                  self.settings1.password)
     assert db_passwords[0] == self.password1
     assert db_usernames[0] == self.username1
     assert db_passwords[1] == self.password2
     assert db_usernames[1] == self.username2
     assert db_passwords[2] == self.password3
     assert db_usernames[2] == self.username3
Пример #7
0
def update_statistics(checkpoint_id):
    """Function changes the statistics about a checkpoint that 
    changes the rating of the email.

    Args:
        checkpoint_id (int): Unique id for the checkpoint.
    """
    row = get_statistics_by_checkpoint_id(checkpoint_id)
    if row:
        update_statistics_counter(row)
    else:
        new_statistics_record = Statistics(
            checkpoint_id=checkpoint_id,
            counter=1,
            created=datetime.timestamp(datetime.today()),
            last_modified=datetime.timestamp(datetime.today()),
        )
        push_into_db(new_statistics_record)
Пример #8
0
 def f_mail_fields(self, f_mail_fields_dict):
     self.mail_fields1 = MailFields(
         subject=self.subject1,
         email_date=datetime.timestamp(datetime.today()),
         body_html=self.body_html1,
         ssdeep=get_fuzzy_hash(self.mail_fields_dict1),
         length=self.length(self.mail_fields_dict1),
         attachment=False,
     )
     self.mail_fields2 = MailFields(
         subject=self.subject2,
         email_date=datetime.timestamp(datetime.today()),
         body_plain=self.body_plain2,
         ssdeep=get_fuzzy_hash(self.mail_fields_dict2),
         length=self.length(self.mail_fields_dict2),
         attachment=False,
     )
     self.mail_fields3 = MailFields(
         subject=self.subject3,
         email_date=datetime.timestamp(datetime.today()),
         body_plain=self.body_plain3,
         body_html=self.body_html3,
         ssdeep=get_fuzzy_hash(self.mail_fields_dict3),
         length=self.length(self.mail_fields_dict3),
         attachment=True,
     )
     self.mail_fields4 = MailFields(
         subject=self.subject4,
         email_date=datetime.timestamp(datetime.today()),
         body_plain=self.body_plain4,
         body_html=self.body_html4,
         ssdeep=get_fuzzy_hash(self.mail_fields_dict4),
         length=self.length(self.mail_fields_dict4),
         attachment=False,
     )
     self.mail_fields_list = [
         self.mail_fields1,
         self.mail_fields2,
         self.mail_fields3,
         self.mail_fields4,
     ]
     for mf in self.mail_fields_list:
         push_into_db(mf)
Пример #9
0
 def test_rating_55(self, f_settings, f_mail_fields_dict):
     """Test email with the username in body_plain and test time"""
     push_into_db(self.settings1)
     self.mail_fields_dict5 = {
         "text": " ".join([self.body_plain1, self.username1]),
         "html": "",
         "subject": self.subject1,
         "from": self.email1,
         "from_name": "",
         "to": [(self.email2, "")],
         "date": 1587298372.484211,
         "attachmentFileName": [],
         "links": [],
     }
     self.mail_fields_dict5["len"] = (
         len(self.mail_fields_dict5["html"]) +
         len(self.mail_fields_dict5["subject"]) +
         len(self.mail_fields_dict5["text"]))
     self.mail_fields_dict5["ssdeep"] = get_fuzzy_hash(
         self.mail_fields_dict5)
     rating = conclude(self.mail_fields_dict5, self.fake_eml_file,
                       self.fake_mail_request)
     assert rating == 55
Пример #10
0
 def test_rating_0(self, f_settings, f_mail_fields_dict):
     """Test email with attachment and word test in subject"""
     push_into_db(self.settings1)
     self.mail_fields_dict5 = {
         "text": " ".join([self.body_plain2]),
         "html": "",
         "subject": " ".join(["test"]),
         "from": self.email1,
         "from_name": "",
         "to": [(self.email2, "")],
         "date": 1587322973.484211,
         "attachmentFileName": ["test.doc"],
         "links": [],
     }
     self.mail_fields_dict5["len"] = (
         len(self.mail_fields_dict5["html"]) +
         len(self.mail_fields_dict5["subject"]) +
         len(self.mail_fields_dict5["text"]))
     self.mail_fields_dict5["ssdeep"] = get_fuzzy_hash(
         self.mail_fields_dict5)
     rating = conclude(self.mail_fields_dict5, self.fake_eml_file,
                       self.fake_mail_request)
     assert rating == 0
Пример #11
0
def conclude(mail_fields, key, mail_request):
    """This is a key function of the whole relay part.

    Function calls other auxiliary functions and calculates the
    final rating of the email. This is called each time a new email arrives.

    Args:
        mail_fields (dict): Email parsed in the dictionary.
        key (str): Name of the file picked up from queue/new.
        mail_request (MailRequest): Instance of the MailRequest class with eml data.

    Returns:
        int: Final email rating when the environmental variable SALMON_SETTINGS_MODULE is set.
    """
    logging.debug(
        "[+] (salmonconclude.py) - In conclude, started calculating the final spam rating."
    )
    attachment = False
    if mail_fields["attachmentFileName"]:
        attachment = True

    # just for the testing purpose
    if mail_fields["text"] == "this is testing email from salmon":
        salmonrelay.relay(mail_fields, key, mail_request, 100)
        return 100

    spam = Spam(
        subject=str(mail_fields["subject"]),
        email_date=str(mail_fields["date"]),
        body_plain=mail_fields["text"],
        body_html=mail_fields["html"],
        ssdeep=mail_fields["ssdeep"],
        length=mail_fields["len"],
        attachment=attachment,
    )
    database_mail_fields = MailFields(
        subject=spam.subject,
        email_date=spam.email_date,
        body_plain=spam.body_plain,
        body_html=spam.body_html,
        ssdeep=spam.ssdeep,
        length=spam.length,
        attachment=spam.attachment,
    )
    sender = Sender(mail_fields["from"], mail_fields["from_name"], database_mail_fields)
    recipient_model_list = spam.get_recipients_for_db(
        mail_fields["to"], database_mail_fields
    )

    # 1.check - try to find password in email
    spam.find_password_in_email()

    # 2.check - try to find username in email
    usernames = get_usernames()
    spam.find_username_in_email(usernames)

    # 3.check - check if the email contains links
    links_from_db = None
    links_into_db = None
    if len(mail_fields["links"]) > 0:
        links_from_db = get_links()
        links_into_db = spam.get_links_for_db(mail_fields["links"], links_from_db)

    # 4.check - verify that the email contains an attachment
    if len(mail_fields["attachmentFileName"]) > 0:
        spam.rating -= 10
        if utils.settings.data["relay"]["save_statistics"]:
            update_statistics(1)

    # 5.check - try to find the word test or testing in the email
    spam.find_word_test_in_email()

    # 6.check - verify that the recipient has already been used in test emails
    is_recipient_in_testmail = spam.is_recipient_in_testmail(mail_fields["to"])

    # 7.check - check the time the email arrived
    spam.investigate_time()

    # 8.check - try to find the IP address of the honeypot in the email
    spam.find_ip_address_in_email()

    # 9.check - analyze what is written in the email
    # this is optional and has to be set in the salmon.yaml
    if utils.settings.data["relay"]["analyze_text"]:
        analyze_text(mail_fields, spam)

    # 10.check - verify that similar email is not already in the database
    tables = get_tables_from_similar(spam)

    # there is a very high probability that email is testing
    push_into_db_testing(
        tables, spam, database_mail_fields, recipient_model_list, sender
    )

    # Verify that current email doesn't look more like a testing one
    can_push_into_db = False
    if len(tables) > 0:
        updater = DBUpdater(spam.rating, mail_fields, usernames)
        for table in tables:
            if isinstance(table, MaybeTestMail):
                if updater(table):
                    can_push_into_db = True

    # there is a chance that email is testing but not for sure
    push_into_db_maybetesting(
        tables,
        spam,
        can_push_into_db,
        database_mail_fields,
        recipient_model_list,
        sender,
    )

    # similar is in the maybe_test_emails table, but this one has a high rating
    for table in tables:
        if isinstance(table, MaybeTestMail) and (
            spam.rating >= 70 or is_recipient_in_testmail
        ):
            logging.info(
                "[+] (salmonconclude.py) - Moving a record from the maybe_test_emails table to the test_emails table."
            )
            move_to_testmail(table.mail_fields_id)

    if is_recipient_in_testmail:
        recipient_in_testmail(spam)

    if len(mail_fields["links"]) > 0:
        spam.update_link_rating(mail_fields["links"], links_from_db)

    if links_into_db and spam.rating >= 50:
        for link in links_into_db:
            link_model = Link(link, 1, spam.rating)
            push_into_db(link_model)

    # 11.check - match the email against the rule file
    # this is optional and has to be set in the salmon.yaml
    if utils.settings.data["relay"]["use_rule_file"]:
        for rule in utils.settings.rules:
            if spam.match_against_rule_file(rule):
                logging.info(
                    "[+] (salmonconclude.py) - Email successfully matched against the rule %s"
                    % rule["name"]
                )
                spam.rating = 100

    final_rating = spam.rating

    del spam
    if "SALMON_SETTINGS_MODULE" in os.environ:
        return final_rating
    salmonrelay.relay(mail_fields, key, mail_request, final_rating)
Пример #12
0
 def test_db_recipient_read(self, f_recipient):
     for recipient in self.recipients_list:
         push_into_db(recipient)
     db_recipients = get_recipients()
     assert db_recipients[3].email == self.email1
     assert db_recipients[4].name == self.name2
Пример #13
0
 def test_db_test_mail_read(self, f_test_emails):
     for email in self.test_emails_list:
         push_into_db(email)
     email = get_testmail_by_mailfield_id(1)
     assert email.id == 1
     assert email.mailfield.subject == self.subject1
Пример #14
0
 def test_db_maybe_test_mail_read(self, f_maybe_test_emails):
     for email in self.maybe_test_emails_list:
         push_into_db(email)
     email = get_maybetestmail_by_mailfield_id(2)
     assert email.id == 2
     assert email.mailfield.subject == self.subject2