예제 #1
0
    def create_hive_case(self, customer, data):
        create_hive_bool = self.get_hive_cases(customer, data)

        # Returns if case already merged.
        if not create_hive_bool:
            return False

        # Baseline for creating a case
        title = ("%s: %s - %s" % (customer.name, str(data["id"]), data["description"]))
	static_task = "Why did it happen? Check rule.",
        task_data = self.get_hive_task_data(data)
        tasks = [
            CaseTask(title=static_task)
        ]
        if task_data:
            for item in task_data:
                tasks.append(CaseTask(title=item))

        # Creates a case object
        case = Case(title=title, tlp=0, flag=False, tags=data["categories"], \
                description=data["description"], tasks=tasks)

        # Creates the actual case based on prior info
        ret = self.hive.create_case(case)

        if ret.ok:
            # FIX, datatype is static
            self.add_observable_data(ret.json()["id"], create_hive_bool, \
                "ip", data, data["categories"])
            return True 

        return False
    def run(self, case_id, task_name, status):
        api = TheHiveApiExtended(self.config['thehive_url'], self.config['thehive_api_key'])

        response = api.get_case_tasks(case_id, query=Eq('title', task_name))
        if response.status_code == 200:
            tasks = response.json()
            if len(tasks) == 1:
                task_id = tasks[0]['id']
            else:
                raise ValueError('[ChangeStatusTaskByNameAction]: task not found')
        else:
            raise ValueError('[ChangeStatusTaskByNameAction]: tasks status_code %d'
                 % response.status_code)

        response = api.get_task(task_id)
        if response.status_code == 200:
            task_object = response.json()
            task = CaseTask(json=task_object)
            task.id = task_id
            task.status = status
            task.owner = self.config['thehive_bot_username']
            api.update_case_task(task)
        else:
            raise ValueError('[ChangeStatusTaskByNameAction]: status_code %d'
                 % response.status_code)

        return True
예제 #3
0
    def run(self, task_id, status):
        api = TheHiveApiExtended(self.config['thehive_url'], self.config['thehive_api_key'])
        response = api.get_task(task_id)
        if response.status_code == 200:
            task_object = response.json()
            task = CaseTask(json=task_object)
            task.id = task_id
            task.status = status
            task.owner = self.config['thehive_bot_username']
            api.update_case_task(task)
        else:
            raise ValueError('[ChangeStatusTaskAction]: status_code %d' % response.status_code)

        return True
예제 #4
0
    def __init__(self, event, tenant):

        # Case attributes
        user = event['user']
        nature = event['nature']
        case_name = event['case']['name']
        case_id = event['case']['id']
        case_url = event['case']['url']
        case_tags = ['McAfee Investigator', case_id, nature]

        # Task attributes
        task_owner = tenant.hive_user
        # task_start_date = datetime.datetime.now().strftime("%d-%m-%Y %H:%M")
        task_start_date = int(time.time()) * 1000
        task_description = "Autogenerated task to track MI case events"
        tasks = [
            CaseTask(title='MI - analytics investigation',
                     status='InProgress',
                     owner=task_owner,
                     startDate=task_start_date,
                     description=task_description),
            CaseTask(title='MI - system events',
                     status='InProgress',
                     owner=task_owner,
                     startDate=task_start_date,
                     description=task_description),
            CaseTask(title='MI - user events',
                     status='Waiting',
                     description="Auto generated task to track MI user events")
        ]

        # Prepare the custom fields (values are searchable)
        customFields = CustomFieldHelper()\
            .add_boolean('MI-autogenerated', True)\
            .add_string('MI-caseid', case_id)\
            .add_string('MI-user', user)\
            .add_string('MI-nature', nature)\
            .build()

        case = Case(title=case_name,
                    tlp=0,
                    flag=False,
                    description="For additional info see " +
                    self.get_case_ui_url(case_url),
                    tags=case_tags,
                    tasks=tasks,
                    customFields=customFields)

        self.case = case
예제 #5
0
    def run(self, params={}):

        client = self.connection.client

        self.logger.info("Input: %s", params)
        task = CaseTask(
            title=params.get("task").get("title", None),
            description=params.get("task").get("description", None),
            flag=params.get("task").get("flag", False),
            owner=params.get("task").get("owner", None),
            status=params.get("task").get("status", None),
            startDate=params.get("task").get("startDate", None),
        )

        case = Case(
            title=params.get("title", None),
            tlp=params.get("tlp", 2),
            flag=params.get("flag", False),
            tags=params.get("tags", []),
            description=params.get("description", None),
            tasks=[task],
            customFields=params.get("customFields", None),
        )

        try:
            new_case = client.create_case(case)
            new_case.raise_for_status()
        except requests.exceptions.HTTPError:
            self.logger.error(new_case.json())
            raise
        except:
            self.logger.error("Failed to create case")
            raise

        return {"case": new_case.json()}
예제 #6
0
    def run(self, params={}):

        client = self.connection.client

        self.logger.info('Input: %s', params)
        task = CaseTask(title=params.get('task').get('title', None),
                        description=params.get('task').get(
                            'description', None),
                        flag=params.get('task').get('flag', False),
                        owner=params.get('task').get('owner', None),
                        status=params.get('task').get('status', None),
                        startDate=params.get('task').get('startDate', None))

        case = Case(title=params.get('title', None),
                    tlp=params.get('tlp', 2),
                    flag=params.get('flag', False),
                    tags=params.get('tags', []),
                    description=params.get('description', None),
                    tasks=[task],
                    customFields=params.get('customFields', None))

        try:
            new_case = client.create_case(case)
            new_case.raise_for_status()
        except requests.exceptions.HTTPError:
            self.logger.error(new_case.json())
            raise
        except:
            self.logger.error('Failed to create case')
            raise

        return {'case': new_case.json()}
예제 #7
0
    async def create_case_task(self, case_id, url, api_key, data=None):

        self.logger.info(f'Creating task for {case_id} in TheHive...')

        if not url.startswith("http"):
            url = f"http://{url}"

        api = TheHiveApi(url, api_key)

        results = {}
        for item in data:
            try:
                title = item["title"]
                description = item["description"]
                startDate = time.time_ns() // 1000000
                task = CaseTask(title=title, description=description, startDate=startDate)

                r = api.create_case_task(case_id, task)

                if r.status_code == 201:
                    results[title] = r.json()
                else:
                    raise IOError(r.text)
            except Exception as e:
                self.console_logger.info(f"Failed to create task with input {item} because: {e}")

        return results
예제 #8
0
def sendtoHIVE(title, description, domain):

    tasks = [
        CaseTask(title='Tracking'),
        CaseTask(title='Communication'),
        CaseTask(title='Investigation', status='Waiting', flag=True)
    ]

    # Prepare the custom fields
    customFields = CustomFieldHelper()\
        .add_boolean('booleanField', True)\
        .add_string('businessImpact', 'HIGH')\
        .add_date('occurDate', int(time.time())*1000)\
        .add_number('cvss', 9)\
        .build()

    case = Case(title=title,
                tlp=3,
                flag=True,
                tags=['wordpress', domain],
                description=description,
                tasks=tasks,
                customFields=customFields)

    # Create the case
    print('Create Case')
    print('-----------------------------')
    id = None
    response = api.create_case(case)
    if response.status_code == 201:
        print(json.dumps(response.json(), indent=4, sort_keys=True))
        print('')
        id = response.json()['id']
    else:
        print('ko: {}/{}'.format(response.status_code, response.text))
        sys.exit(0)

    # Get all the details of the created case
    print('Get created case {}'.format(id))
    print('-----------------------------')
    response = api.get_case(id)
    if response.status_code == requests.codes.ok:
        print(json.dumps(response.json(), indent=4, sort_keys=True))
        print('')
    else:
        print('ko: {}/{}'.format(response.status_code, response.text))
예제 #9
0
    def craftCommTask(self):
        self.logger.info('%s.craftCommTask starts', __name__)

        commTask = CaseTask(title='Communication',
                            status='InProgress',
                            owner='synapse')

        return commTask
예제 #10
0
파일: app.py 프로젝트: yongquanf/WALKOFF
    async def update_case_task(self,
                               url,
                               api_key,
                               task_id,
                               title=None,
                               description=None,
                               status=None,
                               flag=None):
        self.logger.info(f'Updating task {task_id} in TheHive...')

        if not url.startswith("http"):
            url = f"http://{url}"

        api = TheHiveApi(url, api_key)
        task = CaseTask(**api.get_case_task(task_id).json())
        task.id = task_id

        if title:
            task.title = title
        if description:
            task.description = description
        if status:
            task.status = status
        if flag is not None:
            task.flag = flag
        r = api.update_case_task(task)

        if r.status_code == 200:
            return r.json()
        else:
            raise IOError(r.text)
예제 #11
0
    def run(self, task_id):
        api = TheHiveApi(self.config['thehive_url'],
                         self.config['thehive_api_key'])
        response = api.find_tasks(query=Eq('_id', task_id))
        if response.status_code == 200:
            tasks = response.json()
            if len(tasks) == 1:
                task = CaseTask(json=tasks[0])
                task.id = task_id
                task.status = 'InProgress'
                task.owner = self.config['thehive_bot_username']
                api.update_case_task(task)
            else:
                raise ValueError('[TakeTaskAction]: no tasks with this id')
        else:
            raise ValueError('[TakeTaskAction]: status_code %d' %
                             response.status_code)

        return True
예제 #12
0
    def addTask(self, caseId):

        response = self.api.create_case_task(
            caseId,
            CaseTask(title='Autogenerated Report',
                     startDate=int(time.time()) * 1000))
        if response.status_code == 201:
            return (json.dumps(response.json(), indent=4, sort_keys=True))

        else:
            self.error('ko: {}/{}'.format(response.status_code, response.text))
예제 #13
0
 def do_newtask(self, *_):
     '''Create a new task within this case'''
     print("Let's create a new task within this case! The next few steps \
           will request some data from you: ")
     nt_title = input("Task Title: ")
     nt_description = input("Task Description: ")
     new_task = CaseTask(title=nt_title, description=nt_description)
     api = config.get_api()
     resp = api.create_case_task(self.case_id, new_task)
     if resp.status_code == 201:
         print("Successfully created task {0} with the case {1}.".format(
             nt_title, self.case_name))
예제 #14
0
    def run(self, params={}):

        client = self.connection.client

        self.logger.info(params)
        task = CaseTask(
            title=params.get("task").get("title", None),
            description=params.get("task").get("description", None),
            flag=params.get("task").get("flag", False),
            owner=params.get("task").get("owner", None),
            status=params.get("task").get("status", None),
        )

        try:
            task = client.create_case_task(params.get("id"), task)
            task.raise_for_status()
        except requests.exceptions.HTTPError:
            self.logger.error(task.json())
            raise
        except:
            self.logger.error("Failed to create task")
            raise

        d = task.json()
        # If API returns None, manually do what the library does elsewhere
        # https://github.com/CERT-BDF/TheHive4py/blob/master/thehive4py/models.py#L44
        if "startDate" in d:
            if isinstance(d["startDate"], type(None)):
                d["startDate"] = int(time.time()) * 1000

        return {"case": d}
예제 #15
0
    def run(self, job_id, status):
        task_id = self.action_service.get_value(
            name='thehive_job_{}'.format(job_id), local=False)

        api = TheHiveApiExtended(self.config['thehive_url'],
                                 self.config['thehive_api_key'])
        response = api.get_task(task_id)
        if response.status_code == 200:
            task_object = response.json()
            task = CaseTask(json=task_object)
            task.id = task_id
            task.status = status
            task.owner = self.config['thehive_bot_username']
            api.update_case_task(task)
            if status == 'Completed':
                self.action_service.delete_value(
                    name='thehive_job_{}'.format(job_id), local=False)
        else:
            raise ValueError(
                '[ChangeStatusTaskByJobIdAction]: status_code %d' %
                response.status_code)

        return True
    def create_case(self,
                    title,
                    tasks=None,
                    tlp=TLP.AMBER,
                    pap=PAP.AMBER,
                    severity=HiveSeverity.MEDIUM,
                    additional_fields=None,
                    additional_tags=None,
                    flag=False,
                    description='N/A'):

        case_tags = self.case_tags.copy()
        if additional_tags is not None:
            for additional_tag in additional_tags:
                case_tags.append(additional_tag)

        custom_fields_helper = CustomFieldHelper()
        if additional_fields is not None:
            for field in additional_fields:
                custom_fields_helper.add_string(field['name'], field['value'])
        custom_fields = custom_fields_helper.build()

        new_tasks = list()
        if tasks is not None:
            for task in tasks:
                new_tasks.append(CaseTask(title=task))

        hive_case = Case(title=title,
                         tlp=tlp.value,
                         pap=pap.value,
                         description=description,
                         tags=case_tags,
                         severity=severity.value,
                         flag=flag,
                         customFields=custom_fields,
                         tasks=new_tasks)

        response = self.api.create_case(hive_case)
        if response.status_code == 201:
            print('Caso Creada Exitosamente')
            print(json.dumps(response.json(), indent=4, sort_keys=True))
        else:
            print('Error')
            print(response.text)

        return response.json()
def playbook_mapper(rules_list, case_num):
    tasks_dict = (chk_mapping(rules_list))
    order_by_count = 0
    for k, v in tasks_dict.items():
        for items in v:
            task = CaseTask(group='{}'.format(k),
                            title='{}'.format(items),
                            order=order_by_count)
            r = hive_api.create_case_task(
                get_case_by_casenum(case_num)['id'], task)
            print(r.content)
            order_by_count += 1


# #Usage: Use a list of rule-groups/attack vectors etc..to map related tasks into the target case #.
# Exp:
# rule_list = ['Initial Access', 'Drive-by Compromise']
# playbook_mapper(rule_list, 3)
예제 #18
0
def main(api):
    i = 0
    while i < (currentNum):
        check = True
        string = searchCaseByDescription(threats.json['data'][i]['id'])
        if string == None and check == True:
            threat = createKeys(threats.json['data'][i], i)
            parsed = createAlertDescription(threat, i)
            case = Case(title=threats.json['data'][i]['description'],
                        tlp=0,
                        pap=0,
                        severity=1,
                        flag=False,
                        tags=[
                            'Sentinel One',
                            threats.json['data'][i]['classification'],
                            threats.json['data'][i]['agentOsType'],
                        ],
                        description=parsed,
                        tasks=[
                            CaseTask(
                                title='Communication',
                                description='Auto Imported Sentinel One Alert',
                                owner='sentinelone',
                                group='default',
                                createdAt=time.time())
                        ],
                        status='Open',
                        user='******',
                        createdAt=threats.json['data'][i]['createdDate'])
            response = api.create_case(case)
            postUpdate(searchCaseByDescription(threats.json['data'][i]['id']),
                       i)
            if response.status_code == 201:
                logging.info(
                    json.dumps(response.json(), indent=4, sort_keys=True))
                logging.info('')
                id = response.json()['id']
            else:
                print(check)
                logging.error('ko: {}/{}'.format(response.status_code,
                                                 response.text))
        i += 1
예제 #19
0
def submitTheHive(message):
    '''
    Create a new case in TheHive based on the email
    Return 'TRUE' is successfully processed otherwise 'FALSE'
    '''

    # Decode email
    msg = email.message_from_bytes(message)  # gets full content of the email
    decode = email.header.decode_header(msg['From'])[0]
    fromField = str(decode[0])
    decode = email.header.decode_header(msg['Subject'])[0]
    subjectField = str(decode[0])
    if args.verbose:
        print("[INFO] From: %s Subject: %s" % (fromField, subjectField))
    attachments = []
    observables = []
    body = ''
    bodyMessage = ''
    for part in msg.walk():
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True).decode()
            bodyMessage += body
            observables = searchObservables(
                body, observables
            )  # searches the body of the email for supplied observables
        elif part.get_content_type(
        ) == "text/html":  # if email is html based will search throuh html source code
            if args.verbose:
                print("[INFO] Searching for observable in HTML code")
            html = part.get_payload(decode=True).decode()
            observables = searchObservables(html, observables)
        elif part.get_content_type(
        ) == "application/vnd.ms-excel":  #ONLY WORKS FOR .CSV
            body = part.get_payload(decode=True).decode('UTF-8')
            observables = searchObservables(body, observables)
        else:
            # Extract MIME parts
            filename = part.get_filename()
            mimetype = part.get_content_type()
            if filename and mimetype:
                if mimetype in config['caseFiles'] or not config['caseFiles']:
                    print("[INFO] Found attachment: %s (%s)" %
                          (filename, mimetype))
                    # Decode the attachment and save it in a temporary file
                    charset = part.get_content_charset()
                    if charset is None:
                        charset = chardet.detect(bytes(part))['encoding']
                    fd, path = tempfile.mkstemp(prefix=slugify(filename) + "_")
                    try:
                        with os.fdopen(fd, 'w+b') as tmp:
                            tmp.write(part.get_payload(decode=1))
                        attachments.append(path)
                    except OSError as e:
                        print("[ERROR] Cannot dump attachment to %s: %s" %
                              (path, e.errno))
                        return False

    api = TheHiveApi(config['thehiveURL'], config['thehiveUser'],
                     config['thehivePassword'], {
                         'http': '',
                         'https': ''
                     })

    # if '[ALERT]' in subjectField:
    if re.match(config['alertKeywords'], subjectField, flags=0):
        #
        # Add observables found in the mail body
        #
        artifacts = []
        if config['thehiveObservables'] and len(observables) > 0:
            print("t1")
            for o in observables:
                print("t2")
                artifacts.append(
                    AlertArtifact(dataType=o['type'], data=o['value']))

        #
        # Prepare tags - add alert keywords found to the list of tags
        #
        tags = config['alertTags']
        match = re.findall(config['alertKeywords'], subjectField)
        for m in match:
            tags.append(m)

        #
        # Prepare the alert
        #
        sourceRef = str(uuid.uuid4())[0:6]
        alert = Alert(
            title=subjectField.replace('[ALERT]', ''),
            tlp=int(
                config['alertTLP']
            ),  #setting it blank since custom template allows default color, set it back to tlp = int for conf value
            tags=tags,
            description=body,
            type='external',
            source=fromField,
            sourceRef=sourceRef,
            artifacts=artifacts)

        # Create the Alert
        id = None
        response = api.create_alert(alert)
        if response.status_code == 201:
            if args.verbose:
                print('[INFO] Created alert %s' % response.json()['sourceRef'])
        else:
            print('[ERROR] Cannot create alert: %s (%s)' %
                  (response.status_code, response.text))
            return False

    else:
        # Prepare the sample case
        tasks = []
        for task in config['caseTasks']:
            tasks.append(CaseTask(title=task))

        # Prepare the custom fields
        customFields = CustomFieldHelper() \
            .add_string('from', fromField) \
            .add_string('attachment', str(attachments)) \
            .build()

        # If a case template is specified, use it instead of the tasks

        m = 1
        if m == 1:
            templates = []
            for task in config['caseTemplates']:
                templates.append(task)
            temptouse = config['caseTemplate']
            descrip = re.compile('-"(.+)"')
            name = re.compile('(.+)-"')
            for x in templates:
                z = descrip.search(x)
                tempVar = name.search(x)
                searchVar = z.group(1)
                tempVar = tempVar.group(1)

                if searchVar in subjectField:
                    print(
                        x
                    )  #if 2 template names in subject, take the latest defined
                    temptouse = tempVar
                    print("TEMPLATE", temptouse)
            if body:
                testerVar = False
                print("body")
                try:
                    albert = re.compile('Albert Incident #: (\d+)')
                    m = albert.search(body)
                    albertId = m.group(1)
                    print(albertId)
                    customFields = CustomFieldHelper() \
                        .add_string('from', fromField) \
                        .add_string('attachment', str(attachments)) \
                        .add_string('albertId', albertId) \
                        .build()
                    print(customFields)
                except:
                    print("albert id doesnt exist")

                if "Update" in subjectField:  #update code
                    testerVar = True
                    print("UPDATE")
                    #INTIAL
                    try:
                        findBodyInfo = re.compile('---((?:.+[\r\n]+)+)---')
                    except:
                        print(
                            "Unable to update, unable to find two '---'s, exiting.."
                        )
                        sys.exit(0)
                    m = findBodyInfo.search(body)
                    bigGroup = m.group(1)
                    caseId = parseBody("Case Id", bigGroup)
                    print("caseid", caseId)
                    try:
                        caseId = int(caseId)

                    except:
                        print("invalid case id")
                    updateACase(caseId, bigGroup, fromField, attachments)

                    id = None
                    if testerVar == True:
                        print("g")
                        sys.exit(0)
                #end update code

                caseTags = []
                for tag in config['caseTags']:
                    descripFound = descrip.search(tag)
                    nameFound = name.search(tag)
                    descripFound = descripFound.group(1)
                    nameFound = nameFound.group(1)
                    if descripFound == 'always':
                        caseTags.append(nameFound)
                    elif descripFound in bodyMessage:
                        caseTags.append(nameFound)

            try:

                #
                # Add observables found in the mail body
                #
                artifacts = []
                if config['thehiveObservables'] and len(observables) > 0:

                    for o in observables:

                        artifacts.append(
                            AlertArtifact(dataType=o['type'], data=o['value']))

                #
                # Prepare tags - add alert keywords found to the list of tags
                #
                tags = config['alertTags']
                match = re.findall(config['alertKeywords'], subjectField)
                for m in match:
                    tags.append(m)

                #
                # Prepare the alert
                #
                sourceRef = str(uuid.uuid4())[0:6]

                alert = Alert(
                    title=subjectField,
                    tlp=int(
                        config['alertTLP']
                    ),  #setting it blank since custom template allows default color, set it back to tlp = int for conf value
                    tags=caseTags,
                    description=body,
                    type='external',
                    source=fromField,
                    sourceRef=sourceRef,
                    customFields=customFields,
                    severity=None,
                    artifacts=artifacts)

            except FileExistsError:
                print(
                    "Error with creating alert, wrong template name or tags?")
        else:
            print("")
        # Create the alert
        response = api.create_alert(alert)
        print("Alert being created..")
        if response.status_code == 201:
            newID = response.json()['id']
            if args.verbose:
                print('[INFO] Created alert %s' % response.json()['caseId'])
            if len(attachments) > 0:
                for path in attachments:
                    observable = CaseObservable(
                        dataType='file',
                        data=[path],
                        tlp=int(config['caseTLP']),
                        ioc=False,
                        tags=config['caseTags'],
                        message='Found as email attachment')

                    response = api.create_case_observable(newID, observable)
                    if response.status_code == 201:
                        if args.verbose:
                            print('[INFO] Added observable %s to case ID %s' %
                                  (path, newID))
                            os.unlink(path)
                    else:
                        print('[WARNING] Cannot add observable: %s - %s (%s)' %
                              (path, response.status_code, response.text))
            #
            # Add observables found in the mail body
            #
            if config['thehiveObservables'] and len(observables) > 0:
                for o in observables:
                    observable = CaseObservable(
                        dataType=o['type'],
                        data=o['value'],
                        tlp=int(config['caseTLP']),
                        ioc=False,
                        tags=caseTags,  #switched to custom tags
                        message='Found in the email body')
                    response = api.create_case_observable(newID, observable)
                    if response.status_code == 201:
                        if args.verbose:
                            print(
                                '[INFO] Added observable %s: %s to case ID %s'
                                % (o['type'], o['value'], newID))
                    else:
                        print(
                            '[WARNING] Cannot add observable %s: %s - %s (%s)'
                            % (o['type'], o['value'], response.status_code,
                               response.text))
        else:
            print('[ERROR] Cannot create case: %s (%s)' %
                  (response.status_code, response.text))
            return False
    return True
예제 #20
0
def submitTheHive(message):
    '''Create a new case in TheHive based on the email'''

    # Decode email
    msg = email.message_from_bytes(message)
    decode = email.header.decode_header(msg['From'])[0]
    fromField = str(decode[0])
    decode = email.header.decode_header(msg['Subject'])[0]
    subjectField = str(decode[0])
    if args.verbose:
        print("[INFO] From: %s Subject: %s" % (fromField, subjectField))
    attachments = []
    body = ''
    for part in msg.walk():
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True).decode()
        else:
            # Extract MIME parts
            filename = part.get_filename()
            mimetype = part.get_content_type()
            if filename and mimetype:
                if mimetype in config['caseFiles'] or not config['caseFiles']:
                    print("[INFO] Found attachment: %s (%s)" %
                          (filename, mimetype))
                    # Decode the attachment and save it in a temporary file
                    charset = part.get_content_charset()
                    if charset is None:
                        charset = chardet.detect(bytes(part))['encoding']
                    fd, path = tempfile.mkstemp(prefix=slugify(filename) + "_")
                    try:
                        with os.fdopen(fd, 'w+b') as tmp:
                            tmp.write(part.get_payload(decode=1))
                        attachments.append(path)
                    except OSError as e:
                        print("[ERROR] Cannot dump attachment to %s: %s" %
                              (path, e.errno))

    api = TheHiveApi(config['thehiveURL'], config['thehiveUser'],
                     config['thehivePassword'], {
                         'http': '',
                         'https': ''
                     })

    if '[ALERT]' in subjectField:
        # Prepare the alert
        sourceRef = str(uuid.uuid4())[0:6]
        alert = Alert(title=subjectField.replace('[ALERT]', ''),
                      tlp=int(config['alertTLP']),
                      tags=config['alertTags'],
                      description=body,
                      type='external',
                      source=fromField,
                      sourceRef=sourceRef)

        # Create the Alert
        id = None
        response = api.create_alert(alert)
        if response.status_code == 201:
            if args.verbose:
                print('[INFO] Created alert %s' % response.json()['sourceRef'])
        else:
            print('[ERROR] Cannot create alert: %s (%s)' %
                  (response.status_code, response.text))
            sys.exit(0)

    else:
        # Prepare the sample case
        tasks = []
        for task in config['caseTasks']:
            tasks.append(CaseTask(title=task))

        # Prepare the custom fields
        customFields = CustomFieldHelper()\
            .add_string('from', fromField)\
            .add_string('attachment', str(attachments))\
            .build()

        case = Case(title=subjectField,
                    tlp=int(config['caseTLP']),
                    flag=False,
                    tags=config['caseTags'],
                    description=body,
                    tasks=tasks,
                    customFields=customFields)

        # Create the case
        id = None
        response = api.create_case(case)
        if response.status_code == 201:
            newID = response.json()['id']
            if args.verbose:
                print('[INFO] Created case %s' % response.json()['caseId'])
            if len(attachments) > 0:
                for path in attachments:
                    observable = CaseObservable(
                        dataType='file',
                        data=[path],
                        tlp=int(config['caseTLP']),
                        ioc=False,
                        tags=config['caseTags'],
                        message='Created by imap2thehive.py')
                    response = api.create_case_observable(newID, observable)
                    if response.status_code == 201:
                        if args.verbose:
                            print('[INFO] Added observable %s to case ID %s' %
                                  (path, newID))
                            os.unlink(path)
                    else:
                        print('[ERROR] Cannot add observable: %s - %s (%s)' %
                              (path, response.status_code, response.text))
                        sys.exit(0)
        else:
            print('[ERROR] Cannot create case: %s (%s)' %
                  (response.status_code, response.text))
            sys.exit(0)
    return
예제 #21
0
def submitTheHive(message):
    '''
    Create a new case in TheHive based on the email
    Return 'TRUE' is successfully processed otherwise 'FALSE'
    '''

    global log

    # Decode email
    msg = email.message_from_bytes(message)
    decode = email.header.decode_header(msg['From'])[0]
    if decode[1] is not None:
        fromField = decode[0].decode(decode[1])
    else:
        fromField = str(decode[0])
    decode = email.header.decode_header(msg['Subject'])[0]
    if decode[1] is not None:
        subjectField = decode[0].decode(decode[1])
    else:
        subjectField = str(decode[0])
    log.info("From: %s Subject: %s" % (fromField, subjectField))

    attachments = []
    observables = []

    # Extract SMTP headers and search for observables
    parser = HeaderParser()
    headers = parser.parsestr(msg.as_string())
    headers_string = ''
    i = 0
    while i < len(headers.keys()):
        headers_string = headers_string + headers.keys(
        )[i] + ': ' + headers.values()[i] + '\n'
        i += 1
    # Temporary disabled
    # observables = searchObservables(headers_string, observables)

    body = ''
    for part in msg.walk():
        if part.get_content_type() == "text/plain":
            try:
                body = part.get_payload(decode=True).decode()
            except UnicodeDecodeError:
                body = part.get_payload(decode=True).decode('ISO-8859-1')
            observables.extend(searchObservables(body, observables))
        elif part.get_content_type() == "text/html":
            try:
                html = part.get_payload(decode=True).decode()
            except UnicodeDecodeError:
                html = part.get_payload(decode=True).decode('ISO-8859-1')
            observables.extend(searchObservables(html, observables))
        else:
            # Extract MIME parts
            filename = part.get_filename()
            mimetype = part.get_content_type()
            if filename and mimetype:
                if mimetype in config['caseFiles'] or not config['caseFiles']:
                    log.info("Found attachment: %s (%s)" %
                             (filename, mimetype))
                    # Decode the attachment and save it in a temporary file
                    charset = part.get_content_charset()
                    if charset is None:
                        charset = chardet.detect(bytes(part))['encoding']
                    fd, path = tempfile.mkstemp(prefix=slugify(filename) + "_")
                    try:
                        with os.fdopen(fd, 'w+b') as tmp:
                            tmp.write(part.get_payload(decode=1))
                        attachments.append(path)
                    except OSerror as e:
                        log.error("Cannot dump attachment to %s: %s" %
                                  (path, e.errno))
                        return False

    # Cleanup observables (remove duplicates)
    new_observables = []
    for o in observables:
        if not {'type': o['type'], 'value': o['value']} in new_observables:
            # Is the observable whitelisted?
            if isWhitelisted(o['value']):
                log.debug('Skipping whitelisted observable: %s' % o['value'])
            else:
                new_observables.append({
                    'type': o['type'],
                    'value': o['value']
                })
                log.debug('Found observable %s: %s' % (o['type'], o['value']))
        else:
            log.info('Ignoring duplicate observable: %s' % o['value'])
    log.info("Removed duplicate observables: %d -> %d" %
             (len(observables), len(new_observables)))
    observables = new_observables

    if config['thehiveAuthMethod'] == 'APIKey':
        api = TheHiveApi(config['thehiveURL'], config['thehiveAPIKey'], None, {
            'http': '',
            'https': ''
        })
    else:
        api = TheHiveApi(config['thehiveURL'], config['thehiveUser'],
                         config['thehivePassword'], {
                             'http': '',
                             'https': ''
                         })

    # Search for interesting keywords in subjectField:
    log.debug("Searching for %s in '%s'" %
              (config['alertKeywords'], subjectField))
    if re.match(config['alertKeywords'], subjectField, flags=0):
        #
        # Add observables found in the mail body
        #
        artifacts = []
        if config['thehiveObservables'] and len(observables) > 0:
            for o in observables:
                artifacts.append(
                    AlertArtifact(dataType=o['type'], data=o['value']))

        #
        # Prepare tags - add alert keywords found to the list of tags
        #
        tags = list(config['alertTags'])
        match = re.findall(config['alertKeywords'], subjectField)
        for m in match:
            tags.append(m)

        #
        # Prepare the alert
        #
        sourceRef = str(uuid.uuid4())[0:6]
        alert = Alert(title=subjectField.replace('[ALERT]', ''),
                      tlp=int(config['alertTLP']),
                      tags=tags,
                      description=body,
                      type='external',
                      source=fromField,
                      sourceRef=sourceRef,
                      artifacts=artifacts)

        # Create the Alert
        id = None
        response = api.create_alert(alert)
        if response.status_code == 201:
            log.info('Created alert %s' % response.json()['sourceRef'])
        else:
            log.error('Cannot create alert: %s (%s)' %
                      (response.status_code, response.text))
            return False

    else:
        # Prepare the sample case
        tasks = []
        for task in config['caseTasks']:
            tasks.append(CaseTask(title=task))

        # Prepare the custom fields
        customFields = CustomFieldHelper()\
            .add_string('from', fromField)\
            .add_string('attachment', str(attachments))\
            .build()

        # If a case template is specified, use it instead of the tasks
        if len(config['caseTemplate']) > 0:
            case = Case(title=subjectField,
                        tlp=int(config['caseTLP']),
                        flag=False,
                        tags=config['caseTags'],
                        description=body,
                        template=config['caseTemplate'],
                        customFields=customFields)
        else:
예제 #22
0
import time
from thehive4py.api import TheHiveApi
from thehive4py.models import Case, CustomFieldHelper, CaseTask, CaseObservable

#To use this script correctly please configure the following lines
file_id = "</path/to/id_file.txt>"
api = TheHiveApi('<URL_THE_HIVE>', '<THE_HIVE_API_KEY>')
warnings.filterwarnings('ignore')
url = 'https://<QRadar_IP_address>/api/siem/offenses?fields=id%2Cstatus%2Cdescription%2Coffense_type%2Coffense_source%2Cmagnitude%2Csource_network%2Cdestination_networks%2Cassigned_to%2Cstart_time%2Cevent_count'
headers = {'accept': 'application/json', 'SEC': '<QRADAR_API_KEY>', 'Version': '9.0'}



#If you're using JIRA as ticketing platform in the task 'Communication' you can add the URL of your JIRA, else delete the description parameter.
tasks = [
    CaseTask(title='Tracking'),
    CaseTask(title='Communication', description= '**[Ticket creation](https://PATH/TO/JIRA/CreateIssue!default.jspa)**'),
    CaseTask(title='Investigation', status='Waiting', flag=True)
]

def OffensesRequest():
#If you're using a selfsigned certificate on your QRadar instance you have to use "verify=false" parameter:
response_1 = requests.get(url,headers=headers,verify=False)
if (response_1.status_code) == 200:
    data = response_1.json()
    last_id = (str((data[0]['id'])))
    
    with open(file_id) as f:
        data_file = f.readlines()
        if data_file == []:
            last_line = int(last_id)-1
예제 #23
0
    custom_fields = CustomFieldHelper()
    custom_fields.add_number('qradar_id', offense_id)
    custom_fields.add_string('offense_source', offense_source)
    custom_fields.build()

    tlp = offense_severity_mapper(offense_magnitude)['sev']

    # #Case - Offense summary md.
    build_desc = """|Offense Summary:|\n|---|\n|Offense Description: {}|\n|Source NW: {}|\n|Destination NW: {}|\n|Source IPs: {}|\n|Local Destination IPs: {}|\n|Remote Destination IPs: {}|\n|Usernames: {}|\n---\nLink to the Offense: {}""".format(
        offense_desc, offense_src_nw, offense_dst_nw, source_address_list,
        local_dest_list, remote_dest_list, username_list, offense_link)

    # #Some sample tasks-response actions for posting in the case. Customize per your reqs.
    # #TODO: You can also utilize - thehive-playbook-creator - for dynamic task/playbook assignment using your QRadar Rule groups.
    tasks = [
        CaseTask(title='PB:- Phase:Identification'),
        CaseTask(title='PB: - Phase:Remediation'),
        CaseTask(title='PB: - Phase:Lessons Learned',
                 status='Waiting',
                 flag=True)
    ]

    #Build TheHive Case with custom fields
    thehive_case = Case(title=offense_desc,
                        tlp=tlp,
                        flag=True,
                        tags=['offense', 'qradar', offense_type_name],
                        description=build_desc,
                        customFields=custom_fields.fields,
                        tasks=tasks)
예제 #24
0
from __future__ import print_function
from __future__ import unicode_literals

import requests
import sys
import json
import time
from thehive4py.api import TheHiveApi
from thehive4py.models import Case, CaseTask, CustomFieldHelper

api = TheHiveApi('http://127.0.0.1:9000', '**YOUR_API_KEY**')

# Prepare the sample case
tasks = [
    CaseTask(title='Identify'),
    CaseTask(title='Contain'),
    CaseTask(title='Investigate'),
    CaseTask(title='Eradicate'),
    CaseTask(title='Recovery'),
    CaseTask(title='Lessons Learned', status='Waiting', flag=True)
]

# Prepare the custom fields
customFields = CustomFieldHelper()\
    .add_boolean('booleanField', True)\
    .add_string('businessImpact', 'HIGH')\
    .add_date('occurDate', int(time.time())*1000)\
    .add_number('cvss', 9)\
    .build()
예제 #25
0
 def craftTask(self, **attributes):
     self.log.info('%s.craftTask starts', __name__)
     commTask = CaseTask(**attributes)
     return commTask
예제 #26
0
    def parse_hooks(self):
        """
        Check for new MISP Alert containing supported IOC to search automatically
        """

        if self.webhook.isNewMispAlert():
            logger.info(
                'Alert {} has been tagged as MISP and is just created'.format(
                    self.webhook.data['rootId']))

            #Check alert for supported ioc types
            supported_iocs = False
            for artifact in self.webhook.data['object']['artifacts']:
                if artifact['dataType'] in self.qr_config[
                        'supported_datatypes']:
                    supported_iocs = True

            #Promote alert to case if there are support ioc types
            if supported_iocs:
                alert_id = self.webhook.data['rootId']
                casetemplate = "MISP Event"

                logger.info('Alert {} contains IOCs that are supported'.format(
                    alert_id))

                response = self.TheHiveConnector.createCaseFromAlert(
                    alert_id, casetemplate)

                self.report_action = 'createCase'
        """
        Add timestamps to keep track of the search activity per case (we do not want to keep searching forever)
        """
        #Perform automated Analyzer runs for supported observables in a case that has been created from a MISP alert
        if self.webhook.isNewMispCase():
            logger.info(
                'Case {} has been tagged as MISP and is just created'.format(
                    self.webhook.data['rootId']))

            #Retrieve caseid
            caseid = self.webhook.data['object']['id']

            #Add customFields firstSearched and lastSearched
            #Create a Case object? Or whatever it is
            case = Case()

            #Add the case id to the object
            case.id = caseid

            #Debug output
            logger.info('Updating case %s' % case.id)

            #Define which fields need to get updated
            fields = ['customFields']

            #Retrieve all required attributes from the alert and add them as custom fields to the case
            current_time = int(round(time.time() * 1000))
            customFields = CustomFieldHelper()\
                .add_date('firstSearched', current_time)\
                .add_date('lastSearched', current_time)\
                .build()

            #Add custom fields to the case object
            case.customFields = customFields

            #Update the case
            self.TheHiveConnector.updateCase(case, fields)
            self.report_action = 'updateCase'
        """
        Start the analyzers automatically for MISP observables that are supported and update the case with a new timestamp
        """
        #Automatically run Analyzers for newly created MISP cases where supported IOC's are present
        if self.webhook.isNewMispArtifact():
            logger.info(
                'Case artifact is tagged with "MISP-extern". Checking if observable is of a supported type'
            )

            #Retrieve caseid
            caseid = self.webhook.data['rootId']

            #Retrieve case data
            case_data = self.TheHiveConnector.getCase(caseid)

            #List all supported ioc's for the case
            observable = self.webhook.data['object']

            #When supported, start a cortex analyzer for it
            if observable['dataType'] in self.qr_config['supported_datatypes']:
                supported_observable = observable['_id']

                #Trigger a search for the supported ioc
                logger.info('Launching analyzers for observable: {}'.format(
                    observable['_id']))
                response = self.CortexConnector.runAnalyzer(
                    "Cortex-intern", supported_observable,
                    "IBMQRadar_Search_Manual_0_1")

                #Add customFields firstSearched and lastSearched
                #Create a Case object
                case = Case()

                #Add the case id to the object
                case.id = caseid

                #Debug output
                logger.info('Updating case %s' % case.id)

                #Define which fields need to get updated
                fields = ['customFields']

                #Retrieve all required attributes from the alert and add them as custom fields to the case
                current_time = int(round(time.time() * 1000))
                customFields = CustomFieldHelper()\
                    .add_date('firstSearched', case_data['customFields']['firstSearched']['date'])\
                    .add_date('lastSearched', current_time)\
                    .build()

                #Add custom fields to the case object
                case.customFields = customFields

                #Update the case
                self.TheHiveConnector.updateCase(case, fields)
                self.report_action = 'updateCase'
        """
        Automatically create a task for a found IOC
        """
        #If the Job result contains a successful search with minimum of 1 hit, create a task to investigate the results
        if self.webhook.isCaseArtifactJob() and self.webhook.isSuccess(
        ) and self.webhook.isMisp():
            #Case ID
            caseid = self.webhook.data['rootId']
            #Load Case information
            case_data = self.TheHiveConnector.getCase(caseid)

            logger.info(
                'Job {} is part of a case that has been tagged as MISP case and has just finished'
                .format(self.webhook.data['object']['cortexJobId']))

            #Check if the result count higher than 0
            if int(
                    float(self.webhook.data['object']['report']['summary']
                          ['taxonomies'][0]['value'])) > 0:
                logger.info(
                    'Job {} contains hits, checking if a task is already present for this observable'
                    .format(self.webhook.data['object']['cortexJobId']))
                #Retrieve case task information
                response = self.TheHiveConnector.getCaseTasks(caseid)
                case_tasks = response.json()

                #Load CaseTask template
                casetask = CaseTask()

                #Observable + Link
                observable = self.webhook.data['object']['artifactId']
                observable_link = TheHive.get(
                    'url'
                ) + "/index.html#!/case/" + caseid + "/observables/" + self.webhook.data[
                    'object']['artifactId']

                #Task name
                casetask.title = "Investigate found IOC with id: {}".format(
                    observable)

                #Date
                date_found = time.strftime("%d-%m-%Y %H:%M")

                case_task_found = False
                for case_task in case_tasks:

                    #Check if task is present for investigating the new results
                    if casetask.title == case_task['title']:
                        case_task_found = True

                if not case_task_found:
                    logger.info(
                        'No task found, creating task for observable found in job {}'
                        .format(self.webhook.data['object']['cortexJobId']))
                    #Add description
                    casetask.description = "The following ioc is hit in the environment. Investigate the results and act accordingly:\n\n"
                    casetask.description = casetask.description + "{} is seen on {}\n".format(
                        observable_link, date_found)

                    #Check if case is closed
                    if case_data['status'] == "Resolved":
                        #Create a Case object? Or whatever it is
                        case = Case()

                        #Add the case id to the object
                        case.id = caseid

                        logger.info('Updating case %s' % case.id)

                        #Define which fields need to get updated
                        fields = ['status']

                        #Reopen the case
                        case.status = "Open"

                        #Update the case
                        self.TheHiveConnector.updateCase(case, fields)

                    #Add the case task
                    self.TheHiveConnector.createTask(caseid, casetask)
                    self.report_action = 'createTask'
예제 #27
0
from __future__ import print_function
from __future__ import unicode_literals

import requests
import sys
import json
import time
from thehive4py.api import TheHiveApi
from thehive4py.models import Case, CaseTask, CustomFieldHelper

api = TheHiveApi('http://127.0.0.1:9000', '**YOUR_API_KEY**')

# Prepare the sample case
tasks = [
    CaseTask(title='Tracking'),
    CaseTask(title='Communication'),
    CaseTask(title='Investigation', status='Waiting', flag=True)
]

# Prepare the custom fields
customFields = CustomFieldHelper()\
    .add_boolean('booleanField', True)\
    .add_string('businessImpact', 'HIGH')\
    .add_date('occurDate', int(time.time())*1000)\
    .add_number('cvss', 9)\
    .build()

case = Case(title='From TheHive4Py',
            tlp=3,
            flag=True,
예제 #28
0
def submitTheHive(emailFilePath):

    '''
    Create a new case in TheHive based on the email
    Return 'TRUE' is successfully processed otherwise 'FALSE'
    '''
    

    global log

    mailName, mailType = os.path.splitext(emailFilePath)

    if mailType == ".msg":
        fromField, subjectField, observables, body, attachments = readMsg(emailFilePath)
    elif mailType == ".eml":
        fromField, subjectField, observables, body, attachments = readEml(emailFilePath)

    # Cleanup observables (remove duplicates)
    new_observables = []
    for o in observables:
        if not {'type': o['type'], 'value': o['value'] } in new_observables:
            # Is the observable whitelisted?
            if isWhitelisted(o['value']):
                log.debug('Skipping whitelisted observable: %s' % o['value'])
            else:
                new_observables.append({ 'type': o['type'], 'value': o['value'] })
                log.debug('Found observable %s: %s' % (o['type'], o['value']))
        else:
            log.info('Ignoring duplicate observable: %s' % o['value'])
    log.info("Removed duplicate observables: %d -> %d" % (len(observables), len(new_observables)))
    observables = new_observables

    api = TheHiveApi(config['thehiveURL'], config['thehiveApiKey'])

    # Search for interesting keywords in subjectField:
    log.debug("Searching for %s in '%s'" % (config['alertKeywords'], subjectField))
    if re.match(config['alertKeywords'], subjectField, flags=0):
        #
        # Add observables found in the mail body
        #
        artifacts = []
        if config['thehiveObservables'] and len(observables) > 0:
            for o in observables:
                artifacts.append(AlertArtifact(dataType=o['type'], data=o['value']))

        #
        # Prepare tags - add alert keywords found to the list of tags
        #
        tags = list(config['alertTags'])
        match = re.findall(config['alertKeywords'], subjectField)
        for m in match:
            tags.append(m)

        #
        # Prepare the alert
        #
        sourceRef = str(uuid.uuid4())[0:6]
        alert = Alert(title=subjectField.replace('[ALERT]', ''),
                      tlp         = int(config['alertTLP']),
                      tags        = tags,
                      description = body,
                      type        = 'external',
                      source      = fromField,
                      sourceRef   = sourceRef,
                      artifacts   = artifacts)

        # Create the Alert
        id = None
        response = api.create_alert(alert)
        if response.status_code == 201:
            log.info('Created alert %s' % response.json()['sourceRef'])
        else:
            log.error('Cannot create alert: %s (%s)' % (response.status_code, response.text))
            return False

    else:
        # Prepare the sample case
        tasks = []
        for task in config['caseTasks']:
             tasks.append(CaseTask(title=task))

        # Prepare the custom fields
        customFields = CustomFieldHelper()\
            .add_string('from', fromField)\
            .add_string('attachment', str(attachments))\
            .build()

        # If a case template is specified, use it instead of the tasks
        if len(config['caseTemplate']) > 0:
            case = Case(title=subjectField,
                        tlp          = int(config['caseTLP']), 
                        flag         = False,
                        tags         = config['caseTags'],
                        description  = body,
                        template     = config['caseTemplate'],
                        customFields = customFields)
        else:
                                           is_mandatory=True))
        createDate = float(
            configuration.checkAndValidate(
                result, "date", default=DATE_DEFAULT,
                is_mandatory=False)) * 1000
        createTLP = int(
            configuration.checkAndValidate(result,
                                           "tlp",
                                           default=TLP_DEFAULT,
                                           is_mandatory=True))
        createDescription = configuration.checkAndValidate(result,
                                                           "description",
                                                           default="",
                                                           is_mandatory=True)
        createTasks = [
            CaseTask(title=t) for t in configuration.checkAndValidate(
                result, "tasks", default=[], is_mandatory=False).split(" ;")
        ]

        # create the query from parameters
        new_case = Case(title=createTitle,
                        severity=createSeverity,
                        tags=createTags,
                        pap=createPAP,
                        startDate=createDate,
                        tlp=createTLP,
                        description=createDescription,
                        tasks=createTasks)

        logger.info("[THCC-5] Query is: " + str(new_case.jsonify()))
예제 #30
0
from __future__ import print_function
from __future__ import unicode_literals

import requests
import sys
import json
import time
from thehive4py.api import TheHiveApi
from thehive4py.models import Case, CaseTask

api = TheHiveApi('http://127.0.0.1:9000', 'username', 'password', {'http': '', 'https': ''})


# Prepare the sample case
tasks = [
    CaseTask(title='Tracking'),
    CaseTask(title='Communication'),
    CaseTask(title='Investigation', status='Waiting', flag=True)
]
# tasks = []
case = Case(title='From TheHive4Py', tlp=3, flag=True, tags=['TheHive4Py', 'sample'], description='N/A', tasks=tasks)

# Create the case
print('Create Case')
print('-----------------------------')
id = None
response = api.create_case(case)
if response.status_code == 201:
    print(json.dumps(response.json(), indent=4, sort_keys=True))
    print('')
    id = response.json()['id']