mal-toolbox 0.3.11__py3-none-any.whl → 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info}/METADATA +4 -23
- mal_toolbox-1.0.1.dist-info/RECORD +26 -0
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info}/WHEEL +1 -1
- maltoolbox/__init__.py +5 -6
- maltoolbox/__main__.py +3 -34
- maltoolbox/attackgraph/__init__.py +7 -1
- maltoolbox/attackgraph/attackgraph.py +58 -195
- maltoolbox/attackgraph/node.py +2 -82
- maltoolbox/file_utils.py +1 -1
- maltoolbox/language/__init__.py +11 -0
- maltoolbox/language/languagegraph.py +649 -371
- maltoolbox/model.py +7 -221
- maltoolbox/py.typed +0 -0
- maltoolbox/translators/securicad.py +1 -1
- maltoolbox/translators/updater.py +1 -1
- mal_toolbox-0.3.11.dist-info/RECORD +0 -29
- maltoolbox/attackgraph/analyzers/apriori.py +0 -243
- maltoolbox/attackgraph/attacker.py +0 -109
- maltoolbox/attackgraph/query.py +0 -196
- maltoolbox/ingestors/neo4j.py +0 -244
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info}/entry_points.txt +0 -0
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info/licenses}/AUTHORS +0 -0
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info/licenses}/LICENSE +0 -0
- {mal_toolbox-0.3.11.dist-info → mal_toolbox-1.0.1.dist-info}/top_level.txt +0 -0
maltoolbox/attackgraph/node.py
CHANGED
|
@@ -9,7 +9,6 @@ from typing import TYPE_CHECKING
|
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from typing import Any, Optional
|
|
12
|
-
from . import Attacker
|
|
13
12
|
from ..language import LanguageGraphAttackStep, Detector
|
|
14
13
|
from ..model import ModelAsset
|
|
15
14
|
|
|
@@ -21,26 +20,21 @@ class AttackGraphNode:
|
|
|
21
20
|
node_id: int,
|
|
22
21
|
lg_attack_step: LanguageGraphAttackStep,
|
|
23
22
|
model_asset: Optional[ModelAsset] = None,
|
|
24
|
-
|
|
23
|
+
ttc_dist: Optional[dict] = None,
|
|
25
24
|
existence_status: Optional[bool] = None
|
|
26
25
|
):
|
|
27
26
|
self.lg_attack_step = lg_attack_step
|
|
28
27
|
self.name = lg_attack_step.name
|
|
29
28
|
self.type = lg_attack_step.type
|
|
30
|
-
self.ttc = lg_attack_step.ttc
|
|
29
|
+
self.ttc = ttc_dist if ttc_dist is not None else lg_attack_step.ttc
|
|
31
30
|
self.tags = lg_attack_step.tags
|
|
32
31
|
self.detectors = lg_attack_step.detectors
|
|
33
32
|
|
|
34
33
|
self.id = node_id
|
|
35
34
|
self.model_asset = model_asset
|
|
36
|
-
self.defense_status = defense_status
|
|
37
35
|
self.existence_status = existence_status
|
|
38
|
-
|
|
39
36
|
self.children: set[AttackGraphNode] = set()
|
|
40
37
|
self.parents: set[AttackGraphNode] = set()
|
|
41
|
-
self.is_viable: bool = True
|
|
42
|
-
self.is_necessary: bool = True
|
|
43
|
-
self.compromised_by: set[Attacker] = set()
|
|
44
38
|
self.extras: dict = {}
|
|
45
39
|
|
|
46
40
|
def to_dict(self) -> dict:
|
|
@@ -55,22 +49,14 @@ class AttackGraphNode:
|
|
|
55
49
|
self.children},
|
|
56
50
|
'parents': {parent.id: parent.full_name for parent in
|
|
57
51
|
self.parents},
|
|
58
|
-
'compromised_by': [attacker.name for attacker in \
|
|
59
|
-
self.compromised_by]
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
for detector in self.detectors.values():
|
|
63
55
|
node_dict.setdefault('detectors', {})[detector.name] = detector.to_dict()
|
|
64
56
|
if self.model_asset is not None:
|
|
65
57
|
node_dict['asset'] = str(self.model_asset.name)
|
|
66
|
-
if self.defense_status is not None:
|
|
67
|
-
node_dict['defense_status'] = str(self.defense_status)
|
|
68
58
|
if self.existence_status is not None:
|
|
69
59
|
node_dict['existence_status'] = str(self.existence_status)
|
|
70
|
-
if self.is_viable is not None:
|
|
71
|
-
node_dict['is_viable'] = str(self.is_viable)
|
|
72
|
-
if self.is_necessary is not None:
|
|
73
|
-
node_dict['is_necessary'] = str(self.is_necessary)
|
|
74
60
|
if self.tags:
|
|
75
61
|
node_dict['tags'] = list(self.tags)
|
|
76
62
|
if self.extras:
|
|
@@ -108,10 +94,7 @@ class AttackGraphNode:
|
|
|
108
94
|
copied_node.extras = copy.deepcopy(self.extras, memo)
|
|
109
95
|
copied_node.ttc = copy.deepcopy(self.ttc, memo)
|
|
110
96
|
|
|
111
|
-
copied_node.defense_status = self.defense_status
|
|
112
97
|
copied_node.existence_status = self.existence_status
|
|
113
|
-
copied_node.is_viable = self.is_viable
|
|
114
|
-
copied_node.is_necessary = self.is_necessary
|
|
115
98
|
|
|
116
99
|
# Remember that self was already copied
|
|
117
100
|
memo[id(self)] = copied_node
|
|
@@ -119,69 +102,6 @@ class AttackGraphNode:
|
|
|
119
102
|
return copied_node
|
|
120
103
|
|
|
121
104
|
|
|
122
|
-
def is_compromised(self) -> bool:
|
|
123
|
-
"""
|
|
124
|
-
Return True if any attackers have compromised this node.
|
|
125
|
-
False, otherwise.
|
|
126
|
-
"""
|
|
127
|
-
return len(self.compromised_by) > 0
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def is_compromised_by(self, attacker: Attacker) -> bool:
|
|
131
|
-
"""
|
|
132
|
-
Return True if the attacker given as an argument has compromised this
|
|
133
|
-
node.
|
|
134
|
-
False, otherwise.
|
|
135
|
-
|
|
136
|
-
Arguments:
|
|
137
|
-
attacker - the attacker we are interested in
|
|
138
|
-
"""
|
|
139
|
-
return attacker in self.compromised_by
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def compromise(self, attacker: Attacker) -> None:
|
|
143
|
-
"""
|
|
144
|
-
Have the attacker given as a parameter compromise this node.
|
|
145
|
-
|
|
146
|
-
Arguments:
|
|
147
|
-
attacker - the attacker that will compromise the node
|
|
148
|
-
"""
|
|
149
|
-
attacker.compromise(self)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def undo_compromise(self, attacker: Attacker) -> None:
|
|
153
|
-
"""
|
|
154
|
-
Remove the attacker given as a parameter from the list of attackers
|
|
155
|
-
that have compromised this node.
|
|
156
|
-
|
|
157
|
-
Arguments:
|
|
158
|
-
attacker - the attacker that we wish to remove from the compromised
|
|
159
|
-
list.
|
|
160
|
-
"""
|
|
161
|
-
attacker.undo_compromise(self)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def is_enabled_defense(self) -> bool:
|
|
165
|
-
"""
|
|
166
|
-
Return True if this node is a defense node and it is enabled and not
|
|
167
|
-
suppressed via tags.
|
|
168
|
-
False, otherwise.
|
|
169
|
-
"""
|
|
170
|
-
return self.type == 'defense' and \
|
|
171
|
-
'suppress' not in self.tags and \
|
|
172
|
-
self.defense_status == 1.0
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def is_available_defense(self) -> bool:
|
|
176
|
-
"""
|
|
177
|
-
Return True if this node is a defense node and it is not fully enabled
|
|
178
|
-
and not suppressed via tags. False otherwise.
|
|
179
|
-
"""
|
|
180
|
-
return self.type == 'defense' and \
|
|
181
|
-
'suppress' not in self.tags and \
|
|
182
|
-
self.defense_status != 1.0
|
|
183
|
-
|
|
184
|
-
|
|
185
105
|
@property
|
|
186
106
|
def full_name(self) -> str:
|
|
187
107
|
"""
|
maltoolbox/file_utils.py
CHANGED
maltoolbox/language/__init__.py
CHANGED
|
@@ -10,3 +10,14 @@ from .languagegraph import (
|
|
|
10
10
|
LanguageGraphAttackStep,
|
|
11
11
|
disaggregate_attack_step_full_name,
|
|
12
12
|
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"Context",
|
|
16
|
+
"Detector",
|
|
17
|
+
"ExpressionsChain",
|
|
18
|
+
"LanguageGraph",
|
|
19
|
+
"LanguageGraphAsset",
|
|
20
|
+
"LanguageGraphAssociation",
|
|
21
|
+
"LanguageGraphAttackStep",
|
|
22
|
+
"disaggregate_attack_step_full_name"
|
|
23
|
+
]
|