mal-toolbox 0.0.40__tar.gz → 0.1.1__tar.gz
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.0.40/mal_toolbox.egg-info → mal_toolbox-0.1.1}/PKG-INFO +38 -24
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/README.md +37 -23
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1/mal_toolbox.egg-info}/PKG-INFO +38 -24
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/SOURCES.txt +6 -1
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/__init__.py +10 -9
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/__main__.py +1 -2
- mal_toolbox-0.1.1/maltoolbox/attackgraph/analyzers/__init__.py +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/analyzers/apriori.py +39 -22
- mal_toolbox-0.1.1/maltoolbox/attackgraph/attacker.py +102 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/attackgraph.py +330 -143
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/node.py +46 -30
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/query.py +62 -28
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/exceptions.py +13 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/file_utils.py +11 -6
- mal_toolbox-0.1.1/maltoolbox/ingestors/__init__.py +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/ingestors/neo4j.py +68 -70
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/classes_factory.py +37 -21
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/__init__.py +5 -2
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_lexer.py +1 -1
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_parser.py +1 -1
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_visitor.py +4 -5
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/languagegraph.py +268 -171
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/specification.py +19 -18
- mal_toolbox-0.1.1/maltoolbox/model.py +743 -0
- mal_toolbox-0.1.1/maltoolbox/translators/__init__.py +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/translators/securicad.py +49 -33
- mal_toolbox-0.1.1/maltoolbox/translators/updater.py +132 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/wrappers.py +1 -1
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/pyproject.toml +10 -1
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/tests/test_model.py +172 -53
- mal_toolbox-0.1.1/tests/test_wrappers.py +10 -0
- mal_toolbox-0.0.40/maltoolbox/attackgraph/attacker.py +0 -70
- mal_toolbox-0.0.40/maltoolbox/model.py +0 -492
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/AUTHORS +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/LICENSE +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/dependency_links.txt +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/requires.txt +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/top_level.txt +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/__init__.py +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/default.conf +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/__init__.py +0 -0
- {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mal-toolbox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: A collection of tools used to create MAL models and attack graphs.
|
|
5
5
|
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Joakim Loxdal <loxdal@kth.se>
|
|
6
6
|
License: Apache Software License
|
|
@@ -25,16 +25,19 @@ Requires-Dist: antlr4-python3-runtime
|
|
|
25
25
|
Requires-Dist: docopt
|
|
26
26
|
Requires-Dist: PyYAML
|
|
27
27
|
|
|
28
|
-
#
|
|
28
|
+
# MAL Toolbox overview
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
models and attack graphs.
|
|
30
|
+
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
31
|
+
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
|
|
34
|
+
MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
|
|
35
|
+
|
|
36
|
+
## The Language Module
|
|
34
37
|
|
|
35
38
|
The language module provides various tools to process MAL languages.
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
### The Language Specification Submodule
|
|
38
41
|
|
|
39
42
|
The language specification submodule provides functions to load the
|
|
40
43
|
specification from a .mar archive(`load_language_specification_from_mar`) or a
|
|
@@ -43,7 +46,7 @@ then be used to generate python classes representing the assets and
|
|
|
43
46
|
associations of the language and to determine the attack steps for each asset
|
|
44
47
|
when generating the attack graph.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
### The Language Classes Factory Submodule
|
|
47
50
|
|
|
48
51
|
The language classes factory submodule is used to generate python classes
|
|
49
52
|
using the `python_jsonschema_objects` package from a language specification.
|
|
@@ -54,19 +57,23 @@ using JSON Schema validators they will enforce their restrictions when using
|
|
|
54
57
|
the python objects created. These classes are typically used in conjunction
|
|
55
58
|
with model module to create instance models.
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
## The Model Module
|
|
61
|
+
|
|
62
|
+
With a MAL language a Model (a MAL instance model) can be created either
|
|
63
|
+
from a model file or empty.
|
|
64
|
+
|
|
65
|
+
The model class will store all of the relevant information to the MAL
|
|
66
|
+
instance model, most importantly the assets and associations that make it up.
|
|
67
|
+
|
|
68
|
+
Assets and associations are objects of classes created using the language
|
|
69
|
+
classes factory submodule in runtime. It also allows for `Attacker` objects
|
|
70
|
+
to be created and associated with attack steps on assets in the model.
|
|
71
|
+
The most relevant methods of the Model are the ones used to add different
|
|
72
|
+
elements to the model, `add_asset`, `add_association`, and `add_attacker`.
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
store all of the relevant information to the MAL instance model, most
|
|
61
|
-
importantly the assets and associations that make it up. These assets and
|
|
62
|
-
associations should be objects created using the language classes factory
|
|
63
|
-
submodule. It also allows for `Attacker` objects to be created and associated
|
|
64
|
-
with attack steps on assets in the model. The most relevant functions here are
|
|
65
|
-
the ones used to add different elements to the model, `add_asset`,
|
|
66
|
-
`add_association`, and `add_attacker`. Model objects can be used to generate
|
|
67
|
-
attack graphs using the attack graph module.
|
|
74
|
+
Model objects can be used to generate attack graphs with the AttackGraph module.
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
## The Attack Graph Module
|
|
70
77
|
|
|
71
78
|
The attack graph module contains tools used to generate attack graphs from
|
|
72
79
|
existing MAL instance models and analyse MAL attack graphs. The function used
|
|
@@ -84,14 +91,21 @@ resulting attack graph with the instance model given as a parameter in order
|
|
|
84
91
|
to create attack step nodes that represent the entry points of the attackers
|
|
85
92
|
and attach them to the attack steps specified in the instance model.
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
## Ingestors Module
|
|
88
95
|
|
|
89
96
|
The ingestors module contains various tools that can make use of the instance
|
|
90
97
|
model or attack graph. Currently the Neo4J ingestor is the only one available
|
|
91
98
|
and it can be used to visualise the instance model and the attack graph.
|
|
92
99
|
|
|
93
|
-
# Command Line Client
|
|
94
100
|
|
|
101
|
+
# Usage
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
A default configuration file `default.conf` can be found in the package
|
|
105
|
+
directory. This contains the default values to use for logging and can also be
|
|
106
|
+
used to store the information needed to access the local Neo4J instance.
|
|
107
|
+
|
|
108
|
+
## Command Line Client
|
|
95
109
|
In addition to the modules that make up the MAL-Toolbox package it also
|
|
96
110
|
provides a simple command line client that can be used to easily generate
|
|
97
111
|
attack graphs from a .mar language specification file and a JSON instance
|
|
@@ -103,10 +117,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
|
|
|
103
117
|
If the `--neo4j` flag is specified the model and attack graph will be loaded
|
|
104
118
|
into a local Neo4J instance.
|
|
105
119
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
## Code examples / Tutorial
|
|
121
|
+
|
|
122
|
+
To find code examples and tutorials, visit the
|
|
123
|
+
[MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
|
|
110
124
|
|
|
111
125
|
# Tests
|
|
112
126
|
There are unit tests inside of ./tests.
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MAL Toolbox overview
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
models and attack graphs.
|
|
3
|
+
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
4
|
+
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
|
|
7
|
+
MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
|
|
8
|
+
|
|
9
|
+
## The Language Module
|
|
7
10
|
|
|
8
11
|
The language module provides various tools to process MAL languages.
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
### The Language Specification Submodule
|
|
11
14
|
|
|
12
15
|
The language specification submodule provides functions to load the
|
|
13
16
|
specification from a .mar archive(`load_language_specification_from_mar`) or a
|
|
@@ -16,7 +19,7 @@ then be used to generate python classes representing the assets and
|
|
|
16
19
|
associations of the language and to determine the attack steps for each asset
|
|
17
20
|
when generating the attack graph.
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
### The Language Classes Factory Submodule
|
|
20
23
|
|
|
21
24
|
The language classes factory submodule is used to generate python classes
|
|
22
25
|
using the `python_jsonschema_objects` package from a language specification.
|
|
@@ -27,19 +30,23 @@ using JSON Schema validators they will enforce their restrictions when using
|
|
|
27
30
|
the python objects created. These classes are typically used in conjunction
|
|
28
31
|
with model module to create instance models.
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
## The Model Module
|
|
34
|
+
|
|
35
|
+
With a MAL language a Model (a MAL instance model) can be created either
|
|
36
|
+
from a model file or empty.
|
|
37
|
+
|
|
38
|
+
The model class will store all of the relevant information to the MAL
|
|
39
|
+
instance model, most importantly the assets and associations that make it up.
|
|
40
|
+
|
|
41
|
+
Assets and associations are objects of classes created using the language
|
|
42
|
+
classes factory submodule in runtime. It also allows for `Attacker` objects
|
|
43
|
+
to be created and associated with attack steps on assets in the model.
|
|
44
|
+
The most relevant methods of the Model are the ones used to add different
|
|
45
|
+
elements to the model, `add_asset`, `add_association`, and `add_attacker`.
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
store all of the relevant information to the MAL instance model, most
|
|
34
|
-
importantly the assets and associations that make it up. These assets and
|
|
35
|
-
associations should be objects created using the language classes factory
|
|
36
|
-
submodule. It also allows for `Attacker` objects to be created and associated
|
|
37
|
-
with attack steps on assets in the model. The most relevant functions here are
|
|
38
|
-
the ones used to add different elements to the model, `add_asset`,
|
|
39
|
-
`add_association`, and `add_attacker`. Model objects can be used to generate
|
|
40
|
-
attack graphs using the attack graph module.
|
|
47
|
+
Model objects can be used to generate attack graphs with the AttackGraph module.
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
## The Attack Graph Module
|
|
43
50
|
|
|
44
51
|
The attack graph module contains tools used to generate attack graphs from
|
|
45
52
|
existing MAL instance models and analyse MAL attack graphs. The function used
|
|
@@ -57,14 +64,21 @@ resulting attack graph with the instance model given as a parameter in order
|
|
|
57
64
|
to create attack step nodes that represent the entry points of the attackers
|
|
58
65
|
and attach them to the attack steps specified in the instance model.
|
|
59
66
|
|
|
60
|
-
|
|
67
|
+
## Ingestors Module
|
|
61
68
|
|
|
62
69
|
The ingestors module contains various tools that can make use of the instance
|
|
63
70
|
model or attack graph. Currently the Neo4J ingestor is the only one available
|
|
64
71
|
and it can be used to visualise the instance model and the attack graph.
|
|
65
72
|
|
|
66
|
-
# Command Line Client
|
|
67
73
|
|
|
74
|
+
# Usage
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
77
|
+
A default configuration file `default.conf` can be found in the package
|
|
78
|
+
directory. This contains the default values to use for logging and can also be
|
|
79
|
+
used to store the information needed to access the local Neo4J instance.
|
|
80
|
+
|
|
81
|
+
## Command Line Client
|
|
68
82
|
In addition to the modules that make up the MAL-Toolbox package it also
|
|
69
83
|
provides a simple command line client that can be used to easily generate
|
|
70
84
|
attack graphs from a .mar language specification file and a JSON instance
|
|
@@ -76,10 +90,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
|
|
|
76
90
|
If the `--neo4j` flag is specified the model and attack graph will be loaded
|
|
77
91
|
into a local Neo4J instance.
|
|
78
92
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
## Code examples / Tutorial
|
|
94
|
+
|
|
95
|
+
To find code examples and tutorials, visit the
|
|
96
|
+
[MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
|
|
83
97
|
|
|
84
98
|
# Tests
|
|
85
99
|
There are unit tests inside of ./tests.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mal-toolbox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: A collection of tools used to create MAL models and attack graphs.
|
|
5
5
|
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Joakim Loxdal <loxdal@kth.se>
|
|
6
6
|
License: Apache Software License
|
|
@@ -25,16 +25,19 @@ Requires-Dist: antlr4-python3-runtime
|
|
|
25
25
|
Requires-Dist: docopt
|
|
26
26
|
Requires-Dist: PyYAML
|
|
27
27
|
|
|
28
|
-
#
|
|
28
|
+
# MAL Toolbox overview
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
models and attack graphs.
|
|
30
|
+
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
31
|
+
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
|
|
34
|
+
MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
|
|
35
|
+
|
|
36
|
+
## The Language Module
|
|
34
37
|
|
|
35
38
|
The language module provides various tools to process MAL languages.
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
### The Language Specification Submodule
|
|
38
41
|
|
|
39
42
|
The language specification submodule provides functions to load the
|
|
40
43
|
specification from a .mar archive(`load_language_specification_from_mar`) or a
|
|
@@ -43,7 +46,7 @@ then be used to generate python classes representing the assets and
|
|
|
43
46
|
associations of the language and to determine the attack steps for each asset
|
|
44
47
|
when generating the attack graph.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
### The Language Classes Factory Submodule
|
|
47
50
|
|
|
48
51
|
The language classes factory submodule is used to generate python classes
|
|
49
52
|
using the `python_jsonschema_objects` package from a language specification.
|
|
@@ -54,19 +57,23 @@ using JSON Schema validators they will enforce their restrictions when using
|
|
|
54
57
|
the python objects created. These classes are typically used in conjunction
|
|
55
58
|
with model module to create instance models.
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
## The Model Module
|
|
61
|
+
|
|
62
|
+
With a MAL language a Model (a MAL instance model) can be created either
|
|
63
|
+
from a model file or empty.
|
|
64
|
+
|
|
65
|
+
The model class will store all of the relevant information to the MAL
|
|
66
|
+
instance model, most importantly the assets and associations that make it up.
|
|
67
|
+
|
|
68
|
+
Assets and associations are objects of classes created using the language
|
|
69
|
+
classes factory submodule in runtime. It also allows for `Attacker` objects
|
|
70
|
+
to be created and associated with attack steps on assets in the model.
|
|
71
|
+
The most relevant methods of the Model are the ones used to add different
|
|
72
|
+
elements to the model, `add_asset`, `add_association`, and `add_attacker`.
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
store all of the relevant information to the MAL instance model, most
|
|
61
|
-
importantly the assets and associations that make it up. These assets and
|
|
62
|
-
associations should be objects created using the language classes factory
|
|
63
|
-
submodule. It also allows for `Attacker` objects to be created and associated
|
|
64
|
-
with attack steps on assets in the model. The most relevant functions here are
|
|
65
|
-
the ones used to add different elements to the model, `add_asset`,
|
|
66
|
-
`add_association`, and `add_attacker`. Model objects can be used to generate
|
|
67
|
-
attack graphs using the attack graph module.
|
|
74
|
+
Model objects can be used to generate attack graphs with the AttackGraph module.
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
## The Attack Graph Module
|
|
70
77
|
|
|
71
78
|
The attack graph module contains tools used to generate attack graphs from
|
|
72
79
|
existing MAL instance models and analyse MAL attack graphs. The function used
|
|
@@ -84,14 +91,21 @@ resulting attack graph with the instance model given as a parameter in order
|
|
|
84
91
|
to create attack step nodes that represent the entry points of the attackers
|
|
85
92
|
and attach them to the attack steps specified in the instance model.
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
## Ingestors Module
|
|
88
95
|
|
|
89
96
|
The ingestors module contains various tools that can make use of the instance
|
|
90
97
|
model or attack graph. Currently the Neo4J ingestor is the only one available
|
|
91
98
|
and it can be used to visualise the instance model and the attack graph.
|
|
92
99
|
|
|
93
|
-
# Command Line Client
|
|
94
100
|
|
|
101
|
+
# Usage
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
A default configuration file `default.conf` can be found in the package
|
|
105
|
+
directory. This contains the default values to use for logging and can also be
|
|
106
|
+
used to store the information needed to access the local Neo4J instance.
|
|
107
|
+
|
|
108
|
+
## Command Line Client
|
|
95
109
|
In addition to the modules that make up the MAL-Toolbox package it also
|
|
96
110
|
provides a simple command line client that can be used to easily generate
|
|
97
111
|
attack graphs from a .mar language specification file and a JSON instance
|
|
@@ -103,10 +117,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
|
|
|
103
117
|
If the `--neo4j` flag is specified the model and attack graph will be loaded
|
|
104
118
|
into a local Neo4J instance.
|
|
105
119
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
## Code examples / Tutorial
|
|
121
|
+
|
|
122
|
+
To find code examples and tutorials, visit the
|
|
123
|
+
[MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
|
|
110
124
|
|
|
111
125
|
# Tests
|
|
112
126
|
There are unit tests inside of ./tests.
|
|
@@ -19,7 +19,9 @@ maltoolbox/attackgraph/attacker.py
|
|
|
19
19
|
maltoolbox/attackgraph/attackgraph.py
|
|
20
20
|
maltoolbox/attackgraph/node.py
|
|
21
21
|
maltoolbox/attackgraph/query.py
|
|
22
|
+
maltoolbox/attackgraph/analyzers/__init__.py
|
|
22
23
|
maltoolbox/attackgraph/analyzers/apriori.py
|
|
24
|
+
maltoolbox/ingestors/__init__.py
|
|
23
25
|
maltoolbox/ingestors/neo4j.py
|
|
24
26
|
maltoolbox/language/__init__.py
|
|
25
27
|
maltoolbox/language/classes_factory.py
|
|
@@ -29,5 +31,8 @@ maltoolbox/language/compiler/__init__.py
|
|
|
29
31
|
maltoolbox/language/compiler/mal_lexer.py
|
|
30
32
|
maltoolbox/language/compiler/mal_parser.py
|
|
31
33
|
maltoolbox/language/compiler/mal_visitor.py
|
|
34
|
+
maltoolbox/translators/__init__.py
|
|
32
35
|
maltoolbox/translators/securicad.py
|
|
33
|
-
|
|
36
|
+
maltoolbox/translators/updater.py
|
|
37
|
+
tests/test_model.py
|
|
38
|
+
tests/test_wrappers.py
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# MAL Toolbox v0.
|
|
2
|
+
# MAL Toolbox v0.1.1
|
|
3
3
|
# Copyright 2024, Andrei Buhaiu.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -21,7 +21,7 @@ MAL-Toolbox Framework
|
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
__title__ = 'maltoolbox'
|
|
24
|
-
__version__ = '0.
|
|
24
|
+
__version__ = '0.1.1'
|
|
25
25
|
__authors__ = ['Andrei Buhaiu',
|
|
26
26
|
'Giuseppe Nebbione',
|
|
27
27
|
'Nikolaos Kakouros',
|
|
@@ -33,7 +33,6 @@ __docformat__ = 'restructuredtext en'
|
|
|
33
33
|
__all__ = ()
|
|
34
34
|
|
|
35
35
|
import os
|
|
36
|
-
import sys
|
|
37
36
|
import configparser
|
|
38
37
|
import logging
|
|
39
38
|
|
|
@@ -74,15 +73,18 @@ log_level = log_configs['log_level']
|
|
|
74
73
|
if log_level != '':
|
|
75
74
|
level = logging.getLevelName(log_level)
|
|
76
75
|
logger.setLevel(level)
|
|
77
|
-
logger.info(
|
|
76
|
+
logger.info('Set loggin level of %s to %s.', __name__, log_level)
|
|
78
77
|
|
|
79
78
|
if 'neo4j' in config:
|
|
80
79
|
for term in ['uri', 'username', 'password', 'dbname']:
|
|
81
80
|
if term not in config['neo4j']:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
f'
|
|
81
|
+
|
|
82
|
+
msg = (
|
|
83
|
+
'Config file is missing essential Neo4J '
|
|
84
|
+
f'information: {term}, cannot proceed.'
|
|
85
|
+
)
|
|
86
|
+
logger.critical(msg)
|
|
87
|
+
raise ValueError(msg)
|
|
86
88
|
|
|
87
89
|
neo4j_configs = {
|
|
88
90
|
'uri': config['neo4j']['uri'],
|
|
@@ -90,4 +92,3 @@ if 'neo4j' in config:
|
|
|
90
92
|
'password': config['neo4j']['password'],
|
|
91
93
|
'dbname': config['neo4j']['dbname'],
|
|
92
94
|
}
|
|
93
|
-
|
|
@@ -68,10 +68,9 @@ def generate_attack_graph(
|
|
|
68
68
|
delete=False)
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
def compile(lang_file, output_file):
|
|
71
|
+
def compile(lang_file: str, output_file: str) -> None:
|
|
72
72
|
"""Compile language and dump into output file"""
|
|
73
73
|
compiler = MalCompiler()
|
|
74
|
-
|
|
75
74
|
with open(output_file, "w") as f:
|
|
76
75
|
json.dump(compiler.compile(lang_file), f, indent=2)
|
|
77
76
|
|
|
File without changes
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
"""
|
|
4
2
|
MAL-Toolbox Attack Graph Apriori Analyzer Submodule
|
|
5
3
|
|
|
@@ -13,6 +11,7 @@ Currently these are:
|
|
|
13
11
|
compromised) to compromise children attack steps.
|
|
14
12
|
"""
|
|
15
13
|
|
|
14
|
+
from __future__ import annotations
|
|
16
15
|
import logging
|
|
17
16
|
|
|
18
17
|
from ..attackgraph import AttackGraph
|
|
@@ -20,14 +19,16 @@ from ..node import AttackGraphNode
|
|
|
20
19
|
|
|
21
20
|
logger = logging.getLogger(__name__)
|
|
22
21
|
|
|
23
|
-
def propagate_viability_from_node(node: AttackGraphNode):
|
|
22
|
+
def propagate_viability_from_node(node: AttackGraphNode) -> None:
|
|
24
23
|
"""
|
|
25
24
|
Arguments:
|
|
26
25
|
node - the attack graph node from which to propagate the viable
|
|
27
26
|
status
|
|
28
27
|
"""
|
|
29
|
-
logger.debug(
|
|
30
|
-
|
|
28
|
+
logger.debug(
|
|
29
|
+
'Propagate viability from "%s"(%d) with viability status %s.',
|
|
30
|
+
node.full_name, node.id, node.is_viable
|
|
31
|
+
)
|
|
31
32
|
for child in node.children:
|
|
32
33
|
original_value = child.is_viable
|
|
33
34
|
if child.type == 'or':
|
|
@@ -40,14 +41,16 @@ def propagate_viability_from_node(node: AttackGraphNode):
|
|
|
40
41
|
if child.is_viable != original_value:
|
|
41
42
|
propagate_viability_from_node(child)
|
|
42
43
|
|
|
43
|
-
def propagate_necessity_from_node(node: AttackGraphNode):
|
|
44
|
+
def propagate_necessity_from_node(node: AttackGraphNode) -> None:
|
|
44
45
|
"""
|
|
45
46
|
Arguments:
|
|
46
47
|
node - the attack graph node from which to propagate the necessary
|
|
47
48
|
status
|
|
48
49
|
"""
|
|
49
|
-
logger.debug(
|
|
50
|
-
|
|
50
|
+
logger.debug(
|
|
51
|
+
'Propagate necessity from "%s"(%d) with necessity status %s.',
|
|
52
|
+
node.full_name, node.id, node.is_necessary
|
|
53
|
+
)
|
|
51
54
|
for child in node.children:
|
|
52
55
|
original_value = child.is_necessary
|
|
53
56
|
if child.type == 'or':
|
|
@@ -63,17 +66,24 @@ def propagate_necessity_from_node(node: AttackGraphNode):
|
|
|
63
66
|
propagate_necessity_from_node(child)
|
|
64
67
|
|
|
65
68
|
|
|
66
|
-
def evaluate_viability(node):
|
|
69
|
+
def evaluate_viability(node: AttackGraphNode) -> None:
|
|
67
70
|
"""
|
|
68
71
|
Arguments:
|
|
69
72
|
graph - the node to evaluate viability for.
|
|
70
73
|
"""
|
|
71
74
|
match (node.type):
|
|
72
75
|
case 'exist':
|
|
76
|
+
assert isinstance(node.existence_status, bool), \
|
|
77
|
+
f'Existence status not defined for {node.full_name}.'
|
|
73
78
|
node.is_viable = node.existence_status
|
|
74
79
|
case 'notExist':
|
|
80
|
+
assert isinstance(node.existence_status, bool), \
|
|
81
|
+
f'Existence status not defined for {node.full_name}.'
|
|
75
82
|
node.is_viable = not node.existence_status
|
|
76
83
|
case 'defense':
|
|
84
|
+
assert node.defense_status is not None and \
|
|
85
|
+
0.0 <= node.defense_status <= 1.0, \
|
|
86
|
+
f'{node.full_name} defense status invalid: {node.defense_status}.'
|
|
77
87
|
node.is_viable = node.defense_status != 1.0
|
|
78
88
|
case 'or':
|
|
79
89
|
node.is_viable = False
|
|
@@ -84,22 +94,29 @@ def evaluate_viability(node):
|
|
|
84
94
|
for parent in node.parents:
|
|
85
95
|
node.is_viable = node.is_viable and parent.is_viable
|
|
86
96
|
case _:
|
|
87
|
-
msg =
|
|
88
|
-
|
|
89
|
-
logger.error(msg)
|
|
90
|
-
raise ValueError(msg)
|
|
97
|
+
msg = ('Evaluate viability was provided node "%s"(%d) which '
|
|
98
|
+
'is of unknown type "%s"')
|
|
99
|
+
logger.error(msg, node.full_name, node.id, node.type)
|
|
100
|
+
raise ValueError(msg % (node.full_name, node.id, node.type))
|
|
91
101
|
|
|
92
|
-
def evaluate_necessity(node):
|
|
102
|
+
def evaluate_necessity(node: AttackGraphNode) -> None:
|
|
93
103
|
"""
|
|
94
104
|
Arguments:
|
|
95
105
|
graph - the node to evaluate necessity for.
|
|
96
106
|
"""
|
|
97
107
|
match (node.type):
|
|
98
108
|
case 'exist':
|
|
109
|
+
assert isinstance(node.existence_status, bool), \
|
|
110
|
+
f'Existence status not defined for {node.full_name}.'
|
|
99
111
|
node.is_necessary = not node.existence_status
|
|
100
112
|
case 'notExist':
|
|
101
|
-
node.
|
|
113
|
+
assert isinstance(node.existence_status, bool), \
|
|
114
|
+
f'Existence status not defined for {node.full_name}.'
|
|
115
|
+
node.is_necessary = bool(node.existence_status)
|
|
102
116
|
case 'defense':
|
|
117
|
+
assert node.defense_status is not None and \
|
|
118
|
+
0.0 <= node.defense_status <= 1.0, \
|
|
119
|
+
f'{node.full_name} defense status invalid: {node.defense_status}.'
|
|
103
120
|
node.is_necessary = node.defense_status != 0.0
|
|
104
121
|
case 'or':
|
|
105
122
|
node.is_necessary = True
|
|
@@ -110,12 +127,12 @@ def evaluate_necessity(node):
|
|
|
110
127
|
for parent in node.parents:
|
|
111
128
|
node.is_necessary = node.is_necessary or parent.is_necessary
|
|
112
129
|
case _:
|
|
113
|
-
msg =
|
|
114
|
-
|
|
115
|
-
logger.error(msg)
|
|
116
|
-
raise ValueError(msg)
|
|
130
|
+
msg = ('Evaluate necessity was provided node "%s"(%d) which '
|
|
131
|
+
'is of unknown type "%s"')
|
|
132
|
+
logger.error(msg, node.full_name, node.id, node.type)
|
|
133
|
+
raise ValueError(msg % (node.full_name, node.id, node.type))
|
|
117
134
|
|
|
118
|
-
def evaluate_viability_and_necessity(node):
|
|
135
|
+
def evaluate_viability_and_necessity(node: AttackGraphNode) -> None:
|
|
119
136
|
"""
|
|
120
137
|
Arguments:
|
|
121
138
|
graph - the node to evaluate viability and necessity for.
|
|
@@ -123,7 +140,7 @@ def evaluate_viability_and_necessity(node):
|
|
|
123
140
|
evaluate_viability(node)
|
|
124
141
|
evaluate_necessity(node)
|
|
125
142
|
|
|
126
|
-
def calculate_viability_and_necessity(graph: AttackGraph):
|
|
143
|
+
def calculate_viability_and_necessity(graph: AttackGraph) -> None:
|
|
127
144
|
"""
|
|
128
145
|
Arguments:
|
|
129
146
|
graph - the attack graph for which we wish to determine the
|
|
@@ -137,7 +154,7 @@ def calculate_viability_and_necessity(graph: AttackGraph):
|
|
|
137
154
|
if not node.is_necessary:
|
|
138
155
|
propagate_necessity_from_node(node)
|
|
139
156
|
|
|
140
|
-
def prune_unviable_and_unnecessary_nodes(graph: AttackGraph):
|
|
157
|
+
def prune_unviable_and_unnecessary_nodes(graph: AttackGraph) -> None:
|
|
141
158
|
"""
|
|
142
159
|
Arguments:
|
|
143
160
|
graph - the attack graph for which we wish to remove the
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MAL-Toolbox Attack Graph Attacker Class
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .attackgraph import AttackGraphNode
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class Attacker:
|
|
18
|
+
name: str
|
|
19
|
+
entry_points: list[AttackGraphNode] = field(default_factory=list)
|
|
20
|
+
reached_attack_steps: list[AttackGraphNode] = \
|
|
21
|
+
field(default_factory=list)
|
|
22
|
+
id: Optional[int] = None
|
|
23
|
+
|
|
24
|
+
def to_dict(self) -> dict:
|
|
25
|
+
attacker_dict: dict = {
|
|
26
|
+
'id': self.id,
|
|
27
|
+
'name': self.name,
|
|
28
|
+
'entry_points': {},
|
|
29
|
+
'reached_attack_steps': {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for entry_point in self.entry_points:
|
|
33
|
+
attacker_dict['entry_points'][entry_point.id] = \
|
|
34
|
+
entry_point.full_name
|
|
35
|
+
for attack_step in self.reached_attack_steps:
|
|
36
|
+
attacker_dict['reached_attack_steps'][attack_step.id] = \
|
|
37
|
+
attack_step.full_name
|
|
38
|
+
|
|
39
|
+
return attacker_dict
|
|
40
|
+
|
|
41
|
+
def __repr__(self) -> str:
|
|
42
|
+
return str(self.to_dict())
|
|
43
|
+
|
|
44
|
+
def compromise(self, node: AttackGraphNode) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Have the attacke compromise the node given as a parameter.
|
|
47
|
+
|
|
48
|
+
Arguments:
|
|
49
|
+
node - the node that the attacker will compromise
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
logger.debug(
|
|
53
|
+
'Attacker "%s"(%d) is compromising node "%s"(%d).',
|
|
54
|
+
self.name,
|
|
55
|
+
self.id,
|
|
56
|
+
node.full_name,
|
|
57
|
+
node.id
|
|
58
|
+
)
|
|
59
|
+
if node.is_compromised_by(self):
|
|
60
|
+
logger.info(
|
|
61
|
+
'Attacker "%s"(%d) already compromised node "%s"(%d). '
|
|
62
|
+
'Do nothing.',
|
|
63
|
+
self.name,
|
|
64
|
+
self.id,
|
|
65
|
+
node.full_name,
|
|
66
|
+
node.id
|
|
67
|
+
)
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
node.compromised_by.append(self)
|
|
71
|
+
self.reached_attack_steps.append(node)
|
|
72
|
+
|
|
73
|
+
def undo_compromise(self, node: AttackGraphNode) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Remove the attacker from the list of attackers that have compromised
|
|
76
|
+
the node given as a parameter.
|
|
77
|
+
|
|
78
|
+
Arguments:
|
|
79
|
+
node - the node that we wish to remove this attacker from.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
logger.debug(
|
|
83
|
+
'Removing attacker "%s"(%d) from compromised_by '
|
|
84
|
+
'list of node "%s"(%d).',
|
|
85
|
+
self.name,
|
|
86
|
+
self.id,
|
|
87
|
+
node.full_name,
|
|
88
|
+
node.id
|
|
89
|
+
)
|
|
90
|
+
if not node.is_compromised_by(self):
|
|
91
|
+
logger.info(
|
|
92
|
+
'Attacker "%s"(%d) had not compromised node "%s"(%d).'
|
|
93
|
+
' Do nothing.',
|
|
94
|
+
self.name,
|
|
95
|
+
self.id,
|
|
96
|
+
node.full_name,
|
|
97
|
+
node.id
|
|
98
|
+
)
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
node.compromised_by.remove(self)
|
|
102
|
+
self.reached_attack_steps.remove(node)
|