From 82154b3d36bfd58a93562e4a1128e07ed592fec6 Mon Sep 17 00:00:00 2001 From: Sebastian Schmerl - Computacenter Date: Thu, 18 Jun 2020 14:06:37 +0200 Subject: [PATCH 1/3] Added a Analyzer for Crowdstrikes Falcon X Sandbox On branch Crowdstrike-Sandbox-Analyzer Changes to be committed: new file: analyzers/FalconSandbox/FalconSandbox.json new file: analyzers/FalconSandbox/FalconSandbox.py new file: analyzers/FalconSandbox/long.html new file: analyzers/FalconSandbox/requirements.txt new file: analyzers/FalconSandbox/short.html added by Sebastian Schmerl (sebastian.schmerl@gmail.com) --- analyzers/FalconSandbox/FalconSandbox.json | 35 ++++ analyzers/FalconSandbox/FalconSandbox.py | 188 +++++++++++++++++++++ analyzers/FalconSandbox/long.html | 25 +++ analyzers/FalconSandbox/requirements.txt | 5 + analyzers/FalconSandbox/short.html | 3 + 5 files changed, 256 insertions(+) create mode 100755 analyzers/FalconSandbox/FalconSandbox.json create mode 100755 analyzers/FalconSandbox/FalconSandbox.py create mode 100755 analyzers/FalconSandbox/long.html create mode 100755 analyzers/FalconSandbox/requirements.txt create mode 100755 analyzers/FalconSandbox/short.html diff --git a/analyzers/FalconSandbox/FalconSandbox.json b/analyzers/FalconSandbox/FalconSandbox.json new file mode 100755 index 000000000..a13751262 --- /dev/null +++ b/analyzers/FalconSandbox/FalconSandbox.json @@ -0,0 +1,35 @@ +{ + "name": "FalconSandbox", + "version": "1.0", + "author": "Sebastian.Schmerl - Computacenter", + "url": "https://www.crowdstrike.com/blog/tech-center/get-access-falcon-apis/", + "license": "AGPL", + "description": "Submit observables to the Crowdstrike FalconX Sandbox", + "dataTypeList": ["file"], + "command": "FalconSandbox/FalconSandbox.py", + "baseConfig": "FalconSandbox", + "configurationItems": [ + { + "name": "OAuth2_Url", + "description": "Crowdstrike Api OAuth2 url", + "type": "string", + "multi": false, + "required": true, + "default":"https://api.crowdstrike.com/oauth2/token" + }, + { + "name": "Client_ID", + "description": "Crowdstrike Api ClientID", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "Client_Secret", + "description": "Crowdstrike Api Client Secret", + "type": "string", + "multi": false, + "required": true + } + ] +} diff --git a/analyzers/FalconSandbox/FalconSandbox.py b/analyzers/FalconSandbox/FalconSandbox.py new file mode 100755 index 000000000..ac54cba9b --- /dev/null +++ b/analyzers/FalconSandbox/FalconSandbox.py @@ -0,0 +1,188 @@ +#!/usr/bin/python2 +# -*- coding: utf-8 -*- + +import requests +import re +import json +import traceback +import hashlib +import time + +from cortexutils.analyzer import Analyzer +from requests.auth import HTTPBasicAuth +from oauthlib.oauth2 import BackendApplicationClient +from requests_oauthlib import OAuth2Session + +class FalconSandbox(Analyzer): + def __init__(self): + Analyzer.__init__(self) + self.OAuth2_Url = self.get_param('config.OAuth2_Url', None, "Falcon OAuth2 URL missing (e.g.:https://api.crowdstrike.com/self.oauth2/token)") + self.Client_ID = self.get_param( + 'config.Client_ID', None, "Falcon ClientID missing") + self.Client_Secret = self.get_param( + 'config.Client_Secret', None, "Falcon Client_Secret missing") + self.client = BackendApplicationClient(client_id=self.Client_ID) + self.oauth = OAuth2Session(client=self.client) + self.token = self.oauth.fetch_token(token_url=self.OAuth2_Url, client_id=self.Client_ID, client_secret=self.Client_Secret) + + + def summary(self, raw): + taxonomies = [] + level = "info" + namespace = "CS-Sandbox" + predicate = "Threat-Score" + value = "0" + result = { + "has_result": True + } + value = str(raw['resources'][0]['sandbox'][0]['threat_score']) + level = str(raw['resources'][0]['sandbox'][0]['verdict']) + #switch results to thehive summary labels + #ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]"> + switcher={ + 'no verdict':'info', + 'No Specific Threat':'safe', + 'suspicious':'suspicious', + 'malicious':'malicious' + } + level = switcher.get(level, "invalid") + if level == "invalid": + predicate = predicate + "invalid level" + level = "info" + + taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) + return {"taxonomies": taxonomies} + + + def CalcSHA256Hash(self, filepath): + # BUF_SIZE is totally arbitrary, change for your app! + BUF_SIZE = 65536 # lets read stuff in 64kb chunks! + l_sha256 = hashlib.sha256() + with open(filepath, 'rb') as f: + while True: + l_data = f.read(BUF_SIZE) + if not l_data: + break + l_sha256.update(l_data) + + l_own_sha256 = l_sha256.hexdigest() + return l_own_sha256 + + def RestAPIRequest(self, method, url, headers, data): + l_json_response = "{}" + if method == "get": + response = self.oauth.get(url, data=data, headers=headers) + if method == "post": + response = self.oauth.post(url, data=data, headers=headers) + if method == "delete": + response = self.oauth.delete(url, data=data, headers=headers) + l_json_response = json.loads(response.text) + + if l_json_response["errors"]: + if l_json_response["errors"][0]["code"] == 403: + ## ok, we need a new token + self.client = BackendApplicationClient(client_id=self.Client_ID) + self.oauth = OAuth2Session(client=self.client) + self.token = self.oauth.fetch_token(token_url=self.OAuth2_Url, client_id=self.Client_ID, client_secret=self.Client_Secret) + #lets do it again with new token + if method == "get": + response = self.oauth.get(url, data=data, headers=headers) + if method == "post": + response = self.oauth.post(url, data=data, headers=headers) + if method == "delete": + response = self.oauth.delete(url, data=data, headers=headers) + + l_json_response = json.loads(response.text) + return l_json_response + + + def run(self): + try: + Analyzer.run(self) + + filename = self.get_param("filename", "") + filepath = self.get_param("file", "") + + l_FileHashSha256 = self.CalcSHA256Hash(filepath) + + #get the latest report for file with sha256 + Url = "https://api.crowdstrike.com/falconx/queries/submissions/v1?filter=sandbox.sha256:\""+l_FileHashSha256+"\"&limit=1" + payload = {} + headers = {'Content-Type':'application/json'} + json_response = self.RestAPIRequest(method = "get", url=Url, headers=headers, data=payload) + + if json_response["errors"]: + self.error(str(json_response["errors"])) + return + else: + if not json_response["resources"]: + #no scan existing scan report for this file -> submit the file for analysis + payload = open(filepath, "rb") + headers = {'Content-Type':'application/octet-stream'} + Url = "https://api.crowdstrike.com/samples/entities/samples/v2?file_name="+filename+"&comment="+"added by TheHive:FalconSandbox-Analyzer" + json_response_submit=self.RestAPIRequest(method = "post", url=Url, data=payload, headers=headers) + if json_response_submit["errors"]: + self.error(str(json_response_submit["errors"])) + return + else: + #start analysis of the file + Url = "https://api.crowdstrike.com/falconx/entities/submissions/v1" + headers = {'Content-Type':'application/json'} + payload = "{\"sandbox\": [{\"sha256\": \"" + l_FileHashSha256 + "\",\"environment_id\": 110 }] }" + json_response_start_analysis=self.RestAPIRequest(method = "post", url=Url, data=payload, headers=headers) + if json_response_start_analysis["errors"]: + self.error(str(json_response_start_analysis["errors"])) + return + else: + #now the file is submitted and analysis is started, we get now the report_id + Url = "https://api.crowdstrike.com/falconx/queries/submissions/v1?filter=sandbox.sha256:\""+l_FileHashSha256+"\"&limit=1" + payload = {} + headers = {'Content-Type':'application/json'} + report_found = 0 + while report_found == 0: + json_response = self.RestAPIRequest(method = "get", url=Url, data=payload, headers=headers) + if json_response["errors"]: + self.error(str(json_response["errors"])) + return + if not json_response["resources"]: + #still waiting for the report ID + time.sleep(60.0) + report_found = 0 + else: + #report_id is found + Report_ID = json_response["resources"][0] + report_found = 1 + else: + Report_ID = json_response["resources"][0] + + analyzeinprogress = 1 + while analyzeinprogress == 1: + Url = "https://api.crowdstrike.com/falconx/entities/report-summaries/v1?ids=" + Report_ID + payload = {} + headers = {'Content-Type':'application/json'} + json_response_report = self.RestAPIRequest(method = "get", url=Url, data=payload, headers=headers) + if json_response_report["errors"]: + self.error(str(json_response_report["errors"])) + return + + if not json_response_report["resources"] and json_response_report["meta"]["quota"]["in_progress"] != 0: + #still waiting for the analysis results + time.sleep(60.0) + analyzeinprogress = 1 + else: + #report is ready + analyzeinprogress = 0 + + if json_response_report["errors"]: + self.error(str(json_response_report["errors"])) + return + else: + self.report(json_response_report) + + except Exception as ex: + self.error(traceback.format_exc()) + + +if __name__ == '__main__': + FalconSandbox().run() + diff --git a/analyzers/FalconSandbox/long.html b/analyzers/FalconSandbox/long.html new file mode 100755 index 000000000..675f5d474 --- /dev/null +++ b/analyzers/FalconSandbox/long.html @@ -0,0 +1,25 @@ + +
+
+ {{(artifact.data || artifact.attachment.name) | fang}} +
+
+ {{results.errorMessage}} +
+
+ + +
+
+ {{(artifact.data || artifact.attachment.name) | fang}} +
+ +
+ {{key}}: {{value}} +
+
+ {{content}} +
+
\ No newline at end of file diff --git a/analyzers/FalconSandbox/requirements.txt b/analyzers/FalconSandbox/requirements.txt new file mode 100755 index 000000000..43b0fae2e --- /dev/null +++ b/analyzers/FalconSandbox/requirements.txt @@ -0,0 +1,5 @@ +cortexutils +requests +requests_oauthlib +hashlib +time diff --git a/analyzers/FalconSandbox/short.html b/analyzers/FalconSandbox/short.html new file mode 100755 index 000000000..9fd48f9fa --- /dev/null +++ b/analyzers/FalconSandbox/short.html @@ -0,0 +1,3 @@ + + {{t.namespace}}:{{t.predicate}}="{{t.value}}" + \ No newline at end of file From d4bc883633ffe3781c6495f170f0b5bbf26ab4d4 Mon Sep 17 00:00:00 2001 From: Sebastian Schmerl - Computacenter Date: Fri, 19 Jun 2020 15:58:30 +0200 Subject: [PATCH 2/3] did some prettifications --- analyzers/FalconSandbox/FalconSandbox.py | 44 +++++++----------------- analyzers/FalconSandbox/long.html | 33 +++++++++++++----- analyzers/FalconSandbox/short.html | 2 +- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/analyzers/FalconSandbox/FalconSandbox.py b/analyzers/FalconSandbox/FalconSandbox.py index ac54cba9b..a1cbdbffb 100755 --- a/analyzers/FalconSandbox/FalconSandbox.py +++ b/analyzers/FalconSandbox/FalconSandbox.py @@ -36,26 +36,13 @@ def summary(self, raw): "has_result": True } value = str(raw['resources'][0]['sandbox'][0]['threat_score']) - level = str(raw['resources'][0]['sandbox'][0]['verdict']) - #switch results to thehive summary labels - #ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]"> - switcher={ - 'no verdict':'info', - 'No Specific Threat':'safe', - 'suspicious':'suspicious', - 'malicious':'malicious' - } - level = switcher.get(level, "invalid") - if level == "invalid": - predicate = predicate + "invalid level" - level = "info" + level = str(raw['resources'][0]['sandbox'][0]['verdict']) # no verdict, No Specific Threat, suspicious, malicious taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) return {"taxonomies": taxonomies} def CalcSHA256Hash(self, filepath): - # BUF_SIZE is totally arbitrary, change for your app! BUF_SIZE = 65536 # lets read stuff in 64kb chunks! l_sha256 = hashlib.sha256() with open(filepath, 'rb') as f: @@ -70,14 +57,12 @@ def CalcSHA256Hash(self, filepath): def RestAPIRequest(self, method, url, headers, data): l_json_response = "{}" - if method == "get": - response = self.oauth.get(url, data=data, headers=headers) - if method == "post": - response = self.oauth.post(url, data=data, headers=headers) - if method == "delete": - response = self.oauth.delete(url, data=data, headers=headers) + #get the get, post or delete method from the OAuth2Session object + method_to_call = getattr(self.oauth, method) + + response = method_to_call(url, data=data, headers=headers) l_json_response = json.loads(response.text) - + if l_json_response["errors"]: if l_json_response["errors"][0]["code"] == 403: ## ok, we need a new token @@ -85,14 +70,9 @@ def RestAPIRequest(self, method, url, headers, data): self.oauth = OAuth2Session(client=self.client) self.token = self.oauth.fetch_token(token_url=self.OAuth2_Url, client_id=self.Client_ID, client_secret=self.Client_Secret) #lets do it again with new token - if method == "get": - response = self.oauth.get(url, data=data, headers=headers) - if method == "post": - response = self.oauth.post(url, data=data, headers=headers) - if method == "delete": - response = self.oauth.delete(url, data=data, headers=headers) - - l_json_response = json.loads(response.text) + response = method_to_call(url, data=data, headers=headers) + l_json_response = json.loads(response.text) + return l_json_response @@ -116,7 +96,7 @@ def run(self): return else: if not json_response["resources"]: - #no scan existing scan report for this file -> submit the file for analysis + #no scan reports exists for this file -> submit the file for analysis payload = open(filepath, "rb") headers = {'Content-Type':'application/octet-stream'} Url = "https://api.crowdstrike.com/samples/entities/samples/v2?file_name="+filename+"&comment="+"added by TheHive:FalconSandbox-Analyzer" @@ -125,7 +105,7 @@ def run(self): self.error(str(json_response_submit["errors"])) return else: - #start analysis of the file + #start the analysis of the submitted file Url = "https://api.crowdstrike.com/falconx/entities/submissions/v1" headers = {'Content-Type':'application/json'} payload = "{\"sandbox\": [{\"sha256\": \"" + l_FileHashSha256 + "\",\"environment_id\": 110 }] }" @@ -134,7 +114,7 @@ def run(self): self.error(str(json_response_start_analysis["errors"])) return else: - #now the file is submitted and analysis is started, we get now the report_id + #now the file is submitted and analysis is started, let's get the report_id now Url = "https://api.crowdstrike.com/falconx/queries/submissions/v1?filter=sandbox.sha256:\""+l_FileHashSha256+"\"&limit=1" payload = {} headers = {'Content-Type':'application/json'} diff --git a/analyzers/FalconSandbox/long.html b/analyzers/FalconSandbox/long.html index 675f5d474..753893497 100755 --- a/analyzers/FalconSandbox/long.html +++ b/analyzers/FalconSandbox/long.html @@ -1,7 +1,7 @@
- {{(artifact.data || artifact.attachment.name) | fang}} + Crowdstrike FalconX Sandbox report for {{(artifact.data || artifact.attachment.name) | fang}}
{{results.errorMessage}} @@ -9,17 +9,34 @@
-
+
- {{(artifact.data || artifact.attachment.name) | fang}} + CrowdStrike Falcon X Sandbox Report for {{(artifact.data || artifact.attachment.name) | fang}}
-
- {{key}}: {{value}} +
+ +
+
+
+
{{key}}
+
+
+
+ + {{value}} + +
+
{{value}}
+
+
+
+
+
-
- {{content}} -
\ No newline at end of file diff --git a/analyzers/FalconSandbox/short.html b/analyzers/FalconSandbox/short.html index 9fd48f9fa..df37b0291 100755 --- a/analyzers/FalconSandbox/short.html +++ b/analyzers/FalconSandbox/short.html @@ -1,3 +1,3 @@ - + {{t.namespace}}:{{t.predicate}}="{{t.value}}" \ No newline at end of file From a31e10561eb45fe06017574b3ea1abc1dd513643 Mon Sep 17 00:00:00 2001 From: Sebastian Schmerl - Computacenter Date: Tue, 7 Jul 2020 08:26:31 +0200 Subject: [PATCH 3/3] I changed the code to python 3 --- analyzers/FalconSandbox/FalconSandbox.json | 10 +- analyzers/FalconSandbox/FalconSandbox.py | 167 +++++++++++---------- analyzers/FalconSandbox/long.html | 2 +- analyzers/FalconSandbox/requirements.txt | 9 +- 4 files changed, 98 insertions(+), 90 deletions(-) diff --git a/analyzers/FalconSandbox/FalconSandbox.json b/analyzers/FalconSandbox/FalconSandbox.json index a13751262..c59d70a8a 100755 --- a/analyzers/FalconSandbox/FalconSandbox.json +++ b/analyzers/FalconSandbox/FalconSandbox.json @@ -1,21 +1,21 @@ { "name": "FalconSandbox", "version": "1.0", - "author": "Sebastian.Schmerl - Computacenter", + "author": "Sebastian Schmerl - Computacenter", "url": "https://www.crowdstrike.com/blog/tech-center/get-access-falcon-apis/", - "license": "AGPL", + "license": "AGPL-v3", "description": "Submit observables to the Crowdstrike FalconX Sandbox", "dataTypeList": ["file"], "command": "FalconSandbox/FalconSandbox.py", "baseConfig": "FalconSandbox", "configurationItems": [ { - "name": "OAuth2_Url", - "description": "Crowdstrike Api OAuth2 url", + "name": "API_Base_Url", + "description": "Crowdstrike Api Base Url", "type": "string", "multi": false, "required": true, - "default":"https://api.crowdstrike.com/oauth2/token" + "default":"https://api.crowdstrike.com" }, { "name": "Client_ID", diff --git a/analyzers/FalconSandbox/FalconSandbox.py b/analyzers/FalconSandbox/FalconSandbox.py index a1cbdbffb..2e44762c2 100755 --- a/analyzers/FalconSandbox/FalconSandbox.py +++ b/analyzers/FalconSandbox/FalconSandbox.py @@ -1,168 +1,177 @@ -#!/usr/bin/python2 -# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# encoding: utf-8 + -import requests -import re -import json -import traceback import hashlib +import json import time +import traceback from cortexutils.analyzer import Analyzer -from requests.auth import HTTPBasicAuth from oauthlib.oauth2 import BackendApplicationClient from requests_oauthlib import OAuth2Session + class FalconSandbox(Analyzer): def __init__(self): Analyzer.__init__(self) - self.OAuth2_Url = self.get_param('config.OAuth2_Url', None, "Falcon OAuth2 URL missing (e.g.:https://api.crowdstrike.com/self.oauth2/token)") self.Client_ID = self.get_param( 'config.Client_ID', None, "Falcon ClientID missing") self.Client_Secret = self.get_param( 'config.Client_Secret', None, "Falcon Client_Secret missing") + self.API_Base_Url = self.get_param( + 'config.API_Base_Url', None, "Falcon API Base URl missing") self.client = BackendApplicationClient(client_id=self.Client_ID) self.oauth = OAuth2Session(client=self.client) - self.token = self.oauth.fetch_token(token_url=self.OAuth2_Url, client_id=self.Client_ID, client_secret=self.Client_Secret) - + self.token = self.oauth.fetch_token(token_url=self.API_Base_Url + "/oauth2/token", client_id=self.Client_ID, client_secret=self.Client_Secret) def summary(self, raw): taxonomies = [] - level = "info" namespace = "CS-Sandbox" predicate = "Threat-Score" - value = "0" - result = { - "has_result": True - } value = str(raw['resources'][0]['sandbox'][0]['threat_score']) - level = str(raw['resources'][0]['sandbox'][0]['verdict']) # no verdict, No Specific Threat, suspicious, malicious - + level = str( + raw['resources'][0]['sandbox'][0]['verdict']) # no verdict, No Specific Threat, suspicious, malicious + taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) return {"taxonomies": taxonomies} - - def CalcSHA256Hash(self, filepath): - BUF_SIZE = 65536 # lets read stuff in 64kb chunks! + def calc_sha256_hash(self, filepath): + buf_size = 65536 # lets read stuff in 64kb chunks! l_sha256 = hashlib.sha256() with open(filepath, 'rb') as f: while True: - l_data = f.read(BUF_SIZE) + l_data = f.read(buf_size) if not l_data: break l_sha256.update(l_data) - + l_own_sha256 = l_sha256.hexdigest() return l_own_sha256 - def RestAPIRequest(self, method, url, headers, data): - l_json_response = "{}" - #get the get, post or delete method from the OAuth2Session object - method_to_call = getattr(self.oauth, method) - + def rest_api_request(self, method, url, headers, data): + # get the get, post or delete method from the OAuth2Session object + method_to_call = getattr(self.oauth, method) + response = method_to_call(url, data=data, headers=headers) l_json_response = json.loads(response.text) - - if l_json_response["errors"]: - if l_json_response["errors"][0]["code"] == 403: - ## ok, we need a new token - self.client = BackendApplicationClient(client_id=self.Client_ID) - self.oauth = OAuth2Session(client=self.client) - self.token = self.oauth.fetch_token(token_url=self.OAuth2_Url, client_id=self.Client_ID, client_secret=self.Client_Secret) - #lets do it again with new token - response = method_to_call(url, data=data, headers=headers) - l_json_response = json.loads(response.text) - return l_json_response + if l_json_response["errors"] and l_json_response["errors"][0]["code"] == 403: + # ok, we need a new token + self.client = BackendApplicationClient(client_id=self.Client_ID) + self.oauth = OAuth2Session(client=self.client) + self.token = self.oauth.fetch_token(token_url=self.API_Base_Url + "/oauth2/token", + client_id=self.Client_ID, client_secret=self.Client_Secret) + # lets do it again with new token + response = method_to_call(url, data=data, headers=headers) + l_json_response = json.loads(response.text) + return l_json_response def run(self): try: Analyzer.run(self) - + filename = self.get_param("filename", "") filepath = self.get_param("file", "") - - l_FileHashSha256 = self.CalcSHA256Hash(filepath) - #get the latest report for file with sha256 - Url = "https://api.crowdstrike.com/falconx/queries/submissions/v1?filter=sandbox.sha256:\""+l_FileHashSha256+"\"&limit=1" + l_file_hash_sha256 = self.calc_sha256_hash(filepath) + + # get the latest report for file with sha256 + url = self.API_Base_Url + \ + "/falconx/queries/submissions/v1?filter=sandbox.sha256:\"" + \ + l_file_hash_sha256 + \ + "\"&limit=1" payload = {} - headers = {'Content-Type':'application/json'} - json_response = self.RestAPIRequest(method = "get", url=Url, headers=headers, data=payload) + headers = {'Content-Type': 'application/json'} + json_response = self.rest_api_request(method="get", url=url, headers=headers, data=payload) if json_response["errors"]: self.error(str(json_response["errors"])) return else: if not json_response["resources"]: - #no scan reports exists for this file -> submit the file for analysis + # no scan reports exists for this file -> submit the file for analysis payload = open(filepath, "rb") - headers = {'Content-Type':'application/octet-stream'} - Url = "https://api.crowdstrike.com/samples/entities/samples/v2?file_name="+filename+"&comment="+"added by TheHive:FalconSandbox-Analyzer" - json_response_submit=self.RestAPIRequest(method = "post", url=Url, data=payload, headers=headers) + headers = {'Content-Type': 'application/octet-stream'} + url = self.API_Base_Url + \ + "/samples/entities/samples/v2?file_name=" + \ + filename + \ + "&comment=" + \ + "added by TheHive:FalconSandbox-Analyzer" + json_response_submit = self.rest_api_request(method="post", url=url, data=payload, headers=headers) if json_response_submit["errors"]: self.error(str(json_response_submit["errors"])) return else: - #start the analysis of the submitted file - Url = "https://api.crowdstrike.com/falconx/entities/submissions/v1" - headers = {'Content-Type':'application/json'} - payload = "{\"sandbox\": [{\"sha256\": \"" + l_FileHashSha256 + "\",\"environment_id\": 110 }] }" - json_response_start_analysis=self.RestAPIRequest(method = "post", url=Url, data=payload, headers=headers) + # start the analysis of the submitted file + url = self.API_Base_Url + \ + "/falconx/entities/submissions/v1" + headers = {'Content-Type': 'application/json'} + payload = "{\"sandbox\": " \ + "[{\"sha256\": \"" + \ + l_file_hash_sha256 + \ + "\",\"environment_id\": 110 }] }" + json_response_start_analysis = self.rest_api_request(method="post", url=url, data=payload, + headers=headers) if json_response_start_analysis["errors"]: self.error(str(json_response_start_analysis["errors"])) return - else: - #now the file is submitted and analysis is started, let's get the report_id now - Url = "https://api.crowdstrike.com/falconx/queries/submissions/v1?filter=sandbox.sha256:\""+l_FileHashSha256+"\"&limit=1" + else: + # now the file is submitted and analysis is started, let's get the report_id now + url = self.API_Base_Url + \ + "/falconx/queries/submissions/v1?filter=sandbox.sha256:\"" \ + + l_file_hash_sha256 + \ + "\"&limit=1" payload = {} - headers = {'Content-Type':'application/json'} - report_found = 0 - while report_found == 0: - json_response = self.RestAPIRequest(method = "get", url=Url, data=payload, headers=headers) + headers = {'Content-Type': 'application/json'} + report_found = 0 + while report_found == 0: + json_response = self.rest_api_request(method="get", url=url, data=payload, + headers=headers) if json_response["errors"]: self.error(str(json_response["errors"])) return if not json_response["resources"]: - #still waiting for the report ID + # still waiting for the report ID time.sleep(60.0) report_found = 0 else: - #report_id is found - Report_ID = json_response["resources"][0] + # report_id is found + report_id = json_response["resources"][0] report_found = 1 else: - Report_ID = json_response["resources"][0] - - analyzeinprogress = 1 - while analyzeinprogress == 1: - Url = "https://api.crowdstrike.com/falconx/entities/report-summaries/v1?ids=" + Report_ID + report_id = json_response["resources"][0] + + analyzeinprogress = 1 + while analyzeinprogress == 1: + url = self.API_Base_Url + \ + "/falconx/entities/report-summaries/v1?ids=" + report_id payload = {} - headers = {'Content-Type':'application/json'} - json_response_report = self.RestAPIRequest(method = "get", url=Url, data=payload, headers=headers) + headers = {'Content-Type': 'application/json'} + json_response_report = self.rest_api_request(method="get", url=url, data=payload, headers=headers) if json_response_report["errors"]: self.error(str(json_response_report["errors"])) return - - if not json_response_report["resources"] and json_response_report["meta"]["quota"]["in_progress"] != 0: - #still waiting for the analysis results + + if not json_response_report["resources"] and \ + json_response_report["meta"]["quota"]["in_progress"] != 0: + # still waiting for the analysis results time.sleep(60.0) analyzeinprogress = 1 else: - #report is ready + # report is ready analyzeinprogress = 0 - + if json_response_report["errors"]: self.error(str(json_response_report["errors"])) return - else: + else: self.report(json_response_report) - + except Exception as ex: self.error(traceback.format_exc()) if __name__ == '__main__': FalconSandbox().run() - diff --git a/analyzers/FalconSandbox/long.html b/analyzers/FalconSandbox/long.html index 753893497..0f51d66c5 100755 --- a/analyzers/FalconSandbox/long.html +++ b/analyzers/FalconSandbox/long.html @@ -25,7 +25,7 @@
- diff --git a/analyzers/FalconSandbox/requirements.txt b/analyzers/FalconSandbox/requirements.txt index 43b0fae2e..374e61365 100755 --- a/analyzers/FalconSandbox/requirements.txt +++ b/analyzers/FalconSandbox/requirements.txt @@ -1,5 +1,4 @@ -cortexutils -requests -requests_oauthlib -hashlib -time +requests~=2.24.0 +cortexutils~=2.0.0 +urllib3~=1.25.9 +oauthlib~=3.1.0 \ No newline at end of file