From 3590504821cf068301736b6dd89f5df044e18b73 Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Sat, 21 Jan 2017 23:31:19 +0100 Subject: [PATCH 1/6] XForce Exchange v1 (alpha) --- .../modules/expansion/xforceexchange.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 misp_modules/modules/expansion/xforceexchange.py diff --git a/misp_modules/modules/expansion/xforceexchange.py b/misp_modules/modules/expansion/xforceexchange.py new file mode 100644 index 0000000..5d1a24a --- /dev/null +++ b/misp_modules/modules/expansion/xforceexchange.py @@ -0,0 +1,89 @@ +#!/usr/bin/python + +import urllib2 +import json + +import sys +BASEurl = "https://api.xforce.ibmcloud.com/" + +extensions = {"ip1": "ipr/%s", + "ip2": "ipr/malware/%s", + "url": "url/%s", + "hash": "malware/%s", + "vuln": "/vulnerabilities/search/%s"} + +sys.path.append('./') + +misperrors = {'error': 'Error'} +mispattributes = {'input': ['ip-src','ip-dst' 'vulnerability', 'md5', 'sha1', 'sha256'], + 'output': ['ip-src', 'ip-dst', 'text']} + +# possible module-types: 'expansion', 'hover' or both +moduleinfo = {'version': '1', 'author': 'Joerg Stephan (@johest)', + 'description': 'IBM X-Force Exchange expansion module', + 'module-type': ['expansion', 'hover']} + +# config fields that your code expects from the site admin +moduleconfig = ["apikey", "event_limit"] +limit = 5000 #Default + + + +def MyHeader(key=False): + global limit + if key is False: + return None + + return {"Authorization": "Basic %s " % key, + "Accept": "application/json", + 'User-Agent': 'Mozilla 5.0'} + +def handler(q=False): + global limit + if q is False: + return False + + q = json.loads(q) + + key = q["config"]["apikey"] + limit = int(q["config"].get("event_limit", 5)) + + r = {"results": []} + + if "ip-src" in q: + r["results"] += dict( (apicall("ip1", q["ip-src"], key)).items() + (apicall("ip2", q["ip-src"], key)).items()) + if "ip-dst" in q: + r["results"] += dict( (apicall("ip1", q["ip-src"], key)).items() + (apicall("ip2", q["ip-src"], key)).items()) + if "md5" in q: + r["results"] += apicall("hash", q["md5"], key) + if "sha1" in q: + r["results"] += apicall("hash", q["sha1"], key) + if "sha256" in q: + r["results"] += apicall("hash", q["sha256"], key) + if 'vulnerability' in q: + r["results"] += apicall("vuln", q["vulnerability"], key) + + uniq = [] + for res in r["results"]: + if res not in uniq: + uniq.append(res) + r["results"] = uniq + return r + +def apicall(indicator_type, indicator, key=False): + try: + myURL = BASEurl + (extensions[str(indicator_type)])%indicator + request = urllib2.Request(myURL, None, MyHeader(key)) + data = urllib2.urlopen(request) + jsondata = json.loads(data.read()) + except: + return None + return jsondata + +def introspection(): + return mispattributes + + +def version(): + moduleinfo['config'] = moduleconfig + return moduleinfo \ No newline at end of file From 03044e1e6aefaf290159d8499b314191f5399299 Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Sun, 22 Jan 2017 00:00:15 +0100 Subject: [PATCH 2/6] merged xforce exchange --- REQUIREMENTS | 1 + 1 file changed, 1 insertion(+) diff --git a/REQUIREMENTS b/REQUIREMENTS index 6cda15a..2c845ec 100644 --- a/REQUIREMENTS +++ b/REQUIREMENTS @@ -19,3 +19,4 @@ pytesseract SPARQLWrapper domaintools_api pygeoip +urllib2 From dad73feaa41011795d50a9ff0b43ff2bb2454e7a Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Tue, 31 Jan 2017 16:34:41 +0100 Subject: [PATCH 3/6] python3 changes --- .../modules/expansion/xforceexchange.py | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/misp_modules/modules/expansion/xforceexchange.py b/misp_modules/modules/expansion/xforceexchange.py index 5d1a24a..8a01e77 100644 --- a/misp_modules/modules/expansion/xforceexchange.py +++ b/misp_modules/modules/expansion/xforceexchange.py @@ -1,6 +1,4 @@ -#!/usr/bin/python - -import urllib2 +import requests import json import sys @@ -71,19 +69,17 @@ def handler(q=False): return r def apicall(indicator_type, indicator, key=False): - try: + #try: myURL = BASEurl + (extensions[str(indicator_type)])%indicator - request = urllib2.Request(myURL, None, MyHeader(key)) - data = urllib2.urlopen(request) - jsondata = json.loads(data.read()) - except: - return None - return jsondata + jsondata = requests.get(myURL, headers=MyHeader(key)).json() + #except: + #return None + return jsondata def introspection(): - return mispattributes + return mispattributes def version(): - moduleinfo['config'] = moduleconfig - return moduleinfo \ No newline at end of file + moduleinfo['config'] = moduleconfig + return moduleinfo \ No newline at end of file From 2651e68238b67cb95e97e5facf6e8fd9e7df5359 Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Tue, 31 Jan 2017 16:54:53 +0100 Subject: [PATCH 4/6] removed urrlib2 --- REQUIREMENTS | 1 - 1 file changed, 1 deletion(-) diff --git a/REQUIREMENTS b/REQUIREMENTS index 2c845ec..6cda15a 100644 --- a/REQUIREMENTS +++ b/REQUIREMENTS @@ -19,4 +19,3 @@ pytesseract SPARQLWrapper domaintools_api pygeoip -urllib2 From 68250094ff0abe8abebccaf105a5889de1c9e8bc Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Tue, 31 Jan 2017 16:57:16 +0100 Subject: [PATCH 5/6] v1 --- misp_modules/modules/expansion/xforceexchange.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/misp_modules/modules/expansion/xforceexchange.py b/misp_modules/modules/expansion/xforceexchange.py index 8a01e77..5d67a9b 100644 --- a/misp_modules/modules/expansion/xforceexchange.py +++ b/misp_modules/modules/expansion/xforceexchange.py @@ -1,7 +1,7 @@ import requests import json - import sys + BASEurl = "https://api.xforce.ibmcloud.com/" extensions = {"ip1": "ipr/%s", @@ -69,12 +69,12 @@ def handler(q=False): return r def apicall(indicator_type, indicator, key=False): - #try: + try: myURL = BASEurl + (extensions[str(indicator_type)])%indicator jsondata = requests.get(myURL, headers=MyHeader(key)).json() - #except: - #return None - return jsondata + except: + return None + return jsondata def introspection(): return mispattributes From de3495ea6cc8dcbc8d4404a081b55f0c5b7079b2 Mon Sep 17 00:00:00 2001 From: Joerg Stephan Date: Wed, 1 Feb 2017 14:05:29 +0100 Subject: [PATCH 6/6] passed local run check --- .../modules/expansion/xforceexchange.py | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/misp_modules/modules/expansion/xforceexchange.py b/misp_modules/modules/expansion/xforceexchange.py index 5d67a9b..459c69a 100644 --- a/misp_modules/modules/expansion/xforceexchange.py +++ b/misp_modules/modules/expansion/xforceexchange.py @@ -5,16 +5,17 @@ import sys BASEurl = "https://api.xforce.ibmcloud.com/" extensions = {"ip1": "ipr/%s", - "ip2": "ipr/malware/%s", - "url": "url/%s", - "hash": "malware/%s", - "vuln": "/vulnerabilities/search/%s"} + "ip2": "ipr/malware/%s", + "url": "url/%s", + "hash": "malware/%s", + "vuln": "/vulnerabilities/search/%s", + "dns": "resolve/%s"} sys.path.append('./') misperrors = {'error': 'Error'} mispattributes = {'input': ['ip-src','ip-dst' 'vulnerability', 'md5', 'sha1', 'sha256'], - 'output': ['ip-src', 'ip-dst', 'text']} + 'output': ['ip-src', 'ip-dst', 'text', 'domain']} # possible module-types: 'expansion', 'hover' or both moduleinfo = {'version': '1', 'author': 'Joerg Stephan (@johest)', @@ -49,9 +50,9 @@ def handler(q=False): r = {"results": []} if "ip-src" in q: - r["results"] += dict( (apicall("ip1", q["ip-src"], key)).items() + (apicall("ip2", q["ip-src"], key)).items()) + r["results"] += apicall("dns", q["ip-src"], key) if "ip-dst" in q: - r["results"] += dict( (apicall("ip1", q["ip-src"], key)).items() + (apicall("ip2", q["ip-src"], key)).items()) + r["results"] += apicall("dns", q["ip-dst"], key) if "md5" in q: r["results"] += apicall("hash", q["md5"], key) if "sha1" in q: @@ -60,6 +61,8 @@ def handler(q=False): r["results"] += apicall("hash", q["sha256"], key) if 'vulnerability' in q: r["results"] += apicall("vuln", q["vulnerability"], key) + if "domain" in q: + r["results"] += apicall("dns", q["domain"], key) uniq = [] for res in r["results"]: @@ -73,8 +76,21 @@ def apicall(indicator_type, indicator, key=False): myURL = BASEurl + (extensions[str(indicator_type)])%indicator jsondata = requests.get(myURL, headers=MyHeader(key)).json() except: - return None - return jsondata + jsondata = None + redata = [] + #print(jsondata) + if not jsondata is None: + if indicator_type is "hash": + if "malware" in jsondata: + lopointer = jsondata["malware"] + redata.append({"type": "text", "values": lopointer["risk"]}) + if indicator_type is "dns": + if "records" in str(jsondata): + lopointer = jsondata["Passive"]["records"] + for dataset in lopointer: + redata.append({"type":"domain", "values": dataset["value"]}) + + return redata def introspection(): return mispattributes @@ -82,4 +98,4 @@ def introspection(): def version(): moduleinfo['config'] = moduleconfig - return moduleinfo \ No newline at end of file + return moduleinfo