Skip to content

Commit d470a4f

Browse files
amr-cossinadouani
authored andcommitted
Autofocus analyzer v1 (#473)
1 parent 8197824 commit d470a4f

5 files changed

Lines changed: 212 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "AUTOFOCUS_GetSampleAnalysis",
3+
"version": "1.0",
4+
"author": "ANSSI",
5+
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
6+
"license": "AGPL-V3",
7+
"baseConfig": "Autofocus",
8+
"config": {
9+
"service": "get_sample_analysis"
10+
},
11+
"description": "Get full analysis from a sample based on its hash",
12+
"dataTypeList": ["hash"],
13+
"command": "Autofocus/analyzer.py",
14+
"configurationItems": [
15+
{
16+
"name": "apikey",
17+
"description": "Autofocus API key",
18+
"type": "string",
19+
"multi": false,
20+
"required": true
21+
}
22+
]
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "AUTOFOCUS_SearchIOC",
3+
"version": "1.0",
4+
"author": "ANSSI",
5+
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
6+
"license": "AGPL-V3",
7+
"baseConfig": "Autofocus",
8+
"config": {
9+
"service": "search_ioc"
10+
},
11+
"description": "Search samples in Autofocus based on a single IOC",
12+
"dataTypeList": ["domain","fqdn","user-agent","imphash","ip","mutex","tag","url"],
13+
"command": "Autofocus/analyzer.py",
14+
"configurationItems": [
15+
{
16+
"name": "apikey",
17+
"description": "Autofocus API key",
18+
"type": "string",
19+
"multi": false,
20+
"required": true
21+
}
22+
]
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "AUTOFOCUS_SearchJSON",
3+
"version": "1.0",
4+
"author": "ANSSI",
5+
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
6+
"license": "AGPL-V3",
7+
"baseConfig": "Autofocus",
8+
"config": {
9+
"service": "search_json"
10+
},
11+
"description": "Search samples in Autofocus with a full search query in JSON",
12+
"dataTypeList": ["other"],
13+
"command": "Autofocus/analyzer.py",
14+
"configurationItems": [
15+
{
16+
"name": "apikey",
17+
"description": "Autofocus API key",
18+
"type": "string",
19+
"multi": false,
20+
"required": true
21+
}
22+
]
23+
}

analyzers/Autofocus/analyzer.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env python
2+
# encoding: utf-8
3+
from autofocus import AutoFocusAPI, AFSample, AFServerError, AFClientError, AFSampleAbsent
4+
from cortexutils.analyzer import Analyzer
5+
6+
# Define a class representing a search query in JSON format
7+
class SearchJson(object):
8+
def __init__(self, search = ""):
9+
self.search = search
10+
def do_search(self):
11+
res = []
12+
for sample in AFSample.search(self.search):
13+
res.append({'metadata': sample.serialize(),
14+
'tags': [tag.serialize() for tag in sample.__getattribute__('tags')]
15+
})
16+
return {'search': self.search, 'records': res}
17+
18+
19+
# Define subclass for each predefined searches
20+
class SearchJson_IP(SearchJson):
21+
def __init__(self,value):
22+
self.search={"operator":"all","children":[{"field":"alias.ip_address","operator":"contains","value":value}]}
23+
def do_search(self):
24+
return super(SearchJson_IP,self).do_search()
25+
class SearchJson_Domain(SearchJson):
26+
def __init__(self,value):
27+
self.search={"operator":"all","children":[{"field":"alias.domain","operator":"contains","value":value}]}
28+
def do_search(self):
29+
return super(SearchJson_Domain,self).do_search()
30+
class SearchJson_TAG(SearchJson):
31+
def __init__(self,value):
32+
self.search={"operator":"all","children":[{"field":"sample.tag","operator":"is in the list","value":[value]}]}
33+
def do_search(self):
34+
return super(SearchJson_TAG,self).do_search()
35+
class SearchJson_URL(SearchJson):
36+
def __init__(self,value):
37+
self.search={"operator":"all","children":[{"field":"sample.tasks.http","operator":"is in the list","value":[value]}]}
38+
def do_search(self):
39+
return super(SearchJson_URL,self).do_search()
40+
class SearchJson_Imphash(SearchJson):
41+
def __init__(self,value):
42+
self.search={"operator":"all","children":[{"field":"sample.imphash","operator":"is","value":value}]}
43+
def do_search(self):
44+
return super(SearchJson_Imphash,self).do_search()
45+
class SearchJson_Mutex(SearchJson):
46+
def __init__(self,value):
47+
self.search={"operator":"all","children":[{"field":"sample.tasks.mutex","operator":"contains","value":value}]}
48+
def do_search(self):
49+
return super(SearchJson_Mutex,self).do_search()
50+
class SearchJson_UserAgent(SearchJson):
51+
def __init__(self,value):
52+
self.search={"operator":"all","children":[{"field":"alias.user_agent","operator":"contains","value":value}]}
53+
def do_search(self):
54+
return super(SearchJson_UserAgent,self).do_search()
55+
56+
# Main analyzer
57+
class AutoFocusAnalyzer(Analyzer):
58+
def __init__(self):
59+
Analyzer.__init__(self)
60+
self.service = self.getParam(
61+
'config.service', None, 'Service parameter is missing')
62+
self.autofocus_key = self.getParam(
63+
'config.apikey', None, 'Missing AutoFocus API key')
64+
65+
def execute_autofocus_service(self):
66+
data = self.getData()
67+
AutoFocusAPI.api_key = self.autofocus_key
68+
if self.service == 'get_sample_analysis' and self.data_type in ['hash']:
69+
sample = AFSample.get(data)
70+
res = {'metadata': sample.serialize(),
71+
'tags': [tag.serialize() for tag in sample.__getattribute__('tags')],
72+
'analysis': {}
73+
}
74+
for analyse in sample.get_analyses():
75+
analysis_type = analyse.__class__.__name__
76+
if analysis_type not in res['analysis']:
77+
res['analysis'][analysis_type] = []
78+
res['analysis'][analysis_type].append(analyse.serialize())
79+
return res
80+
elif self.service == 'search_ioc' and self.data_type in ['ip']:
81+
searchIP = SearchJson_IP(data)
82+
return searchIP.do_search()
83+
elif self.service == 'search_ioc' and self.data_type in ['domain','fqdn']:
84+
searchDomain = SearchJson_Domain(data)
85+
return searchDomain.do_search()
86+
elif self.service == 'search_ioc' and self.data_type in ['mutex']:
87+
searchMutex = SearchJson_Mutex(data)
88+
return searchMutex.do_search()
89+
elif self.service == 'search_ioc' and self.data_type in ['imphash']:
90+
searchImpash = SearchJson_Imphash(data)
91+
return searchImpash.do_search()
92+
elif self.service == 'search_ioc' and self.data_type in ['tag']:
93+
searchTag = SearchJson_TAG(data)
94+
return searchTag.do_search()
95+
elif self.service == 'search_ioc' and self.data_type in ['url']:
96+
searchURL = SearchJson_URL(data)
97+
return searchURL.do_search()
98+
elif self.service == 'search_ioc' and self.data_type in ['user-agent']:
99+
searchUserAgent = SearchJson_UserAgent(data)
100+
return searchUserAgent.do_search()
101+
elif self.service == 'search_json' and self.data_type in ['other']:
102+
search = SearchJson(data)
103+
return search.do_search()
104+
else:
105+
self.error('Unknown AutoFocus service or invalid data type')
106+
107+
def summary(self, raw):
108+
# taxonomy = {"level": "info", "namespace": "PaloAltoNetworks", "predicate": "AutoFocus", "value": 0}
109+
taxonomies = []
110+
level = "info"
111+
namespace = "PaloAltoNetworks"
112+
predicate = "AutoFocus"
113+
114+
if "metadata" in raw:
115+
value = "Sample found"
116+
elif "records" in raw:
117+
value = "{} sample(s) found".format(len(raw["records"]))
118+
else:
119+
value = ""
120+
121+
taxonomies.append(self.build_taxonomy(level,namespace,predicate,value))
122+
123+
return {'taxonomies': taxonomies}
124+
125+
126+
def run(self):
127+
try:
128+
records = self.execute_autofocus_service()
129+
self.report(records)
130+
131+
except AFSampleAbsent as e: # Sample not in Autofocus
132+
self.error('Unknown sample in Autofocus')
133+
except AFServerError as e: # Server error
134+
self.unexpectedError(e)
135+
except AFClientError as e: # Client error
136+
self.unexpectedError(e)
137+
except Exception: # Unknown error
138+
self.unexpectedError("Unknown error while running Autofocus analyzer")
139+
140+
if __name__ == '__main__':
141+
AutoFocusAnalyzer().run()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cortexutils
2+
git+https://github.com/PaloAltoNetworks/autofocus-client-library ; python_version<='2.7'

0 commit comments

Comments
 (0)