From bd165cb726a96402dbf38b80b14ca32d78eb2bd3 Mon Sep 17 00:00:00 2001 From: Wes Lambert Date: Fri, 3 Jan 2020 01:35:09 +0000 Subject: [PATCH] Add Minemeld Responder --- responders/Minemeld/minemeld.json | 69 ++++++++++++++++++++++++++ responders/Minemeld/minemeld.py | 72 ++++++++++++++++++++++++++++ responders/Minemeld/requirements.txt | 1 + 3 files changed, 142 insertions(+) create mode 100644 responders/Minemeld/minemeld.json create mode 100755 responders/Minemeld/minemeld.py create mode 100644 responders/Minemeld/requirements.txt diff --git a/responders/Minemeld/minemeld.json b/responders/Minemeld/minemeld.json new file mode 100644 index 000000000..983d3b21b --- /dev/null +++ b/responders/Minemeld/minemeld.json @@ -0,0 +1,69 @@ +{ + "name": "Minemeld", + "version": "1.0", + "author": "Wes Lambert, Security Onion Solutions", + "url": "https://github.com/TheHive-Project/Cortex-Analyzers", + "license": "AGPL-V3", + "description": "Submit indicator to Minemeld", + "dataTypeList": ["thehive:case_artifact"], + "command": "Minemeld/minemeld.py", + "baseConfig": "Minemeld", + "configurationItems": [ + { + "name": "minemeld_url", + "description": "URL for Minemeld instance", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "https://x.x.x.x" + }, + { + "name": "minemeld_user", + "description": "User for Minemeld", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "apiuser" + }, + { + "name": "minemeld_password", + "description": "Password for Minemeld", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "password" + }, + { + "name": "minemeld_indicator_list", + "description": "Name of indicator list to which indicators will be added", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "my_block_list" + }, + { + "name": "minemeld_share_level", + "description": "Share level for indicator", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "red" + }, + { + "name": "minemeld_confidence", + "description": "Confidence level for indicator", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "100" + }, + { + "name": "minemeld_ttl", + "description": "TTL for indicator", + "type": "string", + "multi": false, + "required": true, + "defaultValue": "86400" + } + ] +} diff --git a/responders/Minemeld/minemeld.py b/responders/Minemeld/minemeld.py new file mode 100755 index 000000000..84285c9c6 --- /dev/null +++ b/responders/Minemeld/minemeld.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +from cortexutils.responder import Responder +import requests +import json +import ipaddress + +class Minemeld(Responder): + def __init__(self): + Responder.__init__(self) + self.minemeld_url = self.get_param('config.minemeld_url', None, 'URL missing!') + self.minemeld_user = self.get_param('config.minemeld_user', None, 'Username missing!') + self.minemeld_password = self.get_param('config.minemeld_password', None, 'Password missing!') + self.minemeld_indicator_list = self.get_param('config.minemeld_indicator_list', None, "List missing!") + self.minemeld_share_level = self.get_param('config.minemeld_share_level', None, "Share level missing!") + self.minemeld_confidence = self.get_param('config.minemeld_confidence', None, "Confidence level missing!") + self.minemeld_ttl = self.get_param('config.minemeld_ttl', None, "TTL missing!") + self.observable_type = self.get_param('data.dataType', None, "Data type is empty") + self.observable_description = self.get_param('data.message', None, "Message is empty") + self.observable = self.get_param('data.data', None, "Data is empty") + + + 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 operations(self, raw): + return [self.build_operation('AddTagToCase', tag='Minemeld:Indicator Added')] + +if __name__ == '__main__': + Minemeld().run() diff --git a/responders/Minemeld/requirements.txt b/responders/Minemeld/requirements.txt new file mode 100644 index 000000000..8e9db03d5 --- /dev/null +++ b/responders/Minemeld/requirements.txt @@ -0,0 +1 @@ +ipaddress