def twitter_account(data): """ Do the things. :param data: :return: """ misp_event_id = data['misp_event_id'] twitter_post_id = data['twitter_post_id'] response_url = data['response_url'] try: # Get the Twitter status. status = twitter_get_account(twitter_post_id) # Extract relevant values from the Twitter status. microblog_data = transform_twitter_account(status._json) # Load the microblog version from it's definition.json file. with open("misp-objects/twitter-account/definition.json") as f: microblog_definition = json.load(f) f.close() # Create the MISP mircroblog object. # TODO: get the object definition from github # misp_objects_path_custom searches the var path for {objectname}/definition.json to load the object definition # This file needs to be updated when the upstream object is updated. microblog = TwitterAccountObject( parameters=microblog_data, misp_objects_path_custom="misp-objects", template_version=str(microblog_definition["version"])) # Get the MISP event. working_event = misp.get_event(misp_event_id, extended=True, pythonify=True) # Get the Slackbot's MISP org ID. user_profile = misp.get_user("me") bot_org_id = user_profile["User"]["org_id"] # If the bot org can update the MISP Event with the new microblog do so. if str(bot_org_id) == str(working_event["org_id"]): working_event.Object.append(microblog) result = misp.update_event(working_event) print(result) else: new_event = True # If an extension exists for Slackbot objects use it. if "extensionEvents" in working_event: for k, event_extension in working_event[ "extensionEvents"].items(): if event_extension["Orgc"]["id"] == bot_org_id: if event_extension[ "info"] == "Covid Slack: Disinfo Bot": extension_event = misp.get_event( event_extension["id"], pythonify=True) extension_event.Object.append(microblog) result = misp.update_event(extension_event) print(result) new_event = False # Create a new extension to the parent event. if new_event: extended_event = MISPEvent() extended_event.info = "Covid Slack: Disinfo Bot" extended_event.extends_uuid = working_event["id"] extended_event.Object.append(microblog) result = misp.add_event(extended_event, pythonify=True) print(result) # Build slack response. response = {'blocks': [], 'response_type': 'in_channel'} response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': 'Twitter Status: {}'.format(twitter_post_id) } }) twitter_message = "" if microblog_data.get('name'): twitter_message += 'Username: {}\n'.format(microblog_data['name']) if microblog_data.get('display-name'): twitter_message += 'Display Name: {}\n'.format( microblog_data['display-name']) if microblog_data.get('verified'): twitter_message += 'Verified Account: {}\n'.format( microblog_data['verified']) if microblog_data.get('description'): twitter_message += 'Bio: {}\n'.format( microblog_data['description']) if len(microblog_data['hashtag']) > 0: twitter_message += 'Hashtags:\n' for hashtag in microblog_data['hashtag']: twitter_message += '* {}\n'.format(hashtag) if len(microblog_data['embedded-link']) > 0: twitter_message += 'Embedded URLs:\n' for url in microblog_data['embedded-link']: twitter_message += '* {}\n'.format(url) # Add Twitter message as block. response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': twitter_message } }) requests.post(response_url, json=response) except Exception: logger.info(traceback.print_exc(file=sys.stdout)) message = "An error has occurred!" resp = build_response(message, False) requests.post(response_url, json=resp)
def process_reddit_account(data): """ Get data on reddit Account :param data: :return: """ misp_event_id = data['misp_event_id'] reddit_account_name = data['reddit_account'] response_url = data['response_url'] try: redditor = return_reddit_account(reddit_account_name) with open('misp-objects/reddit-account/definition.json') as f: reddit_account_definition = json.load(f) f.close() reddit_account_data = transform_reddit_account(redditor) reddit_account = RedditAccount(parameters=reddit_account_data, misp_objects_path_custom='misp-objects', template_version=str(reddit_account_definition['version'])) reddit_account["first_seen"] = reddit_account_data["first_seen"] # Get the MISP event working_event = misp.get_event(misp_event_id, extended=True, pythonify=True) # Get the slackbot's MISP ID user_profile = misp.get_user('me') bot_org_id = user_profile['User']['org_id'] if str(bot_org_id) == str(working_event['org_id']): working_event.Object.append(reddit_account) result = misp.update_event(working_event) print(result) else: new_event = True if 'extensionevents' in working_event: for k, event_extension in working_event['extensionEvents'].items(): if event_extension['Orgc']['id'] == bot_org_id: if event_extension['info'] == 'Covid Slack: Disinfo Bot': extension_event = misp.get_event(event_extension['id'], pythonify=True) extension_event.Object.append(reddit_account) result = misp.update_event(extension_event) print(result) new_event = False if new_event: extended_event = MISPEvent() extended_event.info = 'Covid Slack: Disinfo Bot' extended_event.extends_uuid = working_event['id'] extended_event.Object.append(reddit_account) result = misp.add_event(extended_event, pythonify=True) print(result) # Build slack response response = {'blocks': [], 'response_type': 'in_channel'} response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': f'Reddit Account Status: {reddit_account_name}' } }) message = reddit_account_data['description'] response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': message } }) requests.post(response_url, json=response) except: logger.info(traceback.print_exc(file=sys.stdout)) resp = build_response(f'Reddit user {reddit_account} not found') requests.post(url=response_url, json=resp)
def run(data): """ Run() is executed and passed to the Redis queue. Therefore this function must execute all of the bot logic. :param data: :return: """ misp_event_id = data['misp_event_id'] domain = data['domain'] response_url = data['response_url'] try: # Get BuiltWith tracking IDs for the specified domain. # We're going to then use the returned dict to build tracking-id MISP objects. tracking_ids = get_builtwith_tracking_ids(domain) # Get the MISP event that the user specified in Slack. # pythonify=True means we want to convert the response to a PyMISP Event object (default response is json). working_event = misp.get_event(misp_event_id, extended=True, pythonify=True) # Load the misp object version from it's definition.json file. # PyMISP validates created objects against the misp-object schema. # Some objects are included by default in PyMISP but new objects will need to be accessed like this. with open("misp-objects/tracking-id/definition.json") as f: object_definition = json.load(f) f.close() # Create the MISP microblog object. # TODO: get the object definition from github # misp_objects_path_custom searches the var path for {objectname}/definition.json to load the object definition # This file needs to be updated when the upstream object is updated. # # Build the tracking-id objects. misp_objects = [] for _, tracking_id in tracking_ids.items(): tracking_id_object = TrackingIDObject(parameters=tracking_id, misp_objects_path_custom="misp-objects", template_version=str(object_definition["version"])) misp_objects.append(tracking_id_object) # Get the Slackbot's MISP org ID. # We do this because the bot can't modify anther org's events. user_profile = misp.get_user("me") bot_org_id = user_profile["User"]["org_id"] # If the bot org is the same and the MISP Event org we can update it directly. if str(bot_org_id) == str(working_event["org_id"]): for each_object in misp_objects: # Add each tracking_id_object to the event. working_event.Object.append(each_object) # Increment the event timestamp by 1 second to avoid timestamp collision. working_event.timestamp = working_event.timestamp + datetime.timedelta(seconds=1) result = misp.update_event(working_event) # Send the result to the docker container's stdout. print(result) else: # If the bot org is not the same as the event we're trying to modify then we need to use an extension. # Let's check if the bot already created an extension event for this event. new_event = True if "extensionEvents" in working_event: for k, event_extension in working_event["extensionEvents"].items(): # Checking if the org IDs match. if event_extension["Orgc"]["id"] == bot_org_id: # Check if the extension has the event name we expect this bot to create. if event_extension["info"] == "Covid Slack: Disinfo Bot": # Get the event and add the object we created. extension_event = misp.get_event(event_extension["id"], pythonify=True) for each_object in misp_objects: extension_event.Object.append(each_object) working_event.timestamp = working_event.timestamp + datetime.timedelta(seconds=1) result = misp.update_event(extension_event) # Send the result to the docker container's stdout. print(result) # Set new event false so we don't create a new event extension in the next step. new_event = False # If the event isn't owned by the bot org , and no event extension exists, we need to create a new event. # This event will be added to the parent as an event extension. if new_event: # Create a new empty event. extended_event = MISPEvent() # Set self.info to row Title extended_event.info = "Covid Slack: Disinfo Bot" # extends_uuid tells us the event we are extending with this new event. extended_event.extends_uuid = working_event["id"] for tracking_id_object in misp_objects: extended_event.Object.append(tracking_id_object) result = misp.add_event(extended_event, pythonify=True) print(result) # Build slack response. # This is the data posted back to the user in Slack. # Change 'text'['text'] to fit your bot name, etc. # 'response_type': 'in_channel' posts the response in channel. Remove response_type to make response private. response = {'blocks': [], 'response_type': 'in_channel'} response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': 'BuiltWith Tracking IDs: {}'.format(domain) } }) # Build the message line by line. # Requires explicit use of line break. message = "" for tracking_id, domains in tracking_ids.items(): message += f'Tracking ID: {tracking_id}\n' message += f'Relationships: {str(len(domains["hostname"]))}\n' # Add Slack message as block. response['blocks'].append({ 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': message } }) # Finally, return the response to the user. requests.post(response_url, json=response) except Exception as e: # Return the error to the user and log to the container. logger.exception(f"Error: {e}") message = f"Error: {e}" resp = build_response(message, False) requests.post(response_url, json=resp)
if vt_obj: event.add_object(vt_obj) if self.urlscan.available: urlscan_attribute = self.__misp_add_urlscan_to_event( capture_uuid, visibility='unlisted' if (cache and cache.no_index) else 'public') if urlscan_attribute: event.add_attribute(**urlscan_attribute) if with_parent and cache.parent: parent = self.misp_export(cache.parent, with_parent) if isinstance(parent, dict): # Something bad happened return parent event.extends_uuid = parent[-1].uuid parent.append(event) return parent return [event] def get_misp_occurrences(self, capture_uuid: str, /) -> Optional[Dict[str, Set[str]]]: if not self.misp.available: return None try: ct = self.get_crawled_tree(capture_uuid) except LookylooException: self.logger.warning(f'Unable to get the modules responses unless the tree ({capture_uuid}) is cached.') return None nodes_to_lookup = ct.root_hartree.rendered_node.get_ancestors() + [ct.root_hartree.rendered_node] to_return: Dict[str, Set[str]] = defaultdict(set)