Skip to content

Commit

Permalink
Merge pull request #735 from TheHive-Project/feature/anyrun
Browse files Browse the repository at this point in the history
add analyzer for any.run sandbox
  • Loading branch information
garanews authored Apr 24, 2020
2 parents 0ad2263 + d334660 commit 4654473
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 0 deletions.
28 changes: 28 additions & 0 deletions analyzers/AnyRun/AnyRun_Sandbox_Analysis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "AnyRun_Sandbox_Analysis",
"version": "1.0",
"author": "Andrea Garavaglia, Davide Arcuri, LDO-CERT",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "AGPL-V3",
"description": "Any.Run Sandbox file analysis",
"dataTypeList": ["file", "url"],
"command": "AnyRun/anyrun_analyzer.py",
"baseConfig": "AnyRun",
"configurationItems": [
{
"name": "token",
"description": "API token",
"type": "string",
"multi": false,
"required": false
},
{
"name": "verify_ssl",
"description": "Verify SSL certificate",
"type": "boolean",
"multi": false,
"required": true,
"defaultValue": true
}
]
}
130 changes: 130 additions & 0 deletions analyzers/AnyRun/anyrun_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
# encoding: utf-8
import time
import requests
from os.path import basename
from cortexutils.analyzer import Analyzer
from requests.packages.urllib3.exceptions import InsecureRequestWarning


class AnyRunAnalyzer(Analyzer):
def __init__(self):
Analyzer.__init__(self)
self.url = "https://api.any.run/v1"
self.token = self.get_param("config.token", None, "Service token is missing")
self.verify_ssl = self.get_param("config.verify_ssl", True, None)
if not self.verify_ssl:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def summary(self, raw):
taxonomies = []
level = "safe"
namespace = "AnyRun"
predicate = "Sandbox"
value = (
raw.get("analysis", {}).get("scores", {}).get("verdict", {}).get("score", 0)
)
if 50 < value < 100:
level = "suspicious"
elif value == 100:
level = "malicious"

taxonomies.append(
self.build_taxonomy(level, namespace, predicate, "{0}/100".format(value))
)

return {"taxonomies": taxonomies}

def run(self):
Analyzer.run(self)

try:
headers = {"Authorization": "API-Key {0}".format(self.token)}

status_code = None
tries = 0
if self.data_type == "file":
filepath = self.get_param("file", None, "File is missing")
filename = self.get_param("filename", basename(filepath))
while status_code in (None, 429) and tries <= 15:
with open(filepath, "rb") as sample:
files = {"file": (filename, sample)}
response = requests.post(
"{0}/analysis".format(self.url),
files=files,
headers=headers,
verify=self.verify_ssl,
)
status_code = response.status_code
if status_code == 200:
task_id = response.json()["data"]["taskid"]
elif status_code == 201:
task_id = response.json()["taskid"]
elif status_code == 429:
# it not support parallel runs, so we wait and resubmit later
time.sleep(60)
tries += 1
else:
self.error(response.json()["message"])
elif self.data_type == "url":
url = self.get_param("data", None, "Url is missing")
data = {"obj_type": "url", "obj_url": url}
while status_code in (None, 429) and tries <= 15:
response = requests.post(
"{0}/analysis".format(self.url),
data=data,
headers=headers,
verify=self.verify_ssl,
)
status_code = response.status_code
if status_code == 200:
task_id = response.json()["data"]["taskid"]
elif status_code == 201:
task_id = response.json()["taskid"]
elif status_code == 429:
# it not support parallel runs, so we wait and resubmit later
time.sleep(60)
tries += 1
else:
self.error(response.json()["message"])
else:
self.error("Invalid data type!")

finished = False
tries = 0
while not finished and tries <= 15: # wait max 15 mins
time.sleep(60)
response = requests.get(
"{0}/analysis/{1}".format(self.url, task_id),
headers=headers,
verify=self.verify_ssl,
)
if response.status_code == 200:
finished = (
True if response.json()["data"]["status"] == "done" else False
)
elif 400 < response.status_code < 500:
self.error(response.json()["message"])
tries += 1
if not finished:
self.error("AnyRun analysis timed out")

# this items could be huge, we provide link to the report so avoid them in cortex
final_report = response.json()["data"]
final_report.pop("environments", None)
final_report.pop("modified", None)
for incident in final_report.get("incidents", []):
incident.pop("events", None)
for process in final_report.get("processes", []):
process.pop("modules", None)
self.report(final_report)

except requests.exceptions.RequestException as e:
self.error(str(e))

except Exception as e:
self.unexpectedError(e)


if __name__ == "__main__":
AnyRunAnalyzer().run()
2 changes: 2 additions & 0 deletions analyzers/AnyRun/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
requests
132 changes: 132 additions & 0 deletions thehive-templates/AnyRun_Sandbox_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<div class="panel panel-success" ng-if="success">

<div class="panel-heading">
Any.Run Sandbox
</div>
<div class="panel-body">
<div>
<dl class="dl-horizontal">
<dt>Score:</dt><dd>{{content.analysis.scores.verdict.score}}/100</dd>
<dt>Threat Score:</dt>
<dd><span class="label" ng-class="{0: 'label-info', 1: 'label-warning', 2:'label-danger'}[content.analysis.scores.verdict.threatLevel]">{{content.analysis.scores.verdict.threatLevelText}}</dd>
<dt>Tags:</dt><dd><span ng-if="content.analysis.tags" ng-repeat="tag in content.analysis.tags" class="label label-info">{{tag.tag}}</span></dd>
</dl>
</div>

<div>
<h3>Link</h3>
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group"><a target="_blank" href="{{content.analysis.permanentUrl}}"><button type="button" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span>Report</button></a></div>
<div class="btn-group" role="group"><a target="_blank" href="{{content.analysis.reports.HTML}}"><button type="button" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span>Html</button></a></div>
<div class="btn-group" role="group"><a target="_blank" href="{{content.analysis.reports.graph}}"><button type="button" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span>Graph</button></a></div>
<div class="btn-group" role="group"><a target="_blank" href="{{content.analysis.reports.MISP}}"><button type="button" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span>MISP</button></a></div>
<div class="btn-group" role="group"><a target="_blank" href="{{content.analysis.reports.IOC}}"><button type="button" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span>IOC</button></a></div>
</div>
</div>

<div>
<h3>Counters</h3>
<div class="row">
<div class="col-md-3">
<h4>Registry</h4>
<dl class="dl-horizontal">
<dt>Read:</dt><dd>{{content.counters.registry.read}}</dd>
<dt>Write:</dt><dd>{{content.counters.registry.write}}</dd>
<dt>Delete:</dt><dd>{{content.counters.registry.delete}}</dd>
<dt>Total:</dt><dd>{{content.counters.registry.total}}</dd>
</dl>
</div>
<div class="col-md-3">
<h4>Processes</h4>
<dl class="dl-horizontal">
<dt>Monitored:</dt><dd>{{content.counters.processes.monitored}}</dd>
<dt>Suspicious:</dt><dd>{{content.counters.processes.suspicious}}</dd>
<dt>Malicious:</dt><dd>{{content.counters.processes.malicious}}</dd>
<dt>Total:</dt><dd>{{content.counters.processes.total}}</dd>
</dl>
</div>
<div class="col-md-3">
<h4>Files</h4>
<dl class="dl-horizontal">
<dt>Text:</dt><dd>{{content.counters.files.text}}</dd>
<dt>Suspicious:</dt><dd>{{content.counters.files.suspicious}}</dd>
<dt>Malicious:</dt><dd>{{content.counters.files.malicious}}</dd>
<dt>Unknown:</dt><dd>{{content.counters.files.unknown}}</dd>
</dl>
</div>
<div class="col-md-3">
<h4>Network</h4>
<dl class="dl-horizontal">
<dt>Dns:</dt><dd>{{content.counters.network.dns}}</dd>
<dt>Http:</dt><dd>{{content.counters.network.http}}</dd>
<dt>Connections:</dt><dd>{{content.counters.network.connections}}</dd>
<dt>Threats:</dt><dd>{{content.counters.network.threats}}</dd>
</dl>
</div>
</dl>
</div>

<div>
<h3>Scores</h3>
<div class="btn-group-xs btn-group-justified" role="group">
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.executableDropped" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.executableDropped]">Executable Dropped</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.crashedTask" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.crashedTask]">Crashed Task</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.torUsed" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.torUsed]">Tor Used</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.memOverrun" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.memOverrun]">Mem Overrun</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.stealing" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.stealing]">Stealing</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.networkLoader" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.networkLoader]">Network Loader</button></div>
</div>
<br/>
<div class="btn-group-xs btn-group-justified" role="group">
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.serviceLauncher" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.serviceLauncher]">Service Launcher</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.notStarted" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.notStarted]">Not Started</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.privEscalation" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.privEscalation]">Privilege Escalation</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.autostart" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.autostart]">Autostart</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.crashedApps" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.crashedApps]">Crashed Apps</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.rebooted" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.rebooted]">Rebooted</button></div>
</div>
<br/>
<div class="btn-group-xs btn-group-justified" role="group">
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.multiprocessing" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.multiprocessing]">Multiprocessing</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.injects" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.injects]">Injects</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.lowAccess" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.lowAccess]">Low Access</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.exploitable" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.exploitable]">Exploitable</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.suspStruct" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.suspStruct]">Suspicious Struct</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.staticDetections" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.staticDetections]">Static Detections</button></div>
</div>
<br/>
<div class="btn-group-xs btn-group-justified" role="group">
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.spam" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.spam]">Spam</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.networkThreats" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.networkThreats]">Network Threats</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.cpuOverrun" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.cpuOverrun]">Cpu Overrun</button></div>
<div class="btn-group" role="group"><button type="button" class="btn btn-default" ng-disabled="!content.analysis.scores.specs.debugOutput" ng-class="{true: 'btn-danger', false: 'btn-default'}[content.analysis.scores.specs.debugOutput]">Debug Output</button></div>
</div>
</div>

<div ng-if="content.mitre.length > 0">
<h3>Mitre</h3>
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group" ng-repeat="mitre in content.mitre">
<a href="https://attack.mitre.org/techniques/{{mitre.id}}/" target="_blank" title="{{mitre.name}}">
<button type="button" class="btn btn-default">
<span style="font-weight: bolder">{{mitre.id}}</span>
</button>
</a>
</div>
</div>
</div>
</div>
</div>

<!-- on error -->
<div class="panel panel-danger" ng-if="!success">
<div class="panel-heading">
Any.Run Sandbox <b>Error</b>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt>Error: </dt>
<dd>{{content.errorMessage}}</dd>
</dl>
</div>
</div>
3 changes: 3 additions & 0 deletions thehive-templates/AnyRun_Sandbox_1_0/short.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<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>&nbsp;

0 comments on commit 4654473

Please sign in to comment.