Skip to content

Commit 900c3cb

Browse files
authored
Merge pull request #3 from Microsoft/RSAFixes
Rsa fixes
2 parents 29bb3be + 9f4ee0b commit 900c3cb

File tree

6 files changed

+92
-62
lines changed

6 files changed

+92
-62
lines changed

msticpy/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""Version file."""
2-
VERSION = "0.0.73"
2+
VERSION = "0.1.03"

msticpy/nbtools/entityschema.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,28 @@ def __init__(self, src_entity=None, **kwargs):
4646
self[k] = src_entity[k]
4747

4848
if v is not None:
49-
if v == RegistryHive.__name__:
50-
self[k] = RegistryHive(src_entity[k])
51-
elif v == OSFamily.__name__:
52-
self[k] = OSFamily(src_entity[k])
53-
elif v == ElevationToken.__name__:
54-
self[k] = ElevationToken(src_entity[k])
55-
elif v == GeoLocation.__name__:
56-
self[k] = GeoLocation(src_entity[k])
57-
elif v == Algorithm.__name__:
58-
self[k] = Algorithm(src_entity[k])
59-
elif isinstance(v, tuple):
60-
entity_list = []
61-
for col_entity in src_entity[k]:
62-
entity_list.append(Entity.instantiate_entity(col_entity))
63-
self[k] = entity_list
64-
else:
65-
self[k] = Entity.instantiate_entity(src_entity[k])
49+
try:
50+
if v == RegistryHive.__name__:
51+
self[k] = RegistryHive[src_entity[k]]
52+
elif v == OSFamily.__name__:
53+
self[k] = OSFamily[src_entity[k]]
54+
elif v == ElevationToken.__name__:
55+
self[k] = ElevationToken[src_entity[k]]
56+
elif v == GeoLocation.__name__:
57+
self[k] = GeoLocation[src_entity[k]]
58+
elif v == Algorithm.__name__:
59+
self[k] = Algorithm[src_entity[k]]
60+
elif isinstance(v, tuple):
61+
entity_list = []
62+
for col_entity in src_entity[k]:
63+
entity_list.append(Entity.instantiate_entity(col_entity))
64+
self[k] = entity_list
65+
else:
66+
self[k] = Entity.instantiate_entity(src_entity[k])
67+
except KeyError:
68+
# Catch key errors from invalid enum values
69+
self[k] = None
70+
6671
# add AdditionalData dictionary if it's populated
6772
if 'AdditionalData' in src_entity:
6873
self['AdditionalData'] = src_entity['AdditionalData']
@@ -517,6 +522,7 @@ def description_str(self) -> str:
517522
@export
518523
class Algorithm(Enum):
519524
"""FileHash Algorithm Enumeration."""
525+
520526
Unknown = 0
521527
MD5 = 1
522528
SHA1 = 2
@@ -862,7 +868,7 @@ def description_str(self) -> str:
862868
_entity_schema = {
863869
# Hive (type System.Nullable`1
864870
# [Microsoft.Azure.Security.Detection.AlertContracts.V3.Entities.RegistryHive])
865-
'Hive': RegistryHive,
871+
'Hive': 'RegistryHive',
866872
# Key (type System.String)
867873
'Key': None
868874
}

msticpy/nbtools/nbwidgets.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,11 @@ def _get_alert(self, alert_id):
372372
if selected_alerts.shape[0] > 0:
373373
alert = pd.Series(selected_alerts.iloc[0])
374374
if isinstance(alert['ExtendedProperties'], str):
375-
alert['ExtendedProperties'] = json.loads(
376-
(alert['ExtendedProperties']))
375+
try:
376+
alert['ExtendedProperties'] = json.loads(
377+
(alert['ExtendedProperties']))
378+
except JSONDecodeError:
379+
pass
377380
if isinstance(alert['Entities'], str):
378381
try:
379382
alert['Entities'] = json.loads((alert['Entities']))

msticpy/nbtools/security_alert.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def __init__(self, src_row: pd.Series = None):
3232
super().__init__(src_row=src_row)
3333

3434
# add entities to dictionary to remove dups
35+
self._src_entities = dict()
3536
if 'Entities' in src_row:
36-
self._src_entities = dict()
3737
self._extract_entities(src_row)
3838

3939
if 'ExtendedProperties' in src_row:
@@ -44,6 +44,8 @@ def __init__(self, src_row: pd.Series = None):
4444
self.extended_properties = json.loads(src_row.ExtendedProperties)
4545
except JSONDecodeError:
4646
pass
47+
else:
48+
self.extended_properties = []
4749
self._find_os_family()
4850

4951
@property

msticpy/nbtools/security_alert_graph.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ def create_alert_graph(alert: SecurityAlert):
2828
alertentity_graph.add_node(alert['AlertType'],
2929
name=alert['AlertType'],
3030
time=str(alert['StartTimeUtc']),
31-
description='Alert: ' + alert['AlertDisplayName'],
31+
description='Alert: ' +
32+
alert['AlertDisplayName'],
3233
color='red',
3334
node_type='alert')
3435

@@ -71,7 +72,8 @@ def create_alert_graph(alert: SecurityAlert):
7172

7273
# if we have a previously created an edge to the alert, remove it
7374
if alertentity_graph.has_edge(alert['AlertType'], related_entity):
74-
alertentity_graph.remove_edge(alert['AlertType'], related_entity)
75+
alertentity_graph.remove_edge(
76+
alert['AlertType'], related_entity)
7577

7678
# if we haven't added an edge to this entity from anything else,
7779
# add one to the alert
@@ -92,10 +94,13 @@ def add_related_alerts(related_alerts: pd.DataFrame, alertgraph: nx.Graph) ->nx.
9294

9395
alert_host_node = _find_graph_node(related_alerts_graph, 'host', '')
9496

95-
related_alerts.apply(lambda x: _add_alert_node(related_alerts_graph, x), axis=1)
96-
related_alerts.apply(lambda x: _add_related_alert_edges(related_alerts_graph,
97-
x,
98-
alert_host_node), axis=1)
97+
related_alerts.apply(lambda x: _add_alert_node(
98+
related_alerts_graph, x), axis=1)
99+
if alert_host_node:
100+
related_alerts.apply(lambda x:
101+
_add_related_alert_edges(related_alerts_graph,
102+
x,
103+
alert_host_node), axis=1)
99104
return related_alerts_graph
100105

101106

@@ -105,25 +110,29 @@ def _add_related_alert_edges(related_alerts_graph, alert_row, default_node):
105110
acct_node = _find_graph_node(related_alerts_graph, 'account',
106111
related_alert.primary_account.qualified_name)
107112
if acct_node is not None:
108-
_add_related_alert_edge(related_alerts_graph, acct_node, related_alert)
113+
_add_related_alert_edge(
114+
related_alerts_graph, acct_node, related_alert)
109115

110116
if related_alert.primary_process is not None:
111117
proc_node = _find_graph_node(related_alerts_graph,
112118
'process',
113119
related_alert.primary_process.ProcessFilePath)
114120
if proc_node is not None:
115-
_add_related_alert_edge(related_alerts_graph, proc_node, related_alert)
121+
_add_related_alert_edge(
122+
related_alerts_graph, proc_node, related_alert)
116123

117124
if related_alert.primary_host is not None:
118125
host_node = _find_graph_node(related_alerts_graph,
119126
'host', related_alert.primary_host['HostName'])
120127
if host_node is not None:
121-
_add_related_alert_edge(related_alerts_graph, host_node, related_alert)
128+
_add_related_alert_edge(
129+
related_alerts_graph, host_node, related_alert)
122130

123131
# if we haven't added an edge to this entity from anything else,
124132
# add one to the alert
125133
if not related_alerts_graph[related_alert['AlertType'] + '(R)']:
126-
_add_related_alert_edge(related_alerts_graph, default_node, related_alert)
134+
_add_related_alert_edge(related_alerts_graph,
135+
default_node, related_alert)
127136

128137

129138
def _add_alert_node(nx_graph, alert):
@@ -159,9 +168,11 @@ def _add_related_alert_edge(nx_graph, source, target):
159168

160169
description = 'Related alert: {} Count:{}'.format(target['AlertType'],
161170
current_count)
162-
node_attrs = {target_node: {'count': current_count, 'description': description}}
171+
node_attrs = {target_node: {
172+
'count': current_count, 'description': description}}
163173
nx.set_node_attributes(nx_graph, node_attrs)
164-
nx_graph.add_edge(source, target_node, weight=0.7, description='Related Alert')
174+
nx_graph.add_edge(source, target_node, weight=0.7,
175+
description='Related Alert')
165176

166177

167178
def _get_account_qualified_name(account):
@@ -261,7 +272,8 @@ def _get_process_name_desc(entity):
261272

262273

263274
def _get_account_name_desc(entity):
264-
e_name = (entity['NTDomain'] + '\\' if 'NTDomain' in entity else '') + entity['Name']
275+
e_name = (entity['NTDomain'] +
276+
'\\' if 'NTDomain' in entity else '') + entity['Name']
265277
e_name = '{}: {}'.format(entity['Type'], e_name)
266278
if 'IsDomainJoined' in entity:
267279
domain_joined = entity['IsDomainJoined']
@@ -291,6 +303,7 @@ def _get_host_name_desc(entity, os_family):
291303
domain_joined = 'false'
292304
if 'OSFamily' in entity:
293305
os_family = entity['OSFamily']
294-
e_description = '{}\n({}, Domain-joined: {})'.format(e_name, os_family, domain_joined)
306+
e_description = '{}\n({}, Domain-joined: {})'.format(e_name,
307+
os_family, domain_joined)
295308

296309
return e_name, e_description

msticpy/nbtools/security_base.py

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -186,32 +186,38 @@ def query_params(self):
186186
dict(str, str) -- Dictionary of parameter names
187187
188188
"""
189-
host_name = self.primary_host.fqdn
190-
proc_name = (self.primary_process.ImageFile.FullPath if
191-
self.primary_process and self.primary_process.ImageFile
192-
else None)
193-
acct_name = self.primary_account.Name if self.primary_account else None
194-
path_separator = self.path_separator
195-
if self.data_family == DataFamily.WindowsSecurity:
196-
proc_name = escape_windows_path(proc_name)
197-
path_separator = escape_windows_path(self.path_separator)
198-
199-
dyn_query_params = {
200-
'subscription_filter': self.subscription_filter(),
201-
'host_filter_eq': self.host_filter(operator='=='),
202-
'host_filter_neq': self.host_filter(operator='!='),
203-
'host_name': host_name,
204-
'account_name': acct_name,
205-
'process_name': proc_name,
206-
'logon_session_id': self.get_logon_id(),
207-
'process_id': (self.primary_process.ProcessId if self.primary_process else None),
208-
'path_separator': path_separator,
209-
'data_family': self.data_family,
210-
'data_environment': self.data_environment
211-
}
212-
213-
dyn_query_params.update(self._custom_query_params)
214-
return dyn_query_params
189+
try:
190+
if self.primary_host:
191+
host_name = self.primary_host.fqdn
192+
else:
193+
host_name = None
194+
proc_name = (self.primary_process.ImageFile.FullPath if
195+
self.primary_process and self.primary_process.ImageFile
196+
else None)
197+
acct_name = self.primary_account.Name if self.primary_account else None
198+
path_separator = self.path_separator
199+
if self.data_family == DataFamily.WindowsSecurity:
200+
proc_name = escape_windows_path(proc_name)
201+
path_separator = escape_windows_path(self.path_separator)
202+
203+
dyn_query_params = {
204+
'subscription_filter': self.subscription_filter(),
205+
'host_filter_eq': self.host_filter(operator='=='),
206+
'host_filter_neq': self.host_filter(operator='!='),
207+
'host_name': host_name,
208+
'account_name': acct_name,
209+
'process_name': proc_name,
210+
'logon_session_id': self.get_logon_id(),
211+
'process_id': (self.primary_process.ProcessId if self.primary_process else None),
212+
'path_separator': path_separator,
213+
'data_family': self.data_family,
214+
'data_environment': self.data_environment,
215+
}
216+
217+
dyn_query_params.update(self._custom_query_params)
218+
return dyn_query_params
219+
except AttributeError:
220+
return {}
215221

216222
@property
217223
def data_family(self) -> DataFamily:

0 commit comments

Comments
 (0)