def run(self): Responder.run(self) if self.get_param('data.dataType') == 'username': str_username = self.get_param('data.data', None, 'No artifacts available') admin_api = duo_client.Admin(self.iKey, self.sKey, self.API_hostname) response = admin_api.get_users_by_name(username=str_username) # print(response) user_id=response[0]["user_id"] # print("user_id:",user_id) r = admin_api.update_user(user_id=user_id,status='disabled') # print("response:",r) if r.get('status') == 'disabled': self.report({'message': 'User is locked in Duo Security.'}) else: self.error('Failed to lock User Account in Duo.') else: self.error('Incorrect dataType. "username" expected.')
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'title is missing') title = title.encode('utf-8') description = self.get_param('data.description', None, 'description is missing') description = description.encode('utf-8') mail_to = None if self.data_type == 'thehive:case': # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[5:] for t in tags if t.startswith('mail:')] if mail_tags: mail_to = mail_tags.pop() else: self.error('recipient address not found in observables') elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param( 'data.artifacts', None, 'recipient address not found in observables') mail_artifacts = [ a['data'] for a in artifacts if a.get('dataType') == 'mail' and 'data' in a ] if mail_artifacts: mail_to = mail_artifacts.pop() else: self.error('recipient address not found in observables') else: self.error('Invalid dataType') msg = MIMEMultipart() msg['Subject'] = title msg['From'] = self.mail_from msg['To'] = mail_to msg['Date'] = formatdate(localtime=True) msg['Message-ID'] = make_msgid() msg.attach(MIMEText(description, 'plain')) s = smtplib.SMTP(self.smtp_host, self.smtp_port) if (self.smtp_auth): try: s.starttls() s.login(self.mail_user, self.mail_pass) except: self.error('an error occured with SMTP username/password') try: s.sendmail(self.mail_from, [mail_to], msg.as_string()) s.quit() self.report({'message': 'message sent'}) except: self.error('unable to send email')
def run(self): Responder.run(self) auth = (self.wazuh_user, self.wazuh_password) headers = {'Content-Type': 'application/json'} # Check observable to ensure valid IP address if self.observable_type == "filename": try: os.path.isfile(self.observable) except ValueError: self.error({'message': "Not a file!"}) else: self.error({'message': "Not a file!"}) payload = '{"command":"file-encryptor.sh", "arguments": ["-", "' + self.observable + '", "var/log/test.log"], "custom": "True"}' r = requests.put(self.wazuh_manager + '/active-response/' + self.wazuh_agent_id, headers=headers, data=payload, verify=False, auth=auth) if r.status_code == 200: self.report({'message': "File encrypted for " + self.observable}) else: self.error(r.status_code)
def run(self): Responder.run(self) def api_call(ip_addr, port, command, json_payload, sid): url = 'https://' + str(ip_addr) + ':' + str(port) + '/web_api/' + command if sid == '': request_headers = {'Content-Type' : 'application/json'} else: request_headers = {'Content-Type' : 'application/json', 'X-chkp-sid' : sid} r = requests.post(url,data=json.dumps(json_payload), headers=request_headers, verify=False) return r.json() def login(user,password): payload = {'user':user, 'password' : password} response = api_call('192.168.50.52', 443, 'login',payload, '') return response['sid'] sid = login(self.username,self.password) #print("session id: " + sid) new_host_data = {'name':'new host name', 'ip-address':self.host_ip} new_host_result = api_call('192.168.50.52', 443,'add-host', new_host_data ,sid) #print(json.dumps(new_host_result)) publish_result = api_call('192.168.50.52', 443,"publish", {},sid) #print("publish result: " + json.dumps(publish_result)) logout_result = api_call('192.168.50.52', 443,"logout", {},sid)
def run(self): Responder.run(self) if self.get_param('data.dataType') == 'domain': domain = self.get_param('data.data', None, 'No artifacts available') dstUrl = "http://" + domain date = datetime.now().strftime("%Y-%m-%dT%XZ") headers = { 'user-agent': 'UmbrellaBlacklister-Cortex-Responder', 'Content-Type': 'application/json' } payload = { "alertTime": date, "deviceId": "cortex_thehive", "deviceVersion": "2.4.81", "dstDomain": domain, "dstUrl": dstUrl, "eventTime": date, "protocolVersion": "1.0a", "providerName": "Security Platform" } r = requests.post(self.integration_url, json=payload, headers=headers) if r.status_code == 200 | 202: self.report({'message': 'Blacklisted in Umbrella.'}) else: self.error('Failed to add to blacklist.') else: self.error('Incorrect dataType. "Domain" expexted.')
def run(self): try: Responder.run(self) ioctypes = {"hash": "sha256", "sha256": "sha256", "md5": "md5", "sha1": "sha1", "ip": "ipv4", "ip6": "ipv6", "ipv6": "ipv6", "domain": "domain", "url": "domain"} data_type = self.get_param('data.dataType') if not data_type in ioctypes: self.error("Unsupported IOC type") return ioc = self.get_param('data.data', None, 'No IOC provided') if data_type == "url": match = re.match(r"(http:\/\/|https:\/\/)?([\w\d\-\.]{0,256}).*", ioc) if match is None or match.group(2) is None: self.error("Could not parse domain from URL") return else: ioc=match.group(2) description = self.get_param('data.case.title',None,"Can't get case title") description = str(description).encode('utf-8')[:128] postdata=json.dumps([{"type": ioctypes[data_type], "value": ioc.strip(), "policy": "detect", "description": description, "share_level": "red", "source": "Cortex - FalconCustomIOC ["+description+"]", "expiration_days": 30}]) response=requests.post(self.falconapi_url,data=postdata,headers={"Content-Type":"application/json"},auth=HTTPBasicAuth(self.apiuser,self.apikey)) json_response = json.loads(response.text) if json_response["errors"]: self.error(str(json_response["errors"])) return else: self.report({'message': ioc+" Submitted to Crowdstrike Falcon custom IOC api","api_response":json_response}) except Exception as ex: self.error(traceback.format_exc())
def run(self): Responder.run(self) if self.get_param("data.dataType") == "username": if self.service in ["lock", "unlock"]: str_username = self.get_param( "data.data", None, "No artifacts available" ) admin_api = duo_client.Admin(self.iKey, self.sKey, self.API_hostname) response = admin_api.get_users_by_name(username=str_username) user_id = response[0]["user_id"] if self.service == "lock": r = admin_api.update_user(user_id=user_id, status="disabled") if r.get("status") == "disabled": self.report({"message": "User is locked in Duo Security."}) else: self.error("Failed to lock User Account in Duo.") elif self.service == "unlock": r = admin_api.update_user(user_id=user_id, status="active") if r.get("status") == "active": self.report( { "message": "User is unlocked in Duo Security. The user must complete secondary authentication." } ) else: self.error("Failed to unlock User Account in Duo.") else: self.error('Incorrect dataType. "username" expected.')
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'title is missing') description = self.get_param('data.description', None, 'description is missing') mail_to = None if self.data_type == 'thehive:case': # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[5:] for t in tags if t.startswith('mail:')] if mail_tags: mail_to = mail_tags.pop() else: self.error('recipient address not found in observables') elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param('data.artifacts', None, 'recipient address not found in observables') mail_artifacts = [a['data'] for a in artifacts if a.get('dataType') == 'mail' and 'data' in a] if mail_artifacts: mail_to = mail_artifacts.pop() else: self.error('recipient address not found in observables') else: self.error('Invalid dataType') msg = MIMEMultipart() msg['Subject'] = title msg['From'] = self.mail_from msg['To'] = mail_to msg.attach(MIMEText(description, 'plain')) s = smtplib.SMTP(self.smtp_host) s.sendmail(self.mail_from, [mail_to], msg.as_string()) s.quit() self.report({'message': 'message sent'})
def run(self): Responder.run(self) #data_type = self.get_param('data.dataType') auth = client.login(self.checkpoint_apikey) if self.server_ip == "ip": try: ipaddress.ip_address(self.server_ip) except ValueError: self.error({'message': "Not a valid IPv4/IPv6 address!"}) else: self.error({'message': "Not a valid IPv4/IPv6 address!"}) if auth.success is False: print("Login failed:\n{}".format(auth.error_message)) exit(1) # add a rule to the top of the "Network" layer add_rule_response = client.api_call("add-access-rule", {"name": self.rule_name, "layer": "Network", "position": "top"}) if add_rule_response.success: print("The rule: '{}' has been added successfully".format(self.rule_name)) # publish the result publish_res = client.api_call("publish", {}) if publish_res.success: print("The changes were published successfully.") else: print("Failed to publish the changes.") else: print("Failed to add the access-rule: '{}', Error:\n{}".format(self.rule_name, add_rule_response.error_message))
def run(self): Responder.run(self) for x in self.hosts: with pysftp.Connection(host=x, username='******', password='******', port=22, cnopts=cnopts) as srv: with srv.cd('/tmp'): srv.put(self.wdir + '/loki_linux.tar.gz') srv.execute('rm /tmp/Loki/out.log') srv.execute('tar -xzf /tmp/loki_linux.tar') srv.execute( 'cd /tmp/Loki && ./loki -l /tmp/Loki/out.log --dontwait -p /' ) srv.get('/tmp/Loki/out.log') srv.get('/tmp/Loki/out.log', self.wdir + '/out.log') with open(self.wdir + '/out.log') as f: content = f.read() if 'SYSTEM SEEMS TO BE CLEAN' in content: self.report({'Host %s' % x: 'good'}) else: self.report({'Host %s' % x: 'bad'}) os.remove(self.wdir + '/out.log')
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'title is missing') description = self.get_param('data.description', None, 'description is missing') mail_to = None if self.data_type == 'thehive:case': # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[5:] for t in tags if t.startswith('mail:')] if mail_tags: mail_to = mail_tags.pop() else: self.error('recipient address not found in tags') elif self.data_type == 'thehive:case_task': # Search recipient address in tags descr_array = description.splitlines() if 'mailto:' in descr_array[0]: mail_to = descr_array[0].replace("mailto\:", "") else: self.error('recipient address not found in description') #Set rest of description as body del descr_array[0] description = '\n'.join(descr_array) elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param( 'data.artifacts', None, 'recipient address not found in observables') mail_artifacts = [ a['data'] for a in artifacts if a.get('dataType') == 'mail' and 'data' in a ] if mail_artifacts: mail_to = mail_artifacts.pop() else: self.error('recipient address not found in observables') else: self.error('Invalid dataType') msg = MIMEMultipart() msg['Subject'] = title msg['From'] = self.mail_from msg['To'] = mail_to msg.attach(MIMEText(description, 'plain')) #Add reply-to header msg.add_header('reply-to', self.mail_reply_to) s = smtplib.SMTP(self.smtp_host, self.smtp_port) if self.smtp_auth: s.ehlo() s.starttls() s.login(self.username, self.password) s.sendmail(self.mail_from, mail_to.split(','), msg.as_string()) s.quit() self.report({'message': 'message sent'})
def run(self): Responder.run(self) parsed_url = "%s/api/v1/workflows/%s/execute" % (self.url, self.workflow_id) headers = { "Authorization": "Bearer %s" % self.api_key, "User-Agent": "Cortex-Analyzer" } requests.post(parsed_url, headers=headers,verify=self.verify) self.report({'message': 'message sent'})
def run(self): Responder.run(self) headers = { "Content-Type": "application/json", "Accept": "application/json", "User-Agent": "Cortex-Analyzer" } requests.post(self.webhook_url, headers=headers,verify=self.verify, json=self.data) self.report({'message': 'message sent'})
def run(self): Responder.run(self) parsed_url = "%s/api/v1/workflows/%s/execute" % (self.url, self.workflow_id) headers = { "Authorization": "Bearer %s" % self.api_key } requests.post(parsed_url, headers=headers) self.report({'message': 'message sent'})
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'Title is missing') if title.find("Phishing report") == -1: self.report({"response" : "Phish_Feedback is only applicable to cases which title starts with 'Phishing report'"}) # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[11:] for t in tags if t.startswith('user_email:')] if mail_tags: mail_to = mail_tags.pop() else: self.report({"Error" : "Recipient address not found in observable"}) if self.mode == "Phishing": description = """\rGreetings, \rYou've recently reported a spear-phishing attempt to us'. \rWe would like to congratulate you for spotting this attempt beacause it was indeed a malicious email! \rThank you, """ elif self.mode == "Legit email": description = """\rGreetings, \rYou've recently reported a spear-phishing attempt to us. \rWe thank you for your submission , however we would like to inform you that this email was legitimate. Can you please tell us why you thought it was malicious ? \rIf you want tips on how to detect phishing emails , please check: \rhttps://campagne.safeonweb.be/en/phishing \rThank you, """ elif self.mode == "Spam": description = """\rGreetings, \rYou've recently reported a spear-phishing attempt to us. \rWe thank you for your submission , but we would like to inform you that this email was not malicious but just ordinary spam. \rIf you would like tips on how to detect phishing emails , please check: \rhttps://campagne.safeonweb.be/en/phishing \rThank you \r """ msg = MIMEMultipart() msg['Subject'] = "Phishing report feedback" msg['From'] = self.mail_from msg['To'] = mail_to msg.attach(MIMEText(description, 'plain')) context = ssl.SSLContext(ssl.PROTOCOL_TLS) server = smtplib.SMTP(self.smtp_host, self.smtp_port) server.starttls(context=context) server.login(self.smtp_user, self.smtp_pwd) server.sendmail(self.mail_from, mail_to, msg.as_string()) server.quit() self.report({'Status': 'Mail sent'})
def run(self): Responder.run(self) auth = (self.minemeld_user, self.minemeld_password) headers = {"Content-Type": "application/json"} # Check for indicator type if self.observable_type == "ip": try: ipaddress.IPv4Address(self.observable) indicator_type = "IPv4" except ValueError: try: ipaddress.IPv6Address(self.observable) indicator_type = "IPv6" except ValueError: self.error({'message': "Not a valid IPv4/IPv6 address!"}) elif self.observable_type == "url": indicator_type = "URL" elif self.observable_type == "domain": indicator_type = "Domain" # Check for comment if self.observable_description == "": comment = "Indicator submitted from TheHive" else: comment = self.observable_description # Build our payload payload = { "indicator": self.observable, "type": indicator_type, "comment": comment, "share_level": self.minemeld_share_level, "confidence": self.minemeld_confidence, "ttl": self.minemeld_ttl } # Send our request try: r = requests.post(str(self.minemeld_url) + '/config/data/' + str(self.minemeld_indicator_list) + '_indicators' + '/append?h=' + str(self.minemeld_indicator_list) + '&t=localdb', data=json.dumps(payload), headers=headers, auth=auth, verify=False) self.report({ 'message': "Indicator " + self.observable + " submitted to Minemeld." }) except: self.error({'message': r.text})
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'title is missing') title = title.encode('utf-8') description = self.get_param('data.description', None, 'description is missing') description = description.encode('utf-8') mail_to = None if self.data_type == 'thehive:case': # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[5:] for t in tags if t.startswith('mail:')] if mail_tags: mail_to = mail_tags.pop() else: self.error('recipient address not found in observables') elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param( 'data.artifacts', None, 'recipient address not found in observables') mail_artifacts = [ a['data'] for a in artifacts if a.get('dataType') == 'mail' and 'data' in a ] if mail_artifacts: mail_to = mail_artifacts.pop() else: self.error('recipient address not found in observables') else: self.error('Invalid dataType') msg = MIMEMultipart() msg['Subject'] = title msg['From'] = email.utils.formataddr( (self.sender_name, self.mail_from)) msg['To'] = mail_to msg['Reply-To'] = '*****@*****.**' msg.attach(MIMEText(description, 'plain')) server = smtplib.SMTP(self.smtp_host, self.smtp_port) server.ehlo() server.starttls() server.ehlo() server.login(self.smtp_username, self.smtp_password) server.sendmail(self.mail_from, [mail_to], msg.as_string()) server.close() self.report({'message': 'message sent'})
def run(self): Responder.run(self) self.hive_auth(self.__thehive_url, self.__thehive_api_key) dataType = self.get_param("data.dataType") observable = self.get_param("data.data") caseId = self.get_param("data._parent") action = getattr( self, self.service, self.__not_found) # call respective func or fail with default action(observable, dataType, caseId)
def run(self): """ Add a hash to the specified Elasticsearch index if some artifacts have been submitted and the hash does not already exist """ Responder.run(self) data = self.get_data() artifacts = self.get_param('data.artifacts') rule_title = self.get_param('data.title', default='no data') suppressing_username = self.get_param('data.createdBy', default='no data') if not artifacts: # If there are no artifacts we have no data to generate a hash self.error('No artifacts submitted') observables = [] # The jsonify method provides a list of predictably sorted JSON strings which we then sort in order to make # sure that the we generate the same hash that will be read from the database by HashSuppressorEnhancement for artifact in artifacts: observables.append(AlertArtifact(dataType=artifact.get('dataType'), data=artifact.get('data'))) observable_hash_string = u'|'.join(sorted([observable.jsonify() for observable in observables])) observable_hash = hashlib.md5(observable_hash_string.encode('utf-8')).hexdigest() class AlertHash(Document): alert_hash = Keyword() date_suppressed = Date() rule_title = Keyword() suppressing_username = Keyword() class Index: name = self.es_index # This is required because the commented registration below does not work connections.create_connection(**self.es_kwargs) alert_hashes = Index(self.es_index) # alert_hashes.document(AlertHash) # Registering a Document to the Index does not work for some reason if not alert_hashes.exists(): alert_hashes.create() results = AlertHash.search().filter('term', alert_hash=observable_hash).execute(ignore_cache=True) if not results: # Don't save the same hash multiple times alert_hash = AlertHash( alert_hash=observable_hash, date_suppressed=datetime.datetime.now(), rule_title=rule_title, suppressing_username=suppressing_username ) alert_hash.save() message = 'MD5 hash [{}] added to Elasticsearch database [{}:{}] index [{}]'.format( observable_hash, self.es_host, self.es_port, self.es_index) else: message = 'MD5 hash [{}] already existed in the Elasticsearch database [{}:{}] index [{}]'.format( observable_hash, self.es_host, self.es_port, self.es_index) self.report({'message': message})
def run(self): Responder.run(self) if self.service == "s1_blacklist": if self.s1_blacklist_ostype not in ( "linux", "macos", "windows", "windows_legacy", ): self.error( f"{self.s1_blacklist_ostype} is not a valid OS Type") return if self.observable_type != "hash": self.error(f"{self.observable} is not a hash") return else: if self.sha1_re.match(self.observable) is None: self.error(f"{self.observable} is not a valid SHA1 hash") return response = requests.post( f"{self.s1_console_url}{self.s1_blacklist_api_endpoint}", headers=self.headers, json={ "data": { "type": self.s1_blacklist_type, "value": self.observable, "osType": self.s1_blacklist_ostype, }, "filter": { "accountIds": [ self.s1_account_id, ] }, }, proxies=self.proxies, ) if response.status_code == requests.codes.ok: self.report({"message": "Blacklisted in SentinelOne."}) else: self.error( f"Error, unable to complete action, recieved {response.status_code} status code from SentinelOne API!" )
def run(self): Responder.run(self) #Se obtienen el titulo de la alerta del campo data.title title = self.get_param('data.title', None, 'title not found in observables') #Se obtienen las IPs origen y destino del bloque data.artifacts artifacts = self.get_param('data.artifacts', None, 'recipient address not found in observables') #ip_artifacts = [a['data'] for a in artifacts if a.get('dataType') == 'source_ip' or a.get('dataType') == 'destination_ip' and 'data' in a] #if ip_artifacts: # ipOrigen = ip_artifacts.pop() # ipDestino = ip_artifacts.pop() #else: # self.error('recipient address not found in observables') source_ip = ''.join([a['data'] for a in artifacts if a.get('dataType') == 'source_ip' and 'data' in a]) destination_ip = ''.join([a['data'] for a in artifacts if a.get('dataType') == 'destination_ip' and 'data' in a]) source_port = ''.join([a['data'] for a in artifacts if a.get('dataType') == 'source_port' and 'data' in a]) destination_port = ''.join([a['data'] for a in artifacts if a.get('dataType') == 'destination_port' and 'data' in a]) #Se obtienen el nombre del host (sensor) que envia la alerta del campo data.source source = self.get_param('data.source', None, 'title not found in observables') #Se obtienen el numero de categoria de la alerta del campo data.severity severity = self.get_param('data.severity', None, 'title not found in observables') #Se concatenan los valores para enviar el mensaje msgText = "IP origen: %s \n Puerto origen: %s \n IP destino: %s \n Puerto destino: %s \n"%(source_ip,source_port,destination_ip,destination_port) #Con los campos anteriores se arma el mensaje para enviar a slack slack_msg = { "username": "******", "attachments": [ { "color": "#bc0909", "title": title, "text": msgText, "mrkdwn_in": [ "text", "pretext" ] } ] } r = requests.post(self.slack_webhook,data=json.dumps(slack_msg)) if r.status_code == 200 : self.report({'message': 'message sent'}) else: self.error('Failed to send message.')
def run(self): Responder.run(self) data_type = self.get_param('data.dataType') ioc_types = ["domain", "url", "fqdn"] if data_type in ioc_types: if data_type == "domain" or data_type == "fqdn": domain = self.get_param('data.data', None, 'No artifacts available') dstUrl = "http://" + domain elif data_type == "url": dstUrl = self.get_param('data.data', None, 'No artifacts available') domain = dstUrl.split('/')[2] date = datetime.now().strftime("%Y-%m-%dT%XZ") headers = { 'user-agent': 'UmbrellaBlacklister-Cortex-Responder', 'Content-Type': 'application/json' } payload = { "alertTime": date, "deviceId": "cortex_thehive", "deviceVersion": "2.4.81", "dstDomain": domain, "dstUrl": dstUrl, "eventTime": date, "protocolVersion": "1.0a", "providerName": "Security Platform" } r = requests.post(self.integration_url, json=payload, headers=headers) if r.status_code == 200 | 202: self.report({'message': 'Blacklisted in Umbrella.'}) else: self.error('Failed to add to blacklist.') else: self.error( 'Incorrect dataType. "Domain", "FQDN", or "URL" expected.')
def run(self): Responder.run(self) title = self.get_param('data.title', None, 'Title is missing') if title.find("#") == -1: self.error( "Responder is only applicable to imported Misp Event alerts") space_indx = title.index(" ") event_id = title[1:space_indx] #add the Relevant tag in Misp to the linked event url = self.misp_url + "/events/addTag" data = { "request": {"Event": {"id": event_id, "tag": "Relevant", "local" : "false" } } } headers = {'Content-type': 'application/json', "Accept" : "application/json" ,'Authorization': self.misp_api_key} r = requests.post(url, json=data, headers=headers, verify = False, proxies=None) #publish it in Misp url = self.misp_url + "/events/publish/" + event_id r = requests.post(url, headers=headers, verify = False) #add tag to alert alert_id = self.get_param('data.id', None, 'alertId is missing') tags = self.get_param('data.tags', None, 'tags field missing') user = str(self.artifact["parameters"]["user"]) tags.append("Set as relevant by : " + user) server = 'Your TheHive URL' uri = "/api/alert/" + alert_id url = server+uri query = { "tags": tags } jsondata = json.dumps(query) jsondatab = jsondata.encode('utf-8') #adds a tag in TheHive headers = {'Authorization': 'Bearer ' + self.thehive_api_key, 'Content-Type': 'application/json'} resp = requests.patch(url, data=jsondatab, headers=headers,verify=False) self.report({'Status': 'Event marked as Relevant in Misp'})
def run(self): Responder.run(self) if self.get_param('data.dataType') == 'mail': tags = self.get_param('data.tags') if self.required_tag in tags or self.required_tag is None: target_user = self.get_param('data.data', None, 'No email address found') headers = { 'Authorization': 'Bearer ' + self.api_key, 'user-agent': 'KnowBe4-Cortex-Responder', 'Content-Type': 'application/json', 'Accept': 'application/json' } thehive_case = '{}/index.html#!/case/{}/details'.format( self.hive_url, self.get_param('data.case._routing')) description = 'TheHive Case: {}\n Description: {}\n URL: {}'.format( self.get_param('data.case.title'), self.get_param('data.case.description'), thehive_case) payload = { 'target_user': target_user, 'event_type': self.event_type, 'description': description, 'risk_level': 10 } r = requests.post(self.api_url, json=payload, headers=headers) if r.status_code == 200 | 201: self.report({'message': 'Added user event.'}) else: self.error('Failed report user to KnowBe4. Status: ' + str(r.status_code)) else: self.error('Email address not tagged with the required tag. ' + self.required_tag) else: self.error('Incorrect dataType. "Mail" expected.')
def run(self): Responder.run(self) tags = self.get_param('data.tags', None) action_request = "{}/{}/{}/{}/".format(self.url, self.zfEntity, self.ZerofoxAlert(tags), self.zfAction) # Manage mail addresses if self.data_type == 'thehive:case': if self.ZerofoxAlert(tags): try: response = requests.post(action_request, headers={'Authorization': 'Token {}'.format(self.api)}) if response.status_code == 200: self.report({'message': 'Alert {} has been closed'.format(self.ZerofoxAlert(tags))}) elif response.status_code == 400: self.error('HTTP 400 : Request body schema error') except Exception as ex: self.error(ex)
def run(self): Responder.run(self) auth = (self.wazuh_user, self.wazuh_password) headers = {'Content-Type': 'application/json'} # Check observable to ensure valid IP address if self.observable_type == "ip": try: ipaddress.ip_address(self.observable) except ValueError: self.error({'message': "Not a valid IPv4/IPv6 address!"}) else: self.error({'message': "Not a valid IPv4/IPv6 address!"}) payload = '{"command":"firewall-drop.sh", "arguments": ["-", "' + self.observable + '", "' + self.wazuh_alert_id + '", "' + self.wazuh_rule_id + '", "' + self.wazuh_agent_id + '", "var/log/test.log"], "custom": "True"}' r = requests.put(self.wazuh_manager + '/active-response/' + self.wazuh_agent_id, headers=headers, data=payload, verify=False, auth=auth) if r.status_code == 200: self.report({'message': "Added DROP rule for " + self.observable }) else: self.error(r.status_code)
def run(self): Responder.run(self) mail_to = None if self.data_type == 'thehive:case': title = self.get_param('data.title', None, 'title is missing') # Search recipient address in tags tags = self.get_param('data.tags', None, 'recipient address not found in tags') mail_tags = [t[5:] for t in tags if t.startswith('mail:')] if mail_tags: mail_to = mail_tags.pop() else: self.error('recipient address not found among tags') # Build the email body content = "Case: " header = self.case_header() content = content + header elif self.data_type == 'thehive:case_task': # Parse the task fields = case_task.get_fields(self) elif self.data_type == 'thehive:case_task_log': # Parse the log fields = case_task_log.get_fields(self) else: self.error('Invalid dataType') msg = MIMEMultipart() msg['Subject'] = fields['subject'] msg['From'] = self.mail_from #self.verify_addr(fields['addresses']) msg['To'] = ', '.join(fields['addresses']) msg.attach(MIMEText(fields['body'], 'html')) s = smtplib.SMTP(self.smtp_host) s.sendmail(self.mail_from, fields['addresses'], msg.as_string()) s.quit() self.report({'message': 'Your message has been sent!'})
def run(self): Responder.run(self) ip_to_block = None artifact_type = self.get_param('data.dataType', None, 'artifact data type not found') if self.data_type == 'thehive:case_artifact' and artifact_type == 'ip': #tag must start with client: artifact_ip = self.get_param('data.data', None, 'Could not get ip from observable') tags = self.get_param('data.tags', None, 'client name not found') client_tags = [t[7:] for t in tags if t.startswith('client:')] if len(client_tags) == 1: block_to = client_tags[0] elif len(client_tags) >= 2: block_to = client_tags else: self.error('recipient address not found..') else: self.error( 'invalid datatype try running on a case or run on ip address') if client_tags: ### first starting here # elif for other customer names #apollo fortigate each client has own firewall config if block_to == 'apollobank': apolloFw = '192.168.192.5' ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy( paramiko.AutoAddPolicy()) ssh_client.connect(hostname='ip', username='******', password='') ## could also use ssh key stdin, stdout, stderr = ssh_client.exec_command( '''config firewall address \n edit testing100 \n set type ipmask \n set subnet {} 255.255.255.255 \n end \n''' .format(artifact_ip)) output = stdout.read().decode('ascii').strip("\n") stdin.flush() stderr.flush() stdout.flush() self.report({'messege': output}) else: self.error('connection to firewall failed')
def run(self): Responder.run(self) if self.get_param('data.dataType') == 'url': url = self.get_param('data.data', None, 'No artifacts available') # URL API link = "https://takedown.netcraft.com/authorise.php" # Data for API requests data = { 'attack': url, 'region': self.account_region, 'comment': 'Ticket report' } # API requests response = requests.post(link, data=data, auth=(self.account_username, self.account_password)) if response.status_code == 200 : answer = response.text.split("\n") td_answer = answer[0] if(td_answer == "TD_OK"): td_ticket = answer[1] self.report({'message': 'URL reported. Ticket #'+str(answer[1])}) elif(td_answer == "TD_EXISTS"): td_ticket = answer[1] self.report({'message': 'URL already reported. Ticket #'+str(answer[1])}) elif(td_answer == "TD_VERIFY"): self.report({'message': 'URL undergoing verification.'}) elif(td_answer == "TD_WILDCARD"): self.report({'message': 'Wilcard sub-domain already reported.'}) else: # No authorization / credits self.error('Error') else: # Error self.error('Error') else: self.error('Incorrect dataType. "URL" expexted.')
def run(self): Responder.run(self) if self.get_param("data.dataType") in ["ip"]: endpoint = self.get_param("data.data") else: self.error('Invalid datatype {}'.format( self.get_param("data.dataType"))) caseId = self.get_param("data.case.caseId") if ipaddress.IPv4Address(endpoint).is_private: if self.check_credentials(): self.triage_endpoint(endpoint=endpoint, incident_name=caseId) self.report({ 'message': 'Endpoint {} under investigation. Incident Name: {}, Session ID: {}' .format(endpoint, caseId, self.ct_sid) }) else: self.error('IP Address {0} is out of scope'.format(endpoint))
def run(self): Responder.run(self) if self.get_param('data.dataType') == 'domain': domain = self.get_param('data.data', None, 'No domain artifact found') else: self.error('Can only operate on "domain" observables') if self.checkname(domain + '.' + self.rpz_zonename) == 0: # Only add if the record isn't already there. keyring = dns.tsigkeyring.from_text( {self.tsig_keyname: self.tsig_keyval}) update = dns.update.Update(self.rpz_zonename, keyring=keyring, keyalgorithm=self.tsig_hashalg) update.add(domain, 30, 'a', self.remediation_ip) response = dns.query.tcp(update, self.bind_server) if response.rcode() != 0: self.error('Failed to add RPZ record') self.report({'message': 'DNS-RPZ block injected'})