mirror of https://github.com/MISP/misp-modules
Add crowdsec module
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>pull/590/head
parent
eaebba2912
commit
382d8036d9
|
@ -27,6 +27,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj
|
|||
* [CIRCL Passive DNS](misp_modules/modules/expansion/circl_passivedns.py) - a hover and expansion module to expand hostname and IP addresses with passive DNS information.
|
||||
* [CIRCL Passive SSL](misp_modules/modules/expansion/circl_passivessl.py) - a hover and expansion module to expand IP addresses with the X.509 certificate(s) seen.
|
||||
* [countrycode](misp_modules/modules/expansion/countrycode.py) - a hover module to tell you what country a URL belongs to.
|
||||
* [CrowdSec](misp_modules/modules/expansion/crowdsec.py) - a hover module to expand using CrowdSec's CTI API.
|
||||
* [CrowdStrike Falcon](misp_modules/modules/expansion/crowdstrike_falcon.py) - an expansion module to expand using CrowdStrike Falcon Intel Indicator API.
|
||||
* [CPE](misp_modules/modules/expansion/cpe.py) - An expansion module to query the CVE Search API with a cpe code, to get its related vulnerabilities.
|
||||
* [CVE](misp_modules/modules/expansion/cve.py) - a hover module to give more information about a vulnerability (CVE).
|
||||
|
|
|
@ -106,6 +106,7 @@ git+https://github.com/sebdraven/pydnstrails@48c1f740025c51289f43a24863d1845ff12
|
|||
pyeupi==1.1
|
||||
pyfaup==1.2
|
||||
pygeoip==0.3.2
|
||||
pycountry==22.3.5
|
||||
pygments==2.13.0 ; python_version >= '3.6'
|
||||
git+https://github.com/MISP/PyIntel471.git@917272fafa8e12102329faca52173e90c5256968#egg=pyintel471
|
||||
git+https://github.com/D4-project/IPASN-History.git/@a2853c39265cecdd0c0d16850bd34621c0551b87#egg=pyipasnhistory&subdirectory=client
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
import json
|
||||
|
||||
from pymisp import MISPEvent, MISPObject
|
||||
import pycountry
|
||||
import requests
|
||||
|
||||
mispattributes = {"input": ["ip-dst", "ip-src"], "output": ["text"]}
|
||||
moduleinfo = {
|
||||
"version": "1.0",
|
||||
"author": "Shivam Sandbhor <shivam@crowdsec.net>",
|
||||
"description": "Module to access CrowdSec CTI API.",
|
||||
"module-type": ["hover"],
|
||||
}
|
||||
moduleconfig = ["api_key", "api_version"]
|
||||
|
||||
|
||||
def handler(q=False):
|
||||
if q is False:
|
||||
return False
|
||||
|
||||
request = json.loads(q)
|
||||
if not request.get("config"):
|
||||
return {"error": "Missing CrowdSec Config"}
|
||||
|
||||
if not request["config"].get("api_key"):
|
||||
return {"error": "Missing CrowdSec API key"}
|
||||
|
||||
if not request["config"].get("api_version"):
|
||||
return {"error": "Missing CrowdSec API version parameter"}
|
||||
|
||||
if request["config"]["api_version"] == "v2":
|
||||
return _handler_v2(request)
|
||||
return {"error": f'API version {request["config"]["api_version"]} not supported'}
|
||||
|
||||
|
||||
def _handler_v2(request_data):
|
||||
if request_data.get("ip-dst"):
|
||||
ip = request_data.get("ip-dst")
|
||||
elif request_data.get("ip-src"):
|
||||
ip = request_data.get("ip-src")
|
||||
|
||||
crowdsec_cti = requests.get(
|
||||
f"https://cti.api.crowdsec.net/v2/smoke/{ip}",
|
||||
headers={"x-api-key": request_data["config"]["api_key"]},
|
||||
)
|
||||
crowdsec_cti.raise_for_status()
|
||||
crowdsec_cti = crowdsec_cti.json()
|
||||
|
||||
misp_event = MISPEvent()
|
||||
crowdsec_context_object = MISPObject("crowdsec-ip-context")
|
||||
crowdsec_context_object.add_attribute("IP Address", **{"type": "text", "value": ip})
|
||||
crowdsec_context_object.add_attribute(
|
||||
"IP Range", **{"type": "text", "value": crowdsec_cti["ip_range"]}
|
||||
)
|
||||
crowdsec_context_object.add_attribute(
|
||||
"IP Range Score", **{"type": "text", "value": crowdsec_cti["ip_range_score"]}
|
||||
)
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Country",
|
||||
**{
|
||||
"type": "text",
|
||||
"value": get_country_name_from_alpha_2(crowdsec_cti["location"]["country"]),
|
||||
},
|
||||
)
|
||||
if crowdsec_cti["location"]["city"]:
|
||||
crowdsec_context_object.add_attribute(
|
||||
"City", **{"type": "text", "value": crowdsec_cti["location"]["city"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Latitude", **{"type": "float", "value": crowdsec_cti["location"]["latitude"]}
|
||||
)
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Longitude", **{"type": "float", "value": crowdsec_cti["location"]["longitude"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"AS Name", **{"type": "text", "value": crowdsec_cti["as_name"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"AS Number", **{"type": "AS", "value": crowdsec_cti["as_num"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Reverse DNS", **{"type": "domain", "value": crowdsec_cti["reverse_dns"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Attack Categories",
|
||||
**{
|
||||
"type": "text",
|
||||
"value": ",".join(
|
||||
[attack_category["label"] for attack_category in crowdsec_cti["behaviors"]]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Triggered Scenarios",
|
||||
**{
|
||||
"type": "text",
|
||||
"value": ",".join([scenario["name"] for scenario in crowdsec_cti["attack_details"]]),
|
||||
},
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Top 10 Target Countries",
|
||||
**{
|
||||
"type": "float",
|
||||
"value": ",".join(
|
||||
map(get_country_name_from_alpha_2, crowdsec_cti["target_countries"].keys())
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Trust", **{"type": "float", "value": crowdsec_cti["scores"]["overall"]["trust"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"First Seen", **{"type": "datetime", "value": crowdsec_cti["history"]["first_seen"]}
|
||||
)
|
||||
|
||||
crowdsec_context_object.add_attribute(
|
||||
"Last Seen", **{"type": "datetime", "value": crowdsec_cti["history"]["last_seen"]}
|
||||
)
|
||||
|
||||
for time_period, indicators in crowdsec_cti["scores"].items():
|
||||
tp = " ".join(map(str.capitalize, time_period.split("_")))
|
||||
|
||||
for indicator_type, indicator_value in indicators.items():
|
||||
crowdsec_context_object.add_attribute(
|
||||
f"{tp} {indicator_type.capitalize()}", **{"type": "float", "value": indicator_value}
|
||||
)
|
||||
|
||||
misp_event.add_object(crowdsec_context_object)
|
||||
|
||||
event = json.loads(misp_event.to_json())
|
||||
results = {key: event[key] for key in ("Attribute", "Object") if (key in event and event[key])}
|
||||
return {"results": results}
|
||||
|
||||
|
||||
def get_country_name_from_alpha_2(alpha_2):
|
||||
country_info = pycountry.countries.get(alpha_2=alpha_2)
|
||||
return country_info.name
|
||||
|
||||
|
||||
def introspection():
|
||||
return mispattributes
|
||||
|
||||
|
||||
def version():
|
||||
moduleinfo["config"] = moduleconfig
|
||||
return moduleinfo
|
|
@ -15,5 +15,6 @@ __all__ = [
|
|||
'csvimport',
|
||||
'cof2misp',
|
||||
'joe_import',
|
||||
'taxii21'
|
||||
'taxii21',
|
||||
'crowdsec'
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue