import demistomock as demisto from CommonServerPython import * from CommonServerUserPython import * """IMPORTS""" import json import math import random from datetime import datetime from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from faker import Faker from faker.providers import internet, lorem, misc, user_agent """SETUP""" fake = Faker() fake.add_provider(internet) fake.add_provider(misc) fake.add_provider(lorem) fake.add_provider(user_agent) """GLOBAL VARS""" PARAMS = demisto.params() INCIDENT_TYPE = PARAMS.get("incidentType", "PhishingDemo") INCIDENTS_PER_MINUTE = int(PARAMS.get("incidents_per_minute", "5")) MAX_NUM_OF_INCIDENTS = int(PARAMS.get("max_num_of_incidents", "10")) FREQUENCY = PARAMS.get("frequency") INDICATORS_PER_INCIDENT = 5 INDICATORS_TO_INCLUDE = ["ipv4_public", "url", "domain_name", "sha1", "sha256", "md5"] EMAIL_PROTOCOLS = ["POP3", "IMAP", "SMTP", "ESMTP", "HTTP", "HTTPS"] # About the drop some mean regex right now disable-secrets-detection-start TEMPLATE_1 = """ Simple Transactional Email """ TEMPLATE_2 = """ Responsive HTML email templates
Logo
Please enable images to view this content
INTRODUCING
Responsive HTML email templates
{}
View on GitHub

""" # Drops the mic disable-secrets-detection-end EMAIL_TEMPLATES = [TEMPLATE_1, TEMPLATE_2] """HELPER FUNCTIONS""" def update_parameters(): """ Check and see if the integration parameters changed and if so update global vars """ params = demisto.params() incidents_per_minute = int(params.get("incidents_per_minute", "5")) max_num_of_incidents = int(params.get("max_num_of_incidents", "10")) frequency = int(params.get("frequency")) if params.get("frequency") else None global INCIDENTS_PER_MINUTE if incidents_per_minute != INCIDENTS_PER_MINUTE: INCIDENTS_PER_MINUTE = incidents_per_minute global MAX_NUM_OF_INCIDENTS if max_num_of_incidents != MAX_NUM_OF_INCIDENTS: MAX_NUM_OF_INCIDENTS = max_num_of_incidents global FREQUENCY if frequency != FREQUENCY: FREQUENCY = frequency def generate_dbot_score(indicator): """Arbitrary (but consistent) scoring method Assign a dbot score according to the last digit of the hash of the indicator. parameter: (string) indicator The indicator for which we need to generate a dbot score returns: Dbot score (0,1,2, or 3) """ the_hash = hash(indicator) last_digit = abs(the_hash) % 10 if last_digit == 0: return 0 elif last_digit < 5: return 1 elif last_digit < 8: return 2 else: return 3 def create_content(): """ Generate fake content to populate the email with Generates textual contents that are randomly generated and defined to include 5 random IPs, 5 random URLs, 5 random sha1 hashes, 5 random sha256 hashes, 5 random md5 hashes, 5 random email addresses, 5 random domains and 100 random words. returns: The randomly generated data as a string """ details = fake.text(600) # pylint: disable=no-member details += "\n" for _ in range(INDICATORS_PER_INCIDENT): ipv4, url, domain = fake.ipv4_public(), fake.url(), fake.domain_name() # pylint: disable=no-member sha1, sha256, md5 = fake.sha1(), fake.sha256(), fake.md5() # pylint: disable=no-member details += str(ipv4) + " " + str(url) + " " + str(domain) + " " + str(sha1) + " " + str(sha256) + " " + str(md5) + "\n" emails = [fake.email() for _ in range(INDICATORS_PER_INCIDENT)] # pylint: disable=no-member details += " ".join(emails) return details def inject_content_into_template(plaintext): """ Choose an email html template at random and populate the main textual component with randomly generated content passed in the 'plaintext' parameter parameter: (string) plaintext The randomly generated content to be used in the email html returns: The html template populated with the randomly generated content """ # Choose random email html template choice = random.randint(0, len(EMAIL_TEMPLATES) - 1) chosen_template = EMAIL_TEMPLATES[choice] html = chosen_template.format(plaintext) return html def create_email(): """ Create message object using template and random data returns: email.Message object and the email as a standard dictionary """ sender = fake.email() # pylint: disable=no-member recipient = fake.email() # pylint: disable=no-member cc = [fake.email() for _ in range(random.randint(0, 2))] # pylint: disable=no-member bcc = [fake.email() for _ in range(random.randint(0, 2))] # pylint: disable=no-member the_time = datetime.now() received = "from " + fake.hostname() + " (" + fake.ipv4_public() # pylint: disable=no-member received += ")" + "by " + fake.domain_word() + "." # pylint: disable=no-member received += fake.free_email_domain() + " with " # pylint: disable=no-member received += EMAIL_PROTOCOLS[random.randint(0, len(EMAIL_PROTOCOLS) - 1)] received += "; " + the_time.strftime("%c") msg = MIMEMultipart("alternative") msg["Subject"] = fake.sentence() # pylint: disable=no-member msg["From"] = sender msg["Reply-To"] = sender msg["To"] = recipient msg["Message-ID"] = str(fake.uuid4()) # pylint: disable=no-member msg["CC"] = ", ".join(cc) if cc else "" msg["BCC"] = ", ".join(bcc) if bcc else "" msg["User-Agent"] = fake.user_agent() # pylint: disable=no-member msg["Date"] = the_time.strftime("%Y-%m-%dT%H:%M:%SZ") msg["Received"] = received plaintext = create_content() html = inject_content_into_template(plaintext) part1 = MIMEText(plaintext, "plain") part2 = MIMEText(html, "html") msg.attach(part1) msg.attach(part2) email_object = {} for key, val in msg.items(): email_object[key] = val email_object["Text"] = plaintext email_object["Body"] = html return msg, email_object def generate_incidents(last_run): """ Determines how many incidents to create and generates them parameter: (number) last_run The number of incidents generated in the last fetch returns: The number of incidents generated in the current call to fetch_incidents and the incidents themselves """ if last_run > 0 and last_run > MAX_NUM_OF_INCIDENTS: demisto.info("last_run is greater than MAX_NUM_OF_INCIDENTS") return 0, [] incidents = [] num_of_incidents_left_to_create = MAX_NUM_OF_INCIDENTS - last_run if num_of_incidents_left_to_create > INCIDENTS_PER_MINUTE: num_of_incident_to_create = INCIDENTS_PER_MINUTE else: num_of_incident_to_create = num_of_incidents_left_to_create for _ in range(num_of_incident_to_create): email, email_object = create_email() incidents.append( { "name": email_object.get("Subject"), "details": email.as_string(), "occurred": email_object.get("Date"), "type": INCIDENT_TYPE, "rawJSON": json.dumps(email_object), } ) return num_of_incident_to_create, incidents """MAIN FUNCTIONS""" def fetch_incidents(): """ Generates and fetches phishing email-like incidents Generates phishing email-like incidents, with the number of incidents, the speed of generation and the recurring time period all set by the values entered in the integration instance parameters. This method operates under the assumption that fetch-incidents is called once per minute. returns: Email-like incidents """ try: update_parameters() minutes_of_generation = MAX_NUM_OF_INCIDENTS / float(INCIDENTS_PER_MINUTE) if not FREQUENCY or minutes_of_generation > FREQUENCY: # Run once last_run = 0 if not demisto.getLastRun() else demisto.getLastRun().get("numOfIncidentsCreated", 0) num_of_incidents_created, incidents = generate_incidents(last_run) demisto.incidents(incidents) demisto.setLastRun({"numOfIncidentsCreated": last_run + num_of_incidents_created}) return else: run_counter = 0 if not demisto.getLastRun() else demisto.getLastRun().get("run_count", 0) last_run = 0 if not demisto.getLastRun() else demisto.getLastRun().get("numOfIncidentsCreated", 0) should_run = run_counter % FREQUENCY if should_run < math.ceil(minutes_of_generation): # then should run if should_run == 0: last_run = 0 num_of_incidents_created, incidents = generate_incidents(last_run) demisto.incidents(incidents) total_incidents_created = last_run + num_of_incidents_created updated_run_count = run_counter + 1 demisto.setLastRun({"numOfIncidentsCreated": total_incidents_created, "run_count": updated_run_count}) return else: updated_run_count = run_counter + 1 demisto.setLastRun({"numOfIncidentsCreated": last_run, "run_count": updated_run_count}) demisto.incidents([]) except Exception: raise def demo_ip_command(): """ Returns the reputation generated by this integration for the IP address passed as an argument demisto param: (string) ip The IP address to get the reputation of returns: IP Reputation to the context """ ip = demisto.args().get("ip") dbotscore = generate_dbot_score(ip) dbotscore_output = {"Indicator": ip, "Type": "ip", "Vendor": "OnboardingIntegration", "Score": dbotscore} standard_ip_output = {"Address": ip} if dbotscore == 3: standard_ip_output["Malicious"] = { "Vendor": "OnboardingIntegration", "Description": "Indicator was found to be malicious.", } context = {"DBotScore": dbotscore_output, outputPaths["ip"]: standard_ip_output} title = f"OnboardingIntegration IP Reputation - {ip}" human_readable = tableToMarkdown(title, dbotscore_output) demisto.results( { "Type": entryTypes["note"], "Contents": context, "ContentsFormat": formats["json"], "ReadableContentsFormat": formats["markdown"], "HumanReadable": human_readable, "EntryContext": context, } ) def demo_url_command(): """ Returns the reputation generated by this integration for the URL passed as an argument demisto param: (string) url The URL to get the reputation of returns: URL Reputation to the context """ url = demisto.args().get("url") dbotscore = generate_dbot_score(url) dbotscore_output = {"Indicator": url, "Type": "url", "Vendor": "OnboardingIntegration", "Score": dbotscore} standard_url_output = {"Data": url} if dbotscore == 3: standard_url_output["Malicious"] = { "Vendor": "OnboardingIntegration", "Description": "Indicator was found to be malicious.", } context = {"DBotScore": dbotscore_output, outputPaths["url"]: standard_url_output} title = f"OnboardingIntegration URL Reputation - {url}" human_readable = tableToMarkdown(title, dbotscore_output) demisto.results( { "Type": entryTypes["note"], "Contents": context, "ContentsFormat": formats["json"], "ReadableContentsFormat": formats["markdown"], "HumanReadable": human_readable, "EntryContext": context, } ) def demo_domain_command(): """ Returns the reputation generated by this integration for the domain passed as an argument demisto param: (string) domain The domain to get the reputation of returns: Domain Reputation to the context """ domain = demisto.args().get("domain") dbotscore = generate_dbot_score(domain) dbotscore_output = {"Indicator": domain, "Type": "domain", "Vendor": "OnboardingIntegration", "Score": dbotscore} standard_domain_output = {"Name": domain} if dbotscore == 3: standard_domain_output["Malicious"] = { "Vendor": "OnboardingIntegration", "Description": "Indicator was found to be malicious.", } context = {"DBotScore": dbotscore_output, outputPaths["domain"]: standard_domain_output} title = f"OnboardingIntegration Domain Reputation - {domain}" human_readable = tableToMarkdown(title, dbotscore_output) demisto.results( { "Type": entryTypes["note"], "Contents": context, "ContentsFormat": formats["json"], "ReadableContentsFormat": formats["markdown"], "HumanReadable": human_readable, "EntryContext": context, } ) def demo_file_command(): """ Returns the reputation generated by this integration for the file hash passed as an argument demisto param: (string) file The file hash to get the reputation of returns: File-Hash Reputation to the context """ file = demisto.args().get("file") hash_type = get_hash_type(file).upper() dbotscore = generate_dbot_score(file) dbotscore_output = {"Indicator": file, "Type": "file", "Vendor": "OnboardingIntegration", "Score": dbotscore} standard_file_output = {hash_type: file} if dbotscore == 3: standard_file_output["Malicious"] = { "Vendor": "OnboardingIntegration", "Description": "Indicator was found to be malicious.", } context = {"DBotScore": dbotscore_output, outputPaths["file"]: standard_file_output} title = f"OnboardingIntegration File Reputation - {file}" human_readable = tableToMarkdown(title, dbotscore_output) demisto.results( { "Type": entryTypes["note"], "Contents": context, "ContentsFormat": formats["json"], "ReadableContentsFormat": formats["markdown"], "HumanReadable": human_readable, "EntryContext": context, } ) def demo_email_command(): """ Returns the reputation generated by this integration for the email address passed as an argument demisto param: (string) email The email address to get the reputation of returns: Email Reputation to the context """ email = demisto.args().get("email") dbotscore = generate_dbot_score(email) dbotscore_output = {"Indicator": email, "Type": "email", "Vendor": "OnboardingIntegration", "Score": dbotscore} standard_email_output = {"Address": email} if dbotscore == 3: standard_email_output["Malicious"] = { "Vendor": "OnboardingIntegration", "Description": "Indicator was found to be malicious.", } context = {"DBotScore": dbotscore_output, outputPaths["email"]: standard_email_output} title = f"OnboardingIntegration Email Reputation - {email}" human_readable = tableToMarkdown(title, dbotscore_output) demisto.results( { "Type": entryTypes["note"], "Contents": context, "ContentsFormat": formats["json"], "ReadableContentsFormat": formats["markdown"], "HumanReadable": human_readable, "EntryContext": context, } ) """ COMMANDS MANAGER / SWITCH PANEL """ COMMANDS = { "demo-url": demo_url_command, "demo-ip": demo_ip_command, "demo-email": demo_email_command, "demo-file": demo_file_command, "demo-domain": demo_domain_command, "fetch-incidents": fetch_incidents, } def main(): try: if demisto.command() == "test-module": demisto.results("ok") elif demisto.command() in COMMANDS: COMMANDS[demisto.command()]() except Exception as e: return_error(str(e)) # python2 uses __builtin__ python3 uses builtin s if __name__ == "__builtin__" or __name__ == "builtins": main()