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 IP2Location.io expansion module #645

Merged
merged 3 commits into from
Dec 12, 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 @@ -49,6 +49,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj
* [html_to_markdown](misp_modules/modules/expansion/html_to_markdown.py) - Simple HTML to markdown converter
* [HYAS Insight](misp_modules/modules/expansion/hyasinsight.py) - a hover and expansion module to get information from [HYAS Insight](https://www.hyas.com/hyas-insight).
* [intel471](misp_modules/modules/expansion/intel471.py) - an expansion module to get info from [Intel471](https://intel471.com).
* [IP2Location.io](misp_modules/modules/expansion/ip2locationio.py) - an expansion module to get additional information on an IP address using the IP2Location.io API
* [IPASN](misp_modules/modules/expansion/ipasn.py) - a hover and expansion to get the BGP ASN of an IP address.
* [ipinfo.io](misp_modules/modules/expansion/ipinfo.py) - an expansion module to get additional information on an IP address using the ipinfo.io API
* [iprep](misp_modules/modules/expansion/iprep.py) - an expansion module to get IP reputation from packetmail.net.
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ For more information: [Extending MISP with Python modules](https://www.circl.lu/
* [hashdd](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/hashdd.py) - a hover module to check file hashes against [hashdd.com](http://www.hashdd.com) including NSLR dataset.
* [hibp](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/hibp.py) - a hover module to lookup against Have I Been Pwned?
* [intel471](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/intel471.py) - an expansion module to get info from [Intel471](https://intel471.com).
* [IP2Location.io](misp_modules/modules/expansion/ip2locationio.py) - an expansion module to get additional information on an IP address using the IP2Location.io API
* [IPASN](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/ipasn.py) - a hover and expansion to get the BGP ASN of an IP address.
* [iprep](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/iprep.py) - an expansion module to get IP reputation from packetmail.net.
* [Joe Sandbox submit](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/joesandbox_submit.py) - Submit files and URLs to Joe Sandbox.
Expand Down
Binary file added docs/logos/ip2locationio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/logos/ip2locationio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions documentation/website/expansion/ip2locationio.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"description": "An expansion module to query IP2Location.io to gather more information on a given IP address.",
"logo": "ip2locationio.png",
"requirements": [
"An IP2Location.io token"
],
"input": "IP address attribute.",
"output": "Additional information on the IP address, such as geolocation, proxy and so on. Refer to the Response Format section in https://www.ip2location.io/ip2location-documentation to find out the full format of the data returned.",
"references": [
"https://www.ip2location.io/ip2location-documentation"
],
"features": "The module takes an IP address attribute as input and queries the IP2Location.io API. \nFree plan user will get the basic geolocation informaiton, and different subsription plan will get more information on the IP address. \n Refer to [pricing page](https://www.ip2location.io/pricing) for more information on data available for each plan. \n\nMore information on the responses content is available in the [documentation](https://www.ip2location.io/ip2location-documentation)."
}
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']
'extract_url_components', 'ipinfo', 'whoisfreaks', 'ip2locationio']


minimum_required_fields = ('type', 'uuid', 'value')
Expand Down
83 changes: 83 additions & 0 deletions misp_modules/modules/expansion/ip2locationio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import json
import requests
from . import check_input_attribute, standard_error_message
from pymisp import MISPAttribute, MISPEvent, MISPObject

mispattributes = {
'input': ['ip-src', 'ip-dst'],
'format': 'misp_standard'
}
moduleinfo = {
'version': 1,
'author': 'IP2Location.io',
'description': 'An expansion module to query IP2Location.io for additional information on an IP address',
'module-type': ['expansion', 'hover']
}
moduleconfig = ['key']

_GEOLOCATION_OBJECT_MAPPING = {
'country_code': 'countrycode',
'country_name': 'country',
'region_name': 'region',
'city_name': 'city',
'zip_code': 'zipcode',
'latitude': 'latitude',
'longitude': 'longitude'
}


def handler(q=False):
# Input checks
if q is False:
return False
request = json.loads(q)
if not request.get('attribute') or not check_input_attribute(request['attribute']):
return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'}
attribute = request['attribute']
if attribute.get('type') not in mispattributes['input']:
return {'error': 'Wrong input attribute type.'}
if not request.get('config'):
return {'error': 'Missing ip2locationio config.'}
if not request['config'].get('key'):
return {'error': 'Missing ip2locationio API key.'}

# Query ip2location.io
query = requests.get(
f"https://api.ip2location.io/json?key={request['config']['key']}&ip={attribute['value']}"
)
if query.status_code != 200:
return {'error': f'Error while querying ip2location.io - {query.status_code}: {query.reason}'}
iplio_result = query.json()

# Check if the IP address is not reserved for special use
# if ipinfo.get('bogon', False):
if '' in iplio_result and iplio_result[''] == 'RSV':
return {'error': 'The IP address is reserved for special use'}

# Initiate the MISP data structures
misp_event = MISPEvent()
input_attribute = MISPAttribute()
input_attribute.from_dict(**attribute)
misp_event.add_attribute(**input_attribute)

# Parse the geolocation information related to the IP address
geolocation = MISPObject('geolocation')
for field, relation in _GEOLOCATION_OBJECT_MAPPING.items():
geolocation.add_attribute(relation, iplio_result[field])
geolocation.add_reference(input_attribute.uuid, 'locates')
misp_event.add_object(geolocation)

# Return the results in MISP format
event = json.loads(misp_event.to_json())
return {
'results': {key: event[key] for key in ('Attribute', 'Object')}
}


def introspection():
return mispattributes


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