Skip to content

Commit

Permalink
Merge pull request #463 from ninoseki/add-ipinfo-analyzer
Browse files Browse the repository at this point in the history
Add IPinfo analyzer
  • Loading branch information
3c7 authored Dec 17, 2019
2 parents 087a5ea + 6f20909 commit e02c866
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 0 deletions.
21 changes: 21 additions & 0 deletions analyzers/IPinfo/IPinfo_Details.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "IPinfo_Details",
"version": "1.0",
"author": "Manabu Niseki",
"url": "https://github.com/ninoseki/ipinfo-analyzers",
"license": "MIT",
"description": "IPinfo details lookup.",
"dataTypeList": ["ip"],
"command": "IPinfo/ipinfo_analyzer.py",
"baseConfig": "IPinfo",
"config": {
"service": "details"
},
"configurationItems": [{
"name": "api_key",
"description": "Define the API key to use to connect the service",
"type": "string",
"multi": false,
"required": true
}]
}
21 changes: 21 additions & 0 deletions analyzers/IPinfo/IPinfo_Hosted_Domains.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "IPinfo_Hosted_Domains",
"version": "1.0",
"author": "Manabu Niseki",
"url": "https://github.com/ninoseki/ipinfo-analyzers",
"license": "MIT",
"description": "IPinfo hosted domains lookup.",
"dataTypeList": ["ip"],
"command": "IPinfo/ipinfo_analyzer.py",
"baseConfig": "IPinfo",
"config": {
"service": "hosted_domains"
},
"configurationItems": [{
"name": "api_key",
"description": "Define the API key to use to connect the service",
"type": "string",
"multi": false,
"required": true
}]
}
39 changes: 39 additions & 0 deletions analyzers/IPinfo/ipinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3

import requests


class IPinfoException(Exception):
pass


class IPinfo():
def __init__(self, api_key):
self.base_url = "https://ipinfo.io"
self.api_key = api_key

if self.api_key is None:
raise IPinfoException("No API key is present")

self.session = requests.Session()
self.session.headers.update(
{"Authorization": "Bearer {}".format(self.api_key)})

def details(self, ip_address):
url = "{}/{}".format(self.base_url, ip_address)
return self._request(url)

def hosted_domains(self, ip_address):
url = "{}/domains/{}".format(self.base_url, ip_address)
return self._request(url)

def _request(self, url):
res = self.session.request("GET", url)

if res.status_code != 200:
raise IPinfoException("IPinfo returns {}".format(res.status_code))

if res.text == "":
return {}

return res.json()
72 changes: 72 additions & 0 deletions analyzers/IPinfo/ipinfo_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# encoding: utf-8

from cortexutils.analyzer import Analyzer
from ipinfo import IPinfoException, IPinfo


class IPinfoAnalyzer(Analyzer):
def __init__(self):
Analyzer.__init__(self)
self.service = self.get_param(
"config.service", None, "IPinfo service is missing")

self.api_key = self.get_param(
"config.api_key", None, "IPinfo API key is missing")

def summary(self, raw):
taxonomies = []
level = "info"
namespace = "IPinfo"

if self.service == "details":
country = raw.get("country")
if country:
taxonomies.append(
self.build_taxonomy(level, namespace, "Country", country)
)

asn = raw.get("asn")
if asn and asn.get("asn"):
taxonomies.append(
self.build_taxonomy(
level, namespace, "ASN", asn.get("asn"))
)

elif self.service == "hosted_domains":
total = 0
if "domains" in raw:
total = len(raw["domains"])

if total < 2:
value = "{} record".format(total)
else:
value = "{} records".format(total)

taxonomies.append(
self.build_taxonomy(level, namespace, "HostedDomains", value)
)

return {"taxonomies": taxonomies}

def run(self):
data = self.get_data()

try:
ipinfo = IPinfo(api_key=self.api_key)

if self.service == "details":
result = ipinfo.details(data)
self.report(result)
elif self.service == "hosted_domains":
result = ipinfo.hosted_domains(data)
self.report(result)
else:
self.error("Unknown IPinfo service")

except IPinfoException as e:
self.error(str(e))


if __name__ == "__main__":
IPinfoAnalyzer().run()
2 changes: 2 additions & 0 deletions analyzers/IPinfo/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
requests
51 changes: 51 additions & 0 deletions thehive-templates/IPinfo_Details_1.0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div class="report" ng-if="success">
<div class="panel panel-info">
<div class="panel-heading">IPinfo details ({{ content.ip || "-" }})</div>
<div class="panel-body">
<div ng-if="(content | json) === '{}'">
No data found
</div>
<div ng-if="(content | json) !== '{}'">
<dl class=" dl-horizontal">
<dt>Hostname:</dt>
<dd class="wrap">{{ content.hostname || "-" }}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Country:</dt>
<dd class="wrap">{{ content.country || "-" }}</dd>
</dl>
<div ng-if="content.asn !== {}">
<dl class="dl-horizontal">
<dt>ASN:</dt>
<dd class="wrap">
{{ content.asn.asn || "-" }} / {{ content.asn.name || "-" }}
</dd>
</dl>
<dl class="dl-horizontal">
<dt>Route:</dt>
<dd class="wrap">{{ content.asn.route || "-" }}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Type:</dt>
<dd class="wrap">{{ content.asn.type || "-" }}</dd>
</dl>
</div>
</div>
</div>
</div>
</div>

<!-- General error -->
<div class="panel panel-danger" ng-if="!success">
<div class="panel-heading">
<strong>{{ artifact.data | fang }}</strong>
</div>
<div class="panel-body">
<dl class="dl-horizontal" ng-if="content.errorMessage">
<dt>
<i class="fa fa-warning"></i>
</dt>
<dd class="wrap">{{ content.errorMessage }}</dd>
</dl>
</div>
</div>
4 changes: 4 additions & 0 deletions thehive-templates/IPinfo_Details_1.0/short.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<span class="label" ng-repeat="t in content.taxonomies"
ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]">
{{t.namespace}}:{{t.predicate}}="{{t.value}}"
</span>
42 changes: 42 additions & 0 deletions thehive-templates/IPinfo_Hosted_Domains_1.0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="report" ng-if="success">
<div class="panel panel-info">
<div class="panel-heading">
IPinfo hosted domains
</div>
<div class="panel-body">
<div ng-if="(content | json) === '{}'">
No data found
</div>
<div ng-if="(content | json) !== '{}'">
<div ng-if="content.domains.length === 0">
No domains found
</div>
<div ng-if="content.domains.length !== 0">
<table class="table table-hover">
<tr>
<th>Domain</th>
</tr>
<tr ng-repeat="domain in content.domains">
<td>{{ domain }}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>

<!-- General error -->
<div class="panel panel-danger" ng-if="!success">
<div class="panel-heading">
<strong>{{ artifact.data | fang }}</strong>
</div>
<div class="panel-body">
<dl class="dl-horizontal" ng-if="content.errorMessage">
<dt>
<i class="fa fa-warning"></i>
</dt>
<dd class="wrap">{{ content.errorMessage }}</dd>
</dl>
</div>
</div>
4 changes: 4 additions & 0 deletions thehive-templates/IPinfo_Hosted_Domains_1.0/short.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<span class="label" ng-repeat="t in content.taxonomies"
ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]">
{{t.namespace}}:{{t.predicate}}="{{t.value}}"
</span>

0 comments on commit e02c866

Please sign in to comment.