Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Vysion expansion module #646

Merged
merged 10 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj
* [VMware NSX](misp_modules/modules/expansion/vmware_nsx.py) - a module to enrich a file or URL with VMware NSX Defender.
* [VulnDB](misp_modules/modules/expansion/vulndb.py) - a module to query [VulnDB](https://www.riskbasedsecurity.com/).
* [Vulners](misp_modules/modules/expansion/vulners.py) - an expansion module to expand information about CVEs using Vulners API.
* [Vysion](misp-modules/misp_modules/modules/expansion/vysion.py) - an expansion module to add dark web intelligence using Vysion API.
* [whois](misp_modules/modules/expansion/whois.py) - a module to query a local instance of [uwhois](https://github.com/rafiot/uwhoisd).
* [whoisfreaks](misp_modules/modules/expansion/whoisfreaks.py) - An expansion module for [whoisfreaks](https://whoisfreaks.com/) that will provide an enriched analysis of the provided domain, including WHOIS and DNS information.
* [wikidata](misp_modules/modules/expansion/wiki.py) - a [wikidata](https://www.wikidata.org) expansion module.
Expand Down
1 change: 1 addition & 0 deletions REQUIREMENTS
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ validators==0.14.0
vt-graph-api==2.2.0
vt-py==0.17.5
vulners==2.0.10
vysion==1.0.10
wand==0.6.11
websocket-client==1.5.1 ; python_version >= '3.7'
websockets==11.0.3 ; python_version >= '3.7'
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ For more information: [Extending MISP with Python modules](https://www.circl.lu/
* [VMray](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/vmray_submit.py) - a module to submit a sample to VMray.
* [VulnDB](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/vulndb.py) - a module to query [VulnDB](https://www.riskbasedsecurity.com/).
* [Vulners](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/vulners.py) - an expansion module to expand information about CVEs using Vulners API.
* [Vysion](misp-modules/misp_modules/modules/expansion/vysion.py) - an expansion module to add dark web intelligence using Vysion API.
* [whois](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/whois.py) - a module to query a local instance of [uwhois](https://github.com/rafiot/uwhoisd).
* [wikidata](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/wiki.py) - a [wikidata](https://www.wikidata.org) expansion module.
* [xforce](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/xforceexchange.py) - an IBM X-Force Exchange expansion module.
Expand Down
Binary file added docs/logos/vysion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1904,6 +1904,26 @@ An expansion hover module to expand information about CVE id using Vulners API.

-----

#### [Vysion](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/vysion.py)

<img src=logos/vysion.png height=60>

Module to enrich the information by making use of the Vysion API.
- **features**:
>This module gets correlated information from our dark web intelligence database. With this you will get several objects containing information related to, for example, an organization victim of a ransomware attack.
>MISP objects containing title, link to our webapp and TOR, i2p or clearnet URLs.
- **input**:
>MISP Attribute which include: company(target-org), country, info.
- **output**:
>MISP objects containing title, link to our webapp and TOR, i2p or clearnet URLs.
- **references**:
>https://vysion.ai/
- **requirements**:
> Vysion python library
> Vysion API Key

-----

#### [whois](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/whois.py)

Module to query a local instance of uwhois (https://github.com/rafiot/uwhoisd).
Expand Down
Binary file added documentation/logos/vysion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions documentation/website/expansion/vysion.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"description": "Module to enrich the information by making use of the Vysion API.",
"logo": "vysion.png",
"requirements": [
"Vysion python library",
"Vysion API Key"
],
"input": "MISP Attribute which include: company(target-org), country, info.",
"output": "MISP objects containing title, link to our webapp and TOR, i2p or clearnet URLs.",
"references": [
"https://vysion.ai/",
"https://developers.vysion.ai/",
"https://github.com/ByronLabs/vysion-cti/tree/main"
],
"features": "This module gets correlated information from our dark web intelligence database. With this you will get several objects containing information related to, for example, an organization victim of a ransomware attack."
}
2 changes: 1 addition & 1 deletion misp_modules/modules/expansion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
'trustar_enrich', 'recordedfuture', 'html_to_markdown', 'socialscan', 'passive-ssh',
'qintel_qsentry', 'mwdb', 'hashlookup', 'mmdb_lookup', 'ipqs_fraud_and_risk_scoring',
'clamav', 'jinja_template_rendering','hyasinsight', 'variotdbs', 'crowdsec',
'extract_url_components', 'ipinfo', 'whoisfreaks', 'ip2locationio']
'extract_url_components', 'ipinfo', 'whoisfreaks', 'ip2locationio', 'vysion']


minimum_required_fields = ('type', 'uuid', 'value')
Expand Down
212 changes: 212 additions & 0 deletions misp_modules/modules/expansion/vysion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import json
from pymisp import MISPAttribute, MISPEvent
from urllib.parse import urlparse

import logging

import vysion.client as vysion

import vysion.dto as dto
from vysion.dto.util import MISPProcessor

misperrors = {"error": "Error"}
mispattributes = {
"input": [
"email",
"domain",
"hostname",
"url",
"text",
"btc",
"phone-number",
"target-org",
],
"format": "misp_standard",
}

# possible module-types: 'expansion', 'hover' or both
moduleinfo = {
"version": "1",
"author": "Byron Labs",
"description": "Enrich observables with the Vysion API",
"module-type": ["expansion"],
}

# config fields that your code expects from the site admin
moduleconfig = [
"apikey",
"event_limit",
"proxy_host",
"proxy_port",
"proxy_username",
"proxy_password",
]

LOGGER = logging.getLogger("vysion")
LOGGER.setLevel(logging.INFO)
LOGGER.info("Starting Vysion")

DEFAULT_RESULTS_LIMIT = 10


def get_proxy_settings(config: dict) -> dict:
"""Returns proxy settings in the requests format.
If no proxy settings are set, return None."""
proxies = None
host = config.get("proxy_host")
port = config.get("proxy_port")
username = config.get("proxy_username")
password = config.get("proxy_password")

if host:
if not port:
misperrors["error"] = (
"The vysion_proxy_host config is set, "
"please also set the vysion_proxy_port."
)
raise KeyError
parsed = urlparse(host)
if "http" in parsed.scheme:
scheme = "http"
else:
scheme = parsed.scheme
netloc = parsed.netloc
host = f"{netloc}:{port}"

if username:
if not password:
misperrors["error"] = (
"The vysion_proxy_username config is set, "
"please also set the vysion_proxy_password."
)
raise KeyError
auth = f"{username}:{password}"
host = auth + "@" + host

proxies = {"http": f"{scheme}://{host}", "https": f"{scheme}://{host}"}
return proxies


def parse_error(status_code: int) -> str:

status_mapping = {
500: "Vysion is blind.",
400: "Incorrect request, please check the arguments.",
403: "You don't have enough privileges to make the request.",
}

if status_code in status_mapping:
return status_mapping[status_code]

return "Vysion may not be accessible."


def handler(q=False):

if q is False:
return False

request = json.loads(q)

if not request.get("config") or not request["config"].get("apikey"):
misperrors["error"] = "A Vysion api key is required for this module."
return misperrors

if not request.get("attribute"):
return {
"error": "The request is missing required attribute information, which should contain at least a type, a value, and a UUID."
}

if request["attribute"]["type"] not in mispattributes["input"]:
return {"error": "Unsupported attribute type."}

# event_limit = request["config"].get("event_limit")
attribute = request["attribute"]
proxy_settings = get_proxy_settings(request.get("config"))

try:

client = vysion.Client(
api_key=request["config"]["apikey"],
headers={
"x-tool": "MISPModuleVysionExpansion",
},
proxy=proxy_settings["http"] if proxy_settings else None,
)

LOGGER.debug(attribute)

misp_attribute = MISPAttribute()
misp_attribute.from_dict(**attribute)

attribute_type = misp_attribute.type
attribute_value = misp_attribute.value

# https://www.misp-project.org/datamodels/#types

LOGGER.debug(attribute_type)

result = None

if attribute_type == "email":
result = client.find_email(attribute_value)
elif attribute_type == "domain":
result = client.search(attribute_value)
elif attribute_type == "url":
result = client.search(
attribute_value
) # TODO result = client.find_url(attribute_value)
elif attribute_type == "text":
result = client.search(attribute_value)
elif attribute_type == "target-org":
result = client.search(attribute_value, exact=True)
elif attribute_type == "btc":
result = client.search(attribute_value) # TODO
elif attribute_type == "phone-number":
result = client.search(attribute_value) # TODO

if result is None:
return {"results": {}}
elif isinstance(result, dto.VysionError):
LOGGER.error(str(result))
return {"results": {}}

p = MISPProcessor()
misp_event: MISPEvent = p.process(result, ref_attribute=misp_attribute)

LOGGER.info("Vysion client initialized")

LOGGER.info("Vysion result obtained")

return {
"results": {
"Object": [
json.loads(object.to_json()) for object in misp_event.objects
],
"Attribute": [
json.loads(attribute.to_json())
for attribute in misp_event.attributes
],
"Tag": [
json.loads(tag.to_json())
for tag in misp_event.tags
]
}
}

except vysion.APIError as ex:

LOGGER.error("Error in Vysion")
LOGGER.error(ex)

misperrors["error"] = ex.message
return misperrors


def introspection():
return mispattributes


def version():
moduleinfo["config"] = moduleconfig
return moduleinfo
Loading