├── .gitattributes ├── .gitignore ├── README.md └── System ├── .gitignore ├── attack-graph-generator.sh ├── attack_vector_files ├── .Rhistory ├── nvdcve-1.0-2002.json ├── nvdcve-1.0-2003.json ├── nvdcve-1.0-2004.json ├── nvdcve-1.0-2005.json ├── nvdcve-1.0-2006.json ├── nvdcve-1.0-2007.json ├── nvdcve-1.0-2008.json ├── nvdcve-1.0-2009.json ├── nvdcve-1.0-2010.json ├── nvdcve-1.0-2011.json ├── nvdcve-1.0-2012.json ├── nvdcve-1.0-2013.json ├── nvdcve-1.0-2014.json ├── nvdcve-1.0-2015.json ├── nvdcve-1.0-2016.json ├── nvdcve-1.0-2017.json ├── nvdcve-1.0-2018.json └── nvdcve-1.0-modified.json ├── components ├── __pycache__ │ ├── attack_graph_parser.cpython-35.pyc │ ├── reader.cpython-35.pyc │ ├── topology_parser.cpython-35.pyc │ ├── vulnerability_parser.cpython-35.pyc │ └── writer.cpython-35.pyc ├── attack_graph_parser.py ├── reader.py ├── topology_parser.py ├── topology_parser.pyc ├── vulnerability_parser.py ├── vurnability_parser.pyc └── writer.py ├── config.yml ├── examples ├── atsea-sample-shop-app-master.zip ├── example │ └── docker-compose.yml ├── exploit-CVE-2016-10033-master.zip ├── exploit-CVE-2017-7494-master.zip ├── javaee-demo-master.zip ├── netflix-oss-example-master-modified.zip └── output_samples │ ├── atsea │ ├── attack_graph.dot │ ├── attack_graph.dot.pdf │ ├── topology_graph.dot │ └── topology_graph.dot.pdf │ ├── javaee │ ├── attack_graph.dot │ ├── attack_graph.dot.pdf │ ├── topology_graph.dot │ └── topology_graph.dot.pdf │ └── netflix-oss-example │ ├── attack_graph.dot │ ├── attack_graph.dot.pdf │ ├── topology_graph.dot │ └── topology_graph.dot.pdf ├── exportGO.sh ├── main.py └── test ├── 1000_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json └── topology.json ├── 100_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json └── topology.json ├── 1_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json ├── topology.json ├── topology_graph.dot └── topology_graph.dot.pdf ├── 20_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json ├── topology.json ├── topology_graph.dot └── topology_graph.dot.pdf ├── 500_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json └── topology.json ├── 50_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json ├── topology.json ├── topology_graph.dot └── topology_graph.dot.pdf ├── 5_example ├── docker-compose.yml ├── example_phpmailer-vulnerabilities.json ├── example_samba-vulnerabilities.json ├── topology.json ├── topology_graph.dot └── topology_graph.dot.pdf ├── atsea ├── atsea_app-vulnerabilities.json ├── atsea_db-vulnerabilities.json ├── atsea_payment_gateway-vulnerabilities.json ├── atsea_reverse_proxy-vulnerabilities.json ├── docker-compose.yml └── topology.json ├── docker_compose_generator.py └── test.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.json filter=lfs diff=lfs merge=lfs -text 2 | *.mkv filter=lfs diff=lfs merge=lfs -text 3 | *.mp4 filter=lfs diff=lfs merge=lfs -text 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | paper_own_docker/main.aux 3 | paper_own_docker/main.log 4 | paper_own_docker/main.pdf 5 | paper_own_docker/main.synctex.gz 6 | *.log 7 | *.aux 8 | paper_own_docker/main.pdf 9 | *.gz 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Academic Citation 2 | Please cite the following paper when using this tool. 3 | 4 | Ibrahim, Amjad, Stevica Bozhinoski, and Alexander Pretschner. "Attack graph generation for microservice architecture." Proceedings of the 34th ACM/SIGAPP Symposium on Applied Computing. ACM, 2019. 5 | 6 | @inproceedings{ibrahim2019attack, 7 | title={Attack graph generation for microservice architecture}, 8 | author={Ibrahim, Amjad and Bozhinoski, Stevica and Pretschner, Alexander}, 9 | booktitle={Proceedings of the 34th ACM/SIGAPP Symposium on Applied Computing}, 10 | pages={1235--1242}, 11 | year={2019}, 12 | organization={ACM} 13 | } 14 | 15 | # Attack Graph Generation for Microservice Architecture 16 | 17 | Microservices are increasingly dominating the field of service systems, among their many characteristics are technology heterogeneity, communicating small services, and automated deployment. 18 | Therefore, with the increase of utilizing third-party components 19 | distributed as images, the potential vulnerabilities existing in a 20 | microservice-based system increase. 21 | 22 | One of the most famous microservice architectures is Docker. This project generates attack graphs for Docker projects. 23 | 24 | ## Getting Started 25 | 26 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. 27 | 28 | ### Prerequisites 29 | 30 | This project works currently only on Ubuntu 16.04.4 LTS. Executing the program for the first time will download all of the needed libraries/components including: 31 | 32 | * [Python 3.6](https://www.python.org/downloads/) - a programming language. 33 | * [Pip](https://pypi.org/project/pip/) - a tool for installing Python packages. 34 | * [Docker Community Edition (CE)](https://docs.docker.com/install/linux/docker-ce/ubuntu/) - a computer program that performs operating-system-level virtualization, also known as "containerization". 35 | * [Docker Compose](https://docs.docker.com/compose/) - a tool for defining and running multi-container Docker applications. 36 | * [Go](https://github.com/golang/go) - an open source programming language that makes it easy to build simple, reliable, and efficient software. 37 | * [Clairctl](https://github.com/jgsqware/clairctl) - a lightweight command-line tool doing the bridge between Registries as Docker Hub, Docker Registry or Quay.io, and the CoreOS vulnerability tracker, Clair. 38 | * [Graphviz](https://www.graphviz.org/) - an open source graph visualization software. 39 | * [Yaml](http://yaml.org/) - a human-readable data serialization language. 40 | * [Networkx](https://networkx.github.io/) - a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks. 41 | * [Numpy](http://www.numpy.org/) - a fundamental package for scientific computing with Python. 42 | 43 | ### Installing 44 | 45 | All of the libraries/components indicated above are automatically installed during the first running of the program. For how to run the program, please refer to the commands bellow. 46 | 47 | ### Running 48 | 49 | In order to run the program, the user needs to enter the home directory of the project and the following command on the terminal should be run: 50 | 51 | ``` 52 | $ sudo ./attack-graph-generator.sh ./examples/atsea 53 | 54 | ``` 55 | 56 | The above command starts the attack-graph-generator.sh script and generates an attack graph for the system ./examples/atsea. This command will download and install the required libraries and set up environment variables when run for the first time. Afterward, it performs the attack graph analysis. 57 | 58 | Other examples are 59 | ``` 60 | $ sudo ./attack-graph-generator.sh ./examples/javaee 61 | $ sudo ./attack-graph-generator.sh ./examples/example 62 | $ sudo ./attack-graph-generator.sh ./examples/netflix-oss-example 63 | 64 | ``` 65 | 66 | * Please note that on the first try, Clair populates the database, so that is why the attack graph will be empty. Furthermore, building the images in the vulnerability-parser for the first time takes longer. The code is tested on a virtual machine running on the above-mentioned operating system. 67 | 68 | ### Customizing the attack graph generation 69 | 70 | The config file is the main point where the attack graphs can be customized. The attack graph generation can be conducted in either online or offline mode. Online mode uses Clair for vulnerabilities detection and takes more time. Offline mode uses already created vulnerability files (by Clair) and performs the attack graph analysis. Therefore, the offline mode does not require an internet connection. Because the edges can have many vulnerabilities, there is an option if we want to display the attack graph with separate edges with different vulnerabilities or combine all of them in one edge. Another option is to display only one vulnerability per edge in the attack graph. Finally, the user has to possibility to modify the pre- and postcondition rules from which the attack graphs are created. For additional details on how to use the config file, please refer to the comments in the config.yml file. 71 | 72 | ## Authors 73 | 74 | * Stevica Bozhinoski stevica.bozhinoski@tum.de 75 | * Amjad Ibrahim, M.Sc. amjad.ibrahim@tum.de 76 | 77 | ## License 78 | 79 | ## Acknowledgments 80 | 81 | We would like to thank the teams of [Clair](https://github.com/coreos/clair) and [Clairctl](https://github.com/jgsqware/clairctl) for their vulnerabilities generator, which is an integral part of our system. Additional thanks to the contributors of all of the third-party tools used in this project. 82 | -------------------------------------------------------------------------------- /System/.gitignore: -------------------------------------------------------------------------------- 1 | examples/atsea 2 | examples/javaee 3 | examples/example 4 | examples-results/* 5 | components/__pycache__ 6 | components/__pycache__/* 7 | -------------------------------------------------------------------------------- /System/attack-graph-generator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "" 4 | echo "Checking if dependencies are installed..." 5 | # Checking if python is installed. 6 | path_python=$(which python3) 7 | length_path_python=$(expr length "$path_python") 8 | if [ "$length_path_python3" = "0" ]; then 9 | echo "Python3.6 is not installed." 10 | sudo apt-get update 11 | sudo apt-get install python3.6 12 | else 13 | echo "Python3.6 is installed." 14 | fi 15 | 16 | path_pip3=$(which pip3) 17 | length_path_pip3=$(expr length "$path_pip3") 18 | if [ "$length_path_pip3" = "0" ]; then 19 | echo "Pip3 is not installed." 20 | sudo apt-get install python3-pip 21 | else 22 | echo "Pip3 is installed." 23 | fi 24 | 25 | # Checking if docker is installed. 26 | path_docker=$(which docker) 27 | length_path_docker=$(expr length "$path_docker") 28 | if [ "$length_path_docker" = "0" ]; then 29 | echo "Docker is not installed." 30 | sudo apt-get install apt-transport-https ca-certificates curl software-properties-common 31 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 32 | sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable" 33 | sudo apt-get update 34 | apt-cache search docker-ce 35 | sudo apt-get install docker-ce 36 | else 37 | echo "Docker is installed." 38 | fi 39 | 40 | # Checking if docker-compose is installed. 41 | path_docker_compose=$(which docker-compose) 42 | length_path_docker_compose=$(expr length "$path_docker_compose") 43 | if [ "$length_path_docker_compose" = "0" ]; then 44 | echo "Docker-compose is not installed." 45 | sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 46 | sudo chmod +x /usr/local/bin/docker-compose 47 | else 48 | echo "Docker-compose is installed." 49 | fi 50 | 51 | # Checking if go is installed. 52 | GO_PATH="/usr/local/go" 53 | if [ -d "$GO_PATH" ]; then 54 | # Control will enter here if $DIRECTORY exists. 55 | echo "Go is installed." 56 | else 57 | echo "Go is not installed. Installing go..." 58 | wget https://dl.google.com/go/go1.10.1.linux-amd64.tar.gz 59 | sudo tar -C /usr/local -xzf go1.10.1.linux-amd64.tar.gz 60 | rm go1.10.1.linux-amd64.tar.gz 61 | fi 62 | 63 | # Checking if go is present. 64 | path_go=$(echo $GOPATH) 65 | length_path_go=$(expr length "$path_go") 66 | if [ $length_path_go = 0 ]; then 67 | echo "GOPATH is not set. Setting GOPATH..." 68 | #export PATH=$PATH:/usr/local/go/bin 69 | #export GOPATH=$GOPATH:/usr/local/go/bin 70 | #GOPATH="/usr/local/go/bin" 71 | #exec /bin/bash 72 | source "exportGO.sh" 73 | else 74 | echo "GOPATH is already set." 75 | fi 76 | sudo chmod -R 777 "/usr/local/go" 77 | 78 | # Checking is clairctl is installed. 79 | CLAIR_CTL_PATH="/usr/local/go/bin/src/github.com/jgsqware/clairctl" 80 | if [ -d "$CLAIR_CTL_PATH" ]; then 81 | # Control will enter here if $DIRECTORY exists. 82 | echo "Clairctl exists." 83 | else 84 | echo "Clairctl does not exist. Please set up clairctl." 85 | 86 | # Creating needed hierarchy for clairctl. 87 | if [ ! -d $GOPATH/src/github.com/jgsqware/clairctl ]; then 88 | echo "Entered here" 89 | mkdir -p -m 777 $GOPATH/src; 90 | mkdir -p -m 777 $GOPATH/src/github.com; 91 | mkdir -p -m 777 $GOPATH/src/github.com/jgsqware; 92 | fi 93 | 94 | 95 | wget https://github.com/jgsqware/clairctl/archive/master.zip 96 | unzip master.zip -d $GOPATH/src/github.com/jgsqware 97 | rm master.zip 98 | mv $GOPATH/src/github.com/jgsqware/clairctl-master $GOPATH/src/github.com/jgsqware/clairctl 99 | fi 100 | 101 | # Installing graphviz 102 | python3 -c "import graphviz" &> /dev/null 103 | if [ "$?" = "1" ]; then 104 | echo "Graphviz has not been installed. Installing Graphviz..." 105 | sudo pip3 install graphviz 106 | else 107 | echo "Graphviz is installed." 108 | fi 109 | 110 | sudo apt-get install graphviz 111 | 112 | # Installing yaml 113 | python3 -c "import yaml" &> /dev/null 114 | if [ "$?" = "1" ]; then 115 | echo "Pyyaml has not been installed. Installing Pyyaml..." 116 | sudo pip3 install pyyaml 117 | else 118 | echo "Pyyaml is installed." 119 | fi 120 | 121 | # Installing networkx 122 | python3 -c "import networkx" &> /dev/null 123 | if [ "$?" = "1" ]; then 124 | echo "Networkx has not been installed. Installing Networkx..." 125 | sudo pip3 install networkx 126 | else 127 | echo "Networkx is installed." 128 | fi 129 | 130 | # Installing numpy 131 | python3 -c "import numpy" &> /dev/null 132 | if [ "$?" = "1" ]; then 133 | echo "Numpy has not been installed. Installing Numpy..." 134 | sudo pip3 install numpy 135 | else 136 | echo "Numpy is installed." 137 | fi 138 | 139 | # Installing unzip 140 | sudo apt-get install unzip 141 | 142 | # Creating examples 143 | # Atsea 144 | unzip examples/atsea-sample-shop-app-master.zip -d examples 145 | sudo chmod -R 777 examples/atsea-sample-shop-app-master 146 | mv examples/atsea-sample-shop-app-master examples/atsea 147 | 148 | # Javaee 149 | unzip examples/javaee-demo-master.zip -d examples 150 | sudo chmod -R 777 examples/javaee-demo-master 151 | mv examples/javaee-demo-master examples/javaee 152 | 153 | # Samba 154 | unzip examples/exploit-CVE-2017-7494-master -d examples 155 | sudo chmod -R 777 examples/exploit-CVE-2017-7494-master 156 | mv examples/exploit-CVE-2017-7494-master examples/example/samba 157 | 158 | # Phpmailer 159 | unzip examples/exploit-CVE-2016-10033-master -d examples 160 | sudo chmod -R 777 examples/exploit-CVE-2016-10033-master 161 | mv examples/exploit-CVE-2016-10033-master examples/example/phpmailer 162 | 163 | # Netflix OSS example 164 | unzip examples/netflix-oss-example-master-modified -d examples 165 | sudo chmod -R 777 examples/netflix-oss-example-master-modified 166 | mv examples/netflix-oss-example-master-modified examples/netflix-oss-example 167 | 168 | #sudo groupadd docker 169 | #sudo usermod -aG docker $(whoami) 170 | #sudo service docker start 171 | 172 | # Checks if the number of arguments is correct. 173 | if [ $# == 1 ]; then 174 | echo "The dependencies are installed. Starting the attack graph generator." 175 | echo "" 176 | sudo python3 main.py $1 177 | else 178 | echo "You need to provide one argument(folder for the project)." 179 | fi 180 | 181 | if [ $1 == "--help" ]; then 182 | echo "Option --help turned on" 183 | echo "Command: ./attack-graph-generator.sh " 184 | echo " is the folder that we want to analyze." 185 | echo " is the name of the docker that the attacker wants to control." 186 | fi 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /System/attack_vector_files/.Rhistory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/attack_vector_files/.Rhistory -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2002.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:168567a09384e84b9cfe0bced000fc8d58efb32fa88d8db5ec118cb33a371661 3 | size 23623496 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2003.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:69ef1ba214aac72008e0b86abf83243018674bbf97379aafb2504b0a9b8e9171 3 | size 6683248 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2004.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6eacc09ad0ab9fbf5841ce3fb1da7cb3f1c057208651c458eed28830671bdd2e 3 | size 14579953 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2005.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aa05a8f3771f041e2ba0e8dc330d8c7fe6f7746af723883af6de8a3fcca0a7a0 3 | size 22014112 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2006.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4cb0cd4be2dd0e85d27b8e3b841bbacf71c51c1ddad3ee66002b00b9987bf542 3 | size 31203222 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2007.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aab6cf98aaaef616389b8a72bc71961469785f4b4f86fe88ce9faf3aa435b9ca 3 | size 29623138 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2008.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4e35c838965f699c4f0ee9deb6a2c1fa86c152f10ce53d5cf9405bcec69241ad 3 | size 38641445 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2009.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4cce5b13c3ab511856ad5d5a89eb893fdc1a03788fef4380390ab99e817de9d6 3 | size 43757080 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2010.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e91f7ff1a2bc88f4dd0b73b5cb917b458cf1b0002e25d61f0e48cd2e770891e9 3 | size 70898760 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2011.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eab4fd314a2b6fb280e89f8449b87f747632a6d867f5a01d5a780395dd61f36b 3 | size 199242753 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2012.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5135ba3a5392f89fa5e7d564bb13e631b87243623a4e9a08603b227c53f6b817 3 | size 67290109 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2013.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e443914f517ba133577df1d8abd2ddfa41801387534da1ceed8ab8aac5613b56 3 | size 67580035 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2014.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:32ec3cd75f103a7bf99726f0125be4b5c985ed48307aa7fa2b1d4d261d119cb4 3 | size 59123335 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2015.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b47b0fb06b1d52554d948778ab93b1eeedf0c82c290994c125da54bf672ccd11 3 | size 47878930 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2016.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5e8924f477fd37e50b429755291c3823d268042e9a27a2bb01fb37e4fe142430 3 | size 58137559 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2017.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cadbaaa0373cb0fa4a1c090f1e3f520dbfc694ec5b35dba2d384dea24e0679f0 3 | size 85293641 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-2018.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:68502a760da128cc6e824362d3b6e668bf417db0a3b9be391522bf42a3ba35c5 3 | size 3671881 4 | -------------------------------------------------------------------------------- /System/attack_vector_files/nvdcve-1.0-modified.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1b3127092aec20e253ab459715c9cc80d38eafae20264066e5c543d85827514e 3 | size 16557752 4 | -------------------------------------------------------------------------------- /System/components/__pycache__/attack_graph_parser.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/__pycache__/attack_graph_parser.cpython-35.pyc -------------------------------------------------------------------------------- /System/components/__pycache__/reader.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/__pycache__/reader.cpython-35.pyc -------------------------------------------------------------------------------- /System/components/__pycache__/topology_parser.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/__pycache__/topology_parser.cpython-35.pyc -------------------------------------------------------------------------------- /System/components/__pycache__/vulnerability_parser.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/__pycache__/vulnerability_parser.cpython-35.pyc -------------------------------------------------------------------------------- /System/components/__pycache__/writer.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/__pycache__/writer.cpython-35.pyc -------------------------------------------------------------------------------- /System/components/attack_graph_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Module responsible for generating the attack graph.""" 3 | 4 | from queue import Queue 5 | import time 6 | import networkx as nx 7 | 8 | from components import reader 9 | from components import topology_parser as top_par 10 | 11 | def clean_vulnerabilities(raw_vulnerabilities, container): 12 | """Cleans the vulnerabilities for a given container.""" 13 | 14 | vulnerabilities = {} 15 | 16 | # Going to the .json hierarchy to get the CVE ids. 17 | layers = raw_vulnerabilities["Layers"] 18 | for layer in layers: 19 | features = layer["Layer"]["Features"] 20 | for feature in features: 21 | if "Vulnerabilities" not in feature: 22 | continue 23 | 24 | vulnerabilities_structure = feature["Vulnerabilities"] 25 | for vulnerability in vulnerabilities_structure: 26 | vulnerability_new = {} 27 | 28 | # Finding the description 29 | if "Description" in vulnerability.keys(): 30 | vulnerability_new["desc"] = vulnerability["Description"] 31 | else: 32 | vulnerability_new["desc"] = "?" 33 | 34 | # Finding the attack vector 35 | vulnerability_new["attack_vec"] = "?" 36 | if "Metadata" in vulnerability.keys(): 37 | metadata = vulnerability["Metadata"] 38 | if "NVD" not in metadata: 39 | continue 40 | 41 | if "CVSSv2" not in metadata["NVD"]: 42 | continue 43 | 44 | if "Vectors" in metadata["NVD"]["CVSSv2"]: 45 | vec = metadata["NVD"]["CVSSv2"]["Vectors"] 46 | vulnerability_new["attack_vec"] = vec 47 | vulnerabilities[vulnerability["Name"]] = vulnerability_new 48 | 49 | print("Total " + str(len(vulnerabilities)) 50 | + " vulnerabilities in container "+container+".") 51 | 52 | return vulnerabilities 53 | 54 | def get_graph(attack_paths): 55 | """Getting the nodes and edges for an array of attack paths.""" 56 | 57 | # Initializing the nodes and edges arrays. 58 | nodes = [] 59 | edges = {} 60 | 61 | # Generating unique nodes. 62 | for attack_path in attack_paths: 63 | for node in attack_path: 64 | if node not in nodes: 65 | nodes.append(node) 66 | 67 | # Generating unique edges. 68 | for attack_path in attack_paths: 69 | 70 | # Checking if an edge is present. 71 | if len(attack_path) >= 2: 72 | for i in range(1, len(attack_path)): 73 | key = attack_path[i]+"|"+attack_path[i-1] 74 | edges[key] = [attack_path[i], attack_path[i-1]] 75 | 76 | return nodes, edges 77 | 78 | def get_attack_vector(attack_vector_files): 79 | """Merging the attack vector files into a dictionary.""" 80 | 81 | # Initializing the attack vector dictionary. 82 | attack_vector_dict = {} 83 | 84 | count = 0 85 | # Iterating through the attack vector files. 86 | for attack_vector_file in attack_vector_files: 87 | 88 | # Load the attack vector. 89 | cve_items = attack_vector_file["CVE_Items"] 90 | 91 | # Filtering only the important information and creating the dictionary. 92 | for cve_item in cve_items: 93 | dictionary_cve = {} 94 | dictionary_cve["attack_vec"] = "?" 95 | dictionary_cve["desc"] = "?" 96 | dictionary_cve["cpe"] = "?" 97 | 98 | # Getting the attack vector and the description. 99 | if "baseMetricV2" in cve_item["impact"]: 100 | 101 | cve_id = cve_item["cve"]["CVE_data_meta"]["ID"] 102 | 103 | cve_attack_vector = cve_item["impact"]["baseMetricV2"]["cvssV2"]["vectorString"] 104 | dictionary_cve["attack_vec"] = cve_attack_vector 105 | 106 | if "description" in cve_item["cve"]: 107 | 108 | descr = cve_item["cve"]["description"]["description_data"][0]['value'] 109 | dictionary_cve["desc"] = descr 110 | 111 | # Get the CPE values: a - application, o - operating system and h - hardware 112 | nodes = cve_item["configurations"]["nodes"] 113 | if len(nodes) > 0: 114 | if "cpe" in nodes[0]: 115 | cpe = cve_item["configurations"]["nodes"][0]["cpe"][0]["cpe22Uri"] 116 | dictionary_cve["cpe"] = cpe 117 | count = count + 1 118 | else: 119 | if "children" in nodes[0] and "cpe" in nodes[0]["children"][0]: 120 | cpe = nodes[0]["children"][0]["cpe"][0]["cpe22Uri"] 121 | dictionary_cve["cpe"] = cpe 122 | count = count + 1 123 | 124 | if dictionary_cve["cpe"] != "?": 125 | dictionary_cve["cpe"] = dictionary_cve["cpe"][5] 126 | attack_vector_dict[cve_id] = dictionary_cve 127 | return attack_vector_dict 128 | 129 | def add_edge(nodes, 130 | edges, 131 | node_start, 132 | node_start_priv, 133 | node_end, 134 | node_end_priv, 135 | edge_desc, 136 | passed_edges): 137 | """Adding an edge to the attack graph and checking if nodes already exist.""" 138 | 139 | 140 | """for key in edges.keys(): 141 | if key.endswith(node_start): 142 | container = node_end.split("(")[0] 143 | if key.startswith(container): 144 | return nodes, edges, passed_edges""" 145 | 146 | # Checks if the opposite edge is already in the collection. If it is, dont add the edge. 147 | node_start_full = node_start + "(" + node_start_priv + ")" 148 | node_end_full = node_end+ "(" + node_end_priv + ")" 149 | 150 | node = passed_edges.get(node_end + "|" + node_start_full) 151 | if node == None: 152 | passed_edges[ node_start + "|" + node_end_full ] = True 153 | else: 154 | return nodes, edges, passed_edges 155 | 156 | if node_start_full not in nodes: 157 | nodes.add(node_start_full) 158 | 159 | if node_end_full not in nodes: 160 | nodes.add(node_end_full) 161 | 162 | key = node_start_full + "|" + node_end_full 163 | 164 | edge = edges.get(key) 165 | if edge == None: 166 | edges[key] = [edge_desc] 167 | else: 168 | edge.append(edge_desc) 169 | edges[key] = edge 170 | 171 | return nodes, edges, passed_edges 172 | 173 | def breadth_first_search(topology, 174 | container_exploitability, 175 | priviledged_access): 176 | """Breadth first search approach for generation of nodes and edges 177 | without generating attack paths.""" 178 | 179 | # This is where the nodes and edges are going to be stored. 180 | edges = {} 181 | nodes = set() 182 | passed_nodes = {} 183 | passed_edges = {} 184 | 185 | # Creating the passed nodes array. 186 | #for container in topology: 187 | # for privilege in ["0", "1", "2", "3", "4"]: 188 | # passed_nodes[container+"|"+privilege] = False 189 | 190 | # Putting the attacker in the queue 191 | queue = Queue() 192 | queue.put("outside|4") 193 | passed_nodes["outside|4"] = True 194 | 195 | # Starting the time 196 | bds_start = time.time() 197 | 198 | while not queue.empty(): 199 | 200 | parts_current = queue.get().split("|") 201 | current_node = parts_current[0] 202 | priv_current = int(parts_current[1]) 203 | 204 | neighbours = topology[current_node] 205 | if current_node != "docker host": 206 | neighbours.append(current_node) 207 | 208 | # Iterate through all of the neighbours 209 | for neighbour in neighbours: 210 | 211 | # Checks if the attacker has access to the docker host. 212 | if current_node == "docker host" and passed_nodes.get(neighbour+"|4") != None: 213 | 214 | # Add the edge 215 | nodes, edges, passed_edges = add_edge(nodes, 216 | edges, 217 | current_node, 218 | "ADMIN", 219 | neighbour, 220 | "ADMIN", 221 | "root access", 222 | passed_edges) 223 | 224 | # Checks if the container has privileged access. 225 | elif neighbour == "docker host" and priviledged_access[current_node]: 226 | 227 | # Add the edge 228 | nodes, edges, passed_edges = add_edge(nodes, 229 | edges, 230 | current_node, 231 | get_priv(priv_current), 232 | neighbour, 233 | "ADMIN", 234 | "privileged", 235 | passed_edges) 236 | 237 | queue.put(neighbour+"|4") 238 | passed_nodes[neighbour+"|4"] = True 239 | 240 | elif neighbour != "outside" and neighbour != "docker host": 241 | 242 | precond = container_exploitability[neighbour]["precond"] 243 | postcond = container_exploitability[neighbour]["postcond"] 244 | 245 | for vul in precond.keys(): 246 | 247 | if priv_current >= precond[vul] and \ 248 | ((neighbour != current_node and postcond[vul] != 0) or \ 249 | (neighbour == current_node and priv_current < postcond[vul])): 250 | 251 | # Add the edge 252 | nodes, edges, passed_edges = add_edge(nodes, 253 | edges, 254 | current_node, 255 | get_priv(priv_current), 256 | neighbour, 257 | get_priv(postcond[vul]), 258 | vul, 259 | passed_edges) 260 | 261 | # If the neighbour was not passed or it has a lower privilege... 262 | passed_nodes_key = neighbour + "|" + str(postcond[vul]) 263 | if passed_nodes.get(passed_nodes_key) == None: 264 | # ... put it in the queue 265 | queue.put(passed_nodes_key) 266 | passed_nodes[passed_nodes_key] = True 267 | 268 | duration_bdf = time.time()-bds_start 269 | print("Breadth-first-search took "+str(duration_bdf)+" seconds.") 270 | return nodes, edges, duration_bdf 271 | 272 | 273 | def attack_vector_string_to_dict(av_string): 274 | """Transforms the attack vector string to dictionary.""" 275 | 276 | av_dict = {} 277 | 278 | # Remove brackets. 279 | if av_string[0] == "(": 280 | av_string = av_string[1:len(av_string)-1] 281 | 282 | # Put structure into dictionary 283 | categories = av_string.split("/") 284 | for category in categories: 285 | parts = category.split(":") 286 | av_dict[parts[0]] = parts[1] 287 | 288 | return av_dict 289 | 290 | def merge_attack_vector_vuls(attack_vector_dict, vulnerabilities): 291 | """Merging the information from vulnerabilities and the attack vector files.""" 292 | 293 | merged_vulnerabilities = {} 294 | 295 | for vulnerability in vulnerabilities: 296 | vulnerability_new = {} 297 | if vulnerability in attack_vector_dict: 298 | 299 | vulnerability_new["desc"] = attack_vector_dict[vulnerability]["desc"] 300 | 301 | if attack_vector_dict[vulnerability]["attack_vec"] != "?": 302 | av_string = attack_vector_dict[vulnerability]["attack_vec"] 303 | attack_vec = attack_vector_string_to_dict(av_string) 304 | vulnerability_new["attack_vec"] = attack_vec 305 | vulnerability_new["cpe"] = attack_vector_dict[vulnerability]["cpe"] 306 | 307 | else: 308 | 309 | vulnerability_new["desc"] = vulnerabilities[vulnerability]["desc"] 310 | if vulnerabilities[vulnerability]["attack_vec"] != "?": 311 | 312 | av_string = vulnerabilities[vulnerability]["attack_vec"] 313 | attack_vec = attack_vector_string_to_dict(av_string) 314 | vulnerability_new["attack_vec"] = attack_vec 315 | 316 | vulnerability_new["cpe"] = "?" 317 | 318 | merged_vulnerabilities[vulnerability] = vulnerability_new 319 | 320 | return merged_vulnerabilities 321 | 322 | def get_val(privilege): 323 | """Mapping the privilege level to its value, so that it can be compared later.""" 324 | 325 | mapping = {"NONE": 0, 326 | "VOS USER" : 1, 327 | "VOS ADMIN" : 2, 328 | "USER": 3, 329 | "ADMIN": 4} 330 | 331 | return mapping[privilege] 332 | 333 | def get_priv(privilege): 334 | """Mapping the value to the privilege level for easier readability in the attack graph.""" 335 | 336 | mapping = {0: "NONE", 337 | 1 : "VOS USER", 338 | 2 : "VOS ADMIN", 339 | 3: "USER", 340 | 4: "ADMIN"} 341 | 342 | return mapping[privilege] 343 | 344 | def get_rule_precondition(rule, vul, precond, vul_key): 345 | """Checks if it finds rule precondition""" 346 | 347 | # Checks if the cpe in the rule is same with vulnerability. 348 | if rule["cpe"] != "?": 349 | if rule["cpe"] == "o" and vul["cpe"] != "o": 350 | return precond 351 | elif rule["cpe"] == "h" and (vul["cpe"] != "h" and vul["cpe"] != "a"): 352 | return precond 353 | 354 | # Checks if the vocabulary is matching 355 | if "vocabulary" in rule.keys(): 356 | sentences = rule["vocabulary"] 357 | hit_vocab = False 358 | for sentence in sentences: 359 | if "..." in sentence: 360 | parts = sentence.split("...") 361 | if parts[0] in vul["desc"] and parts[1] in vul["desc"]: 362 | hit_vocab = True 363 | break 364 | elif "?" == sentence: 365 | hit_vocab = True 366 | break 367 | elif sentence in vul["desc"]: 368 | hit_vocab = True 369 | break 370 | if hit_vocab and \ 371 | (vul_key not in precond or precond[vul_key] < get_val(rule["precondition"])): 372 | precond[vul_key] = get_val(rule["precondition"]) 373 | 374 | # Check access vector 375 | else: 376 | if rule["accessVector"] != "?": 377 | 378 | if rule["accessVector"] == "LOCAL" and vul["attack_vec"]["AV"] != "L": 379 | return precond 380 | elif vul["attack_vec"]["AV"] != "A" and vul["attack_vec"]["AV"] != "N": 381 | return precond 382 | 383 | if rule["authentication"] != "?": 384 | if rule["authentication"] == "NONE" and vul["attack_vec"]["Au"] != "N": 385 | return precond 386 | elif vul["attack_vec"]["Au"] != "L" and vul["attack_vec"]["Au"] != "H": 387 | return precond 388 | 389 | if rule["accessComplexity"][0] == vul["attack_vec"]["AC"] and \ 390 | (vul_key not in precond or precond[vul_key] < get_val(rule["precondition"])): 391 | precond[vul_key] = get_val(rule["precondition"]) 392 | 393 | return precond 394 | 395 | def get_rule_postcondition(rule, vul, postcond, vul_key): 396 | """Checks if it finds rule postcondition""" 397 | 398 | # Checks if the cpe in the rule is same with vulnerability. 399 | if rule["cpe"] != "?": 400 | if rule["cpe"] == "o" and vul["cpe"] != "o": 401 | return postcond 402 | elif rule["cpe"] == "h" and (vul["cpe"] != "h" and vul["cpe"] != "a"): 403 | return postcond 404 | 405 | # Checks if the vocabulary is matching 406 | sentences = rule["vocabulary"] 407 | hit_vocab = False 408 | for sentence in sentences: 409 | if "..." in sentence: 410 | parts = sentence.split("...") 411 | if parts[0] in vul["desc"] and parts[1] in vul["desc"]: 412 | hit_vocab = True 413 | break 414 | elif "?" == sentence: 415 | hit_vocab = True 416 | break 417 | elif sentence in vul["desc"]: 418 | hit_vocab = True 419 | break 420 | if not hit_vocab: 421 | return postcond 422 | 423 | # Check Impacts 424 | if rule["impacts"] == "ALL_COMPLETE": 425 | if vul["attack_vec"]["I"] == "C" and vul["attack_vec"]["C"] == "C": 426 | if vul_key not in postcond or postcond[vul_key] > get_val(rule["postcondition"]): 427 | postcond[vul_key] = get_val(rule["postcondition"]) 428 | 429 | elif rule["impacts"] == "PARTIAL": 430 | 431 | if vul["attack_vec"]["I"] == "P" or vul["attack_vec"]["C"] == "P": 432 | if vul_key not in postcond or postcond[vul_key] > get_val(rule["postcondition"]): 433 | postcond[vul_key] = get_val(rule["postcondition"]) 434 | 435 | else: 436 | if vul_key not in postcond or postcond[vul_key] > get_val(rule["postcondition"]): 437 | postcond[vul_key] = get_val(rule["postcondition"]) 438 | 439 | elif rule["impacts"] == "ANY_NONE": 440 | if vul["attack_vec"]["I"] == "N" or vul["attack_vec"]["C"] == "N": 441 | if vul_key not in postcond or postcond[vul_key] > get_val(rule["postcondition"]): 442 | postcond[vul_key] = get_val(rule["postcondition"]) 443 | 444 | return postcond 445 | 446 | def rule_processing(merged_vul, pre_rules, post_rules): 447 | """ This functions is responspible for creating the 448 | precondition and postcondition rules.""" 449 | 450 | precond = {} 451 | postcond = {} 452 | for vul_key in merged_vul: 453 | vul = merged_vul[vul_key] 454 | 455 | if "attack_vec" not in vul or vul["attack_vec"] == "?": 456 | continue 457 | for pre_rule in pre_rules: 458 | rule = pre_rules[pre_rule] 459 | precond = get_rule_precondition(rule, vul, precond, vul_key) 460 | 461 | for post_rule in post_rules: 462 | rule = post_rules[post_rule] 463 | postcond = get_rule_postcondition(rule, vul, postcond, vul_key) 464 | 465 | # Assign default values if rules are undefined 466 | if vul_key not in precond: 467 | precond[vul_key] = 0 # 0 is None level 468 | if vul_key not in postcond: 469 | postcond[vul_key] = 4 # 4 is Admin level 470 | 471 | return precond, postcond 472 | 473 | def get_exploitable_vuls_container(vulnerabilities, 474 | container_name, 475 | attack_vector_dict, 476 | pre_rules, 477 | post_rules): 478 | """Processes and provides exploitable vulnerabilities per container.""" 479 | 480 | # Remove junk and just takethe most important part from each vulnerability 481 | cleaned_vulnerabilities = clean_vulnerabilities(vulnerabilities, container_name) 482 | 483 | # Merging the cleaned vulnerabilities 484 | merged_vul = merge_attack_vector_vuls(attack_vector_dict, cleaned_vulnerabilities) 485 | 486 | # Get the preconditions and postconditions for each vulnerability. 487 | precond, postcond = rule_processing(merged_vul, pre_rules, post_rules) 488 | exploitability_dict = {"precond": precond, "postcond":postcond} 489 | 490 | return exploitability_dict 491 | 492 | def generate_attack_graph(attack_vector_path, 493 | pre_rules, 494 | post_rules, 495 | topology, 496 | vulnerabilities, 497 | example_folder): 498 | """Main pipeline for the attack graph generation algorithm.""" 499 | 500 | print("Start with attack graph generation...") 501 | 502 | # Read the attack vector files. 503 | attack_vector_files = reader.read_attack_vector_files(attack_vector_path) 504 | 505 | print("Vulnerabilities preprocessing started.") 506 | time_start = time.time() 507 | 508 | # Read the service to image mapping. 509 | mapping_names = top_par.get_mapping_service_to_image_names(example_folder) 510 | 511 | # Read priviledged containers from docker-compose.yml 512 | privileged_access = reader.check_priviledged_access(mapping_names, example_folder) 513 | 514 | # Merging the attack vector files and creating an attack vector dictionary. 515 | attack_vector_dict = get_attack_vector(attack_vector_files) 516 | 517 | # Getting the potentially exploitable vulnerabilities for each container. 518 | exploitable_vuls = {} 519 | for container in topology.keys(): 520 | if container != "outside" and container != "docker host": 521 | 522 | # Reading the vulnerability 523 | exploitable_vuls[container] = get_exploitable_vuls_container(vulnerabilities[container], 524 | container, 525 | attack_vector_dict, 526 | pre_rules, 527 | post_rules) 528 | 529 | duration_vuls_preprocessing = time.time() - time_start 530 | print("Vulnerabilities preprocessing finished. Time elapsed: " + \ 531 | str(duration_vuls_preprocessing) + \ 532 | " seconds.\n") 533 | 534 | # Breadth first search algorithm for generation of attack paths. 535 | print("Breadth-first search started.") 536 | nodes, edges, duration_bdf = breadth_first_search(topology, 537 | exploitable_vuls, 538 | privileged_access) 539 | 540 | print("Breadth-first search finished. Time elapsed: "+str(duration_bdf)+" seconds.\n") 541 | 542 | # Returns a graph with nodes and edges. 543 | return nodes, edges, duration_bdf, duration_vuls_preprocessing 544 | 545 | def print_graph_properties(label_edges, nodes, edges): 546 | """This functions prints graph properties.""" 547 | 548 | print("\n**********Attack Graph properties**********") 549 | 550 | time_start = time.time() 551 | 552 | # Create the graph 553 | graph = nx.DiGraph() 554 | 555 | for node in nodes: 556 | graph.add_node(node) 557 | for edge_name in edges.keys(): 558 | terminal_points = edge_name.split("|") 559 | 560 | edge_vuls = edges[edge_name] 561 | 562 | if label_edges == "single": 563 | for edge_vul in edge_vuls: 564 | graph.add_edge(terminal_points[0], 565 | terminal_points[1], 566 | contstraint='false') 567 | 568 | elif label_edges == "multiple": 569 | graph.add_edge(terminal_points[0], 570 | terminal_points[1], 571 | contstraint='false') 572 | 573 | # Calculate the attack graph properties 574 | 575 | # Number of nodes 576 | no_nodes = graph.number_of_nodes() 577 | print("The number of nodes in the graph is "+str(no_nodes)+"\n") 578 | 579 | # Number of edges 580 | no_edges = graph.number_of_edges() 581 | print("The number of edges in the graph is "+str(no_edges)+"\n") 582 | 583 | # Degree centrality 584 | degree_centrality = nx.degree_centrality(graph) 585 | print("The degree centrality of the graph is: ") 586 | for item in degree_centrality.keys(): 587 | print(str(item)+" "+str(degree_centrality[item])) 588 | 589 | # Average degree centrality 590 | avg_degree_centrality = 0 591 | for node in degree_centrality: 592 | avg_degree_centrality = avg_degree_centrality + degree_centrality[node] 593 | if no_nodes != 0: 594 | avg_degree_centrality = avg_degree_centrality / no_nodes 595 | print("The average degree centrality of the graph is: "+str(avg_degree_centrality)+"\n") 596 | 597 | # In-degree and average in-degree 598 | in_degree = graph.in_degree() 599 | print("The in-degree is:") 600 | for item in in_degree: 601 | print(item) 602 | 603 | avg_in_degree = 0 604 | for node in in_degree: 605 | avg_in_degree = avg_in_degree + node[1] 606 | if no_nodes != 0: 607 | avg_in_degree = avg_in_degree / no_nodes 608 | print("The average in-degree is "+str(avg_in_degree)) 609 | print("\n") 610 | 611 | out_degree = graph.out_degree() 612 | print("The out-degree is:") 613 | for item in out_degree: 614 | print(item) 615 | 616 | avg_out_degree = 0 617 | for node in out_degree: 618 | avg_out_degree = avg_out_degree + node[1] 619 | if no_nodes != 0: 620 | avg_out_degree = avg_out_degree / no_nodes 621 | print("The average out-degree is "+str(avg_out_degree)) 622 | print("\n") 623 | 624 | if no_nodes != 0: 625 | print("Is the graph strongly connected? "+str(nx.is_strongly_connected(graph))+"\n") 626 | 627 | duration_graph_properties = time.time() - time_start 628 | print("Time elapsed: "+str(duration_graph_properties)+" seconds.\n") 629 | 630 | return duration_graph_properties 631 | -------------------------------------------------------------------------------- /System/components/reader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Module responsible for all the input reading and validation.""" 3 | 4 | import sys 5 | import os 6 | import json 7 | import yaml 8 | 9 | def validate_command_line_input(arguments): 10 | """This function validates the command line user input.""" 11 | print("Command-line input validation...\n") 12 | 13 | is_valid = True 14 | 15 | # Check if the user has entered right number of arguments. 16 | if len(arguments) != 2: 17 | print("Incorrect number of arguments.") 18 | is_valid = False 19 | 20 | # Check if the specified folder exists. 21 | if is_valid: 22 | if not os.path.exists(arguments[1]): 23 | print("The entered example folder name does not exist.") 24 | is_valid = False 25 | 26 | # Check if there is a docker-compose.yml file in the specified folder. 27 | if is_valid: 28 | content = os.listdir(arguments[1]) 29 | if "docker-compose.yml" not in content: 30 | print("docker-compose.yml is missing in the folder "+arguments[1]) 31 | is_valid = False 32 | 33 | return is_valid 34 | 35 | def validate_config_file(): 36 | """This function validates the config file content.""" 37 | 38 | print("Config file content validation...\n") 39 | 40 | is_valid = True 41 | config_file = read_config_file() 42 | 43 | # Check if the main keywords are present in the config file. 44 | main_keywords = ["attack-vector-folder-path", 45 | "examples-results-path", 46 | "mode", 47 | "labels_edges", 48 | "generate_graphs", 49 | "show_one_vul_per_edge"] 50 | 51 | for main_keyword in main_keywords: 52 | if main_keyword not in config_file.keys(): 53 | print("'"+main_keyword+"' keyword is missing in the config file.") 54 | is_valid = False 55 | 56 | # Check if the mode keyword has the right values 57 | if is_valid: 58 | config_mode = config_file["mode"] 59 | if config_mode != "offline" and config_mode != "online": 60 | is_valid = False 61 | print("Value: "+ \ 62 | config_mode + \ 63 | " is invalid for keyword mode") 64 | sys.exit(0) 65 | 66 | # Checks if clairctl has been installed. 67 | elif config_mode == "online": 68 | print("Checking if clairctl has been installed") 69 | 70 | home = os.path.expanduser("~") 71 | os.path.exists(os.path.join(home, 72 | "golang" 73 | "go", 74 | "bin", 75 | "src", 76 | "github.com", 77 | "jgsqware", 78 | "clairctl")) 79 | 80 | # Check if the generate_graphs keyword has the right values 81 | if is_valid: 82 | config_mode = config_file["generate_graphs"] 83 | if config_mode != True and config_mode != False: 84 | is_valid = False 85 | print("Value: " + \ 86 | config_mode + \ 87 | " is invalid for keyword generate_graphs") 88 | sys.exit(0) 89 | 90 | # Check if the show_one_vul_per_edge keyword has the right values 91 | if is_valid: 92 | config_mode = config_file["show_one_vul_per_edge"] 93 | if config_mode != True and config_mode != False: 94 | is_valid = False 95 | print("Value: " + \ 96 | config_mode + \ 97 | " is invalid for keyword generate_graphs") 98 | sys.exit(0) 99 | 100 | # Check if the labels_edges keyword has the right values 101 | if is_valid: 102 | config_mode = config_file["labels_edges"] 103 | if config_mode != "single" and config_mode != "multiple": 104 | is_valid = False 105 | print("Value: " + \ 106 | config_mode + \ 107 | " is invalid for keyword labels_edges") 108 | sys.exit(0) 109 | 110 | return is_valid 111 | 112 | def check_priviledged_access(mapping_names, example_folder_path): 113 | """Checks if a container has the privileged flag.""" 114 | docker_compose = read_docker_compose_file(example_folder_path) 115 | services = docker_compose["services"] 116 | priviledged_access = {} 117 | for service in services: 118 | if "privileged" in services[service] and services[service]["privileged"]: 119 | priviledged_access[mapping_names[service]] = True 120 | elif "volumes" in services[service]: 121 | volumes = services[service]["volumes"] 122 | # Check if docker socket is mounted 123 | socket_mounted = False 124 | for volume in volumes: 125 | if "/var/run/docker.sock:/var/run/docker.sock" in volume: 126 | socket_mounted = True 127 | if socket_mounted: 128 | priviledged_access[mapping_names[service]] = True 129 | else: 130 | priviledged_access[mapping_names[service]] = False 131 | else: 132 | priviledged_access[mapping_names[service]] = False 133 | 134 | return priviledged_access 135 | 136 | def read_attack_vector_files(attack_vector_folder_path): 137 | """It reads the attack vector files.""" 138 | 139 | attack_vector_list = [] 140 | 141 | attack_vector_filenames = os.listdir(attack_vector_folder_path) 142 | 143 | # Iterating through the attack vector files. 144 | for attack_vector_filename in attack_vector_filenames: 145 | 146 | # Load the attack vector. 147 | if not attack_vector_filename.startswith("nvdcve"): 148 | continue 149 | with open(os.path.join(attack_vector_folder_path, attack_vector_filename)) as att_vec: 150 | attack_vector_list.append(json.load(att_vec)) 151 | 152 | return attack_vector_list 153 | 154 | def read_topology(example_folder_path): 155 | """Reads the topology .json file.""" 156 | 157 | config = read_config_file() 158 | folder_name = os.path.basename(example_folder_path) 159 | topology_path = os.path.join(config["examples-results-path"], 160 | folder_name, 161 | "topology.json") 162 | 163 | with open(topology_path) as topology_file: 164 | topology = json.load(topology_file) 165 | 166 | return topology 167 | 168 | def read_vulnerabilities(vulnerabilities_folder_path, containers): 169 | """This function reads the .json file for the vulnerabilities of a container.""" 170 | 171 | vulnerabilities = {} 172 | 173 | for container in containers: 174 | 175 | vulnerabilities_path = os.path.join(vulnerabilities_folder_path, 176 | container+"-vulnerabilities.json") 177 | if os.path.exists(vulnerabilities_path): 178 | with open(vulnerabilities_path) as vul_file: 179 | vulnerabilities_container = json.load(vul_file) 180 | vulnerabilities[container] = vulnerabilities_container 181 | 182 | return vulnerabilities 183 | 184 | def read_docker_compose_file(example_folder_path): 185 | """This function is responsible for reading the docker-compose file of the container.""" 186 | 187 | with open(os.path.join(example_folder_path, "docker-compose.yml"), "r") as compose_file: 188 | docker_compose_file = yaml.load(compose_file) 189 | 190 | return docker_compose_file 191 | 192 | def read_config_file(old_root_path=""): 193 | """This function is responsible for reading the config file.""" 194 | 195 | with open(os.path.join(old_root_path, "config.yml"), "r") as stream: 196 | try: 197 | config_file = yaml.load(stream) 198 | except yaml.YAMLError as exc: 199 | print(exc) 200 | 201 | return config_file 202 | 203 | def read_clairctl_config_file(clairctl_home): 204 | """This function is responsible for reading the clairctl config file.""" 205 | 206 | with open(os.path.join(clairctl_home, "clairctl.yml"), "r") as clair_config: 207 | clair_config = yaml.load(clair_config) 208 | return clair_config 209 | -------------------------------------------------------------------------------- /System/components/topology_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Module responsible for manipulation of the topology of the docker system.""" 3 | 4 | import os 5 | import time 6 | 7 | from graphviz import Graph 8 | from components import reader 9 | from components import writer 10 | 11 | def get_services(example_folder_path): 12 | """It returns a dictionary of all of the services defined in docker-compose.yml""" 13 | 14 | docker_compose_file = reader.read_docker_compose_file(example_folder_path) 15 | 16 | services = {} 17 | if "services" in docker_compose_file: 18 | services = docker_compose_file["services"] 19 | 20 | return services 21 | 22 | def validation_docker_compose(example_folder_path): 23 | """Checks if the built keyword is present for every service.""" 24 | 25 | services = get_services(example_folder_path) 26 | 27 | # Checks if the services are present. 28 | if not services: 29 | print("The services in the docker-compose are not specified. Please specify them.") 30 | return False 31 | 32 | # Checks if the services have the "build" keyword for local building. 33 | for service in services: 34 | contents_service = services[service] 35 | if 'build' not in contents_service.keys(): 36 | print("Now it is not allowed to take images from distant repository.") 37 | print("They should be manually built. Please specify the keyword 'build' " 38 | " for the service " + \ 39 | service + \ 40 | " to the location of the image in the docker-compose.yml file.") 41 | return False 42 | 43 | return True 44 | 45 | def get_mapping_service_to_image_names(example_folder_path): 46 | """This function mapps the service name to the real image name. 47 | 48 | In docker images get assigned different names based on how the 49 | docker-compose.yml file is constructed. 50 | This function helps us with that issue.""" 51 | 52 | mapping = {} 53 | services = get_services(example_folder_path) 54 | for service in services: 55 | content_service = services[service] 56 | 57 | # Checks if the 'image' keyword is present and names the service after it. 58 | if 'image' in content_service.keys(): 59 | mapping[service] = content_service['image'] 60 | 61 | # If not, it appends the folder name as a prefix to the service name. 62 | else: 63 | # Specific to docker: '-' and '_' are removed. 64 | parent_name = os.path.basename(example_folder_path).replace("-", "").replace("_", "") 65 | mapping[service] = os.path.basename(parent_name)+"_"+service 66 | 67 | return mapping 68 | 69 | def create_topology_graph(list_services, 70 | example_folder_path, 71 | example_results_path=""): 72 | """This function creates a topology graph.""" 73 | 74 | nodes = [] 75 | edges = {} 76 | for service in list_services.keys(): 77 | nodes.append(service) 78 | for neighbour in list_services[service]: 79 | if neighbour+"|"+service not in edges.keys(): 80 | edges[service+"|"+neighbour] = [service, neighbour] 81 | 82 | dot = Graph(comment="Topology Graph") 83 | for node in nodes: 84 | dot.node(node) 85 | for edge in edges: 86 | dot.edge(edges[edge][0], edges[edge][1], contstraint='false') 87 | 88 | writer.write_topology_graph(dot, 89 | example_folder_path, 90 | example_results_path) 91 | 92 | def parse_topology(example_folder_path, 93 | example_results_path=""): 94 | """ Function for parsing the topology of the docker system. 95 | 96 | Assumptions: 97 | 1) We assume that the docker-compose file contains networks 98 | and the dockers are connected through these networks 99 | 2) We assume that port mapping is done exclusively through docker-compose.yml""" 100 | 101 | print("Executing the topology parser...") 102 | 103 | time_start = time.time() 104 | 105 | # Checks if the services are specified. 106 | services = get_services(example_folder_path) 107 | 108 | # Get name mapping from service names to image names. 109 | mapping_names = get_mapping_service_to_image_names(example_folder_path) 110 | list_services = {} 111 | 112 | # Checks if the services are connected to the outside. 113 | list_services["outside"] = [] 114 | list_services["docker host"] = [] 115 | 116 | # Iteration through the first service. 117 | for first_service_name in services: 118 | 119 | # Check if network keyword exists in the first service. 120 | if "networks" in services[first_service_name].keys(): 121 | first_service_networks = services[first_service_name]["networks"] 122 | else: 123 | 124 | # If it does not, it means that it is exposed to every other service. 125 | first_service_networks = "exposed" 126 | list_services[mapping_names[first_service_name]] = [] 127 | 128 | # Iteration through the second service. 129 | for second_service_name in services: 130 | if first_service_name != second_service_name: 131 | 132 | # Check if network keyword exists in the second service. 133 | if "networks" in services[second_service_name].keys(): 134 | second_service_networks = services[second_service_name]["networks"] 135 | else: 136 | 137 | # If it does not, it means that it is exposed to every other service. 138 | second_service_networks = "exposed" 139 | 140 | # Checks if the first and second service belong to the same network. 141 | for first_service_network in first_service_networks: 142 | if first_service_network in second_service_networks: 143 | 144 | # If they do, then they are added. 145 | list_services[mapping_names[first_service_name]]\ 146 | .append(mapping_names[second_service_name]) 147 | 148 | # Check if the ports are mapped to the host machine 149 | # i.e. the docker is exposed to outside 150 | if "ports" in services[first_service_name].keys(): 151 | list_services["outside"].append(mapping_names[first_service_name]) 152 | list_services[mapping_names[first_service_name]].append("outside") 153 | 154 | # Adding the docker host as a node in the graph connected to all of the services 155 | list_services[mapping_names[first_service_name]].append("docker host") 156 | list_services["docker host"].append(mapping_names[first_service_name]) 157 | 158 | # Writing the dictonary into a json file. 159 | writer.write_topology_file(list_services, 160 | example_folder_path, 161 | example_results_path) 162 | 163 | print("Topology parser executed.") 164 | 165 | duration_topology = time.time() - time_start 166 | print("Time elapsed: "+str(duration_topology)+" seconds.\n") 167 | 168 | return list_services, duration_topology 169 | -------------------------------------------------------------------------------- /System/components/topology_parser.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/topology_parser.pyc -------------------------------------------------------------------------------- /System/components/vulnerability_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Module responsible for generating vulnerabilites from docker containers.""" 3 | 4 | import os 5 | import subprocess 6 | 7 | from components import topology_parser as top_par 8 | from components import writer 9 | 10 | def parse_vulnerabilities(folder): 11 | """Function that gets the vulnerabilities for each docker container.""" 12 | 13 | print("Executing the vulnerability parser...") 14 | 15 | list_services = top_par.get_services(folder) 16 | mapping_image_names = top_par.get_mapping_service_to_image_names(folder) 17 | 18 | old_root_path = os.getcwd() 19 | 20 | if not os.path.exists(os.path.join(old_root_path, "examples-results")): 21 | os.makedirs(os.path.join(old_root_path, "examples-results"), mode=0o777) 22 | 23 | 24 | if not os.path.exists(os.path.join(old_root_path, "examples-results", folder)): 25 | os.makedirs(os.path.join(old_root_path, "examples-results", folder), mode=0o777) 26 | 27 | os.chdir(os.path.join(os.getcwd(), folder)) 28 | 29 | # Build the images that are specified in docker-compose.yml 30 | subprocess.call(["docker-compose", 31 | "build"]) 32 | 33 | # Start clair, clairctl and postgres 34 | clairctl_home = os.path.join("/usr", 35 | "local", 36 | "go", 37 | "bin", 38 | "src", 39 | "github.com", 40 | "jgsqware", 41 | "clairctl") 42 | 43 | os.chdir(clairctl_home) 44 | 45 | subprocess.call(["docker-compose", 46 | "up", 47 | "-d"]) 48 | 49 | # Doing the analyzis and make reports files. 50 | for service in list_services: 51 | 52 | image = mapping_image_names[service] 53 | 54 | print("Pushing the image "+image) 55 | subprocess.call(["docker-compose", 56 | "exec", 57 | "--user", 58 | "root", 59 | "clairctl", 60 | "clairctl", 61 | "push", 62 | "--local", 63 | image], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 64 | 65 | print("Analyzing the image "+image) 66 | subprocess.call(["docker-compose", 67 | "exec", 68 | "--user", 69 | "root", 70 | "clairctl", 71 | "clairctl", 72 | "analyze", 73 | "--local", 74 | image]) 75 | 76 | print("Making report for the image "+image) 77 | subprocess.call(["docker-compose", 78 | "exec", 79 | "--user", 80 | "root", 81 | "clairctl", 82 | "clairctl", 83 | "report", 84 | "--local", 85 | "--format", 86 | "json", 87 | image], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 88 | 89 | writer.copy_vulnerability_file(clairctl_home, image, old_root_path, folder) 90 | 91 | os.chdir(old_root_path) 92 | 93 | print("Vulnerability parser executed.") 94 | -------------------------------------------------------------------------------- /System/components/vurnability_parser.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/components/vurnability_parser.pyc -------------------------------------------------------------------------------- /System/components/writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """This module is responsible for writing the outputs into files.""" 3 | 4 | import os 5 | import json 6 | import yaml 7 | 8 | from components import reader 9 | 10 | def write_topology_file(list_services, 11 | example_folder_path="", 12 | example_result_path=""): 13 | """Writes list of services into a file.""" 14 | 15 | folder_name = os.path.basename(example_folder_path) 16 | if example_result_path == "": 17 | config = reader.read_config_file() 18 | example_result_path = config["examples-results-path"] 19 | topology_writing_path = os.path.join(example_result_path, 20 | folder_name, 21 | "topology.json") 22 | 23 | with open(topology_writing_path, "w") as topology: 24 | json.dump(list_services, topology) 25 | 26 | def write_attack_graph(example_folder_path, graph): 27 | """Writes the attack graph onto a dot file.""" 28 | 29 | config = reader.read_config_file() 30 | folder_name = os.path.basename(example_folder_path) 31 | attack_graph_path = os.path.join(config["examples-results-path"], 32 | folder_name, 33 | "attack_graph.dot") 34 | graph.render(attack_graph_path) 35 | 36 | def write_topology_graph(graph, 37 | example_folder_path, 38 | example_result_path=""): 39 | """Writes the topology graph onto a dot file.""" 40 | 41 | folder_name = os.path.basename(example_folder_path) 42 | if example_result_path == "": 43 | config = reader.read_config_file() 44 | example_result_path = config["examples-results-path"] 45 | topology_graph_path = os.path.join(example_result_path, 46 | folder_name, 47 | "topology_graph.dot") 48 | graph.render(topology_graph_path) 49 | 50 | def write_clarictl_config_file(clairctl_home, clairctl_config_dict): 51 | """Writes the modified clairctl config file.""" 52 | 53 | with open(os.path.join(clairctl_home, "clairctl.yml"), "w") as outfile: 54 | yaml.dump(clairctl_config_dict, outfile) 55 | 56 | def copy_vulnerability_file(clairctl_home, image_name, old_root_path, parent_folder): 57 | """Copies the vulnerability file from clairctl to the local location.""" 58 | 59 | config = reader.read_config_file(old_root_path) 60 | parent_folder = os.path.basename(parent_folder) 61 | 62 | os.rename(os.path.join(clairctl_home, 63 | "docker-compose-data", 64 | "clairctl-reports", 65 | "json", 66 | "analysis-"+image_name+"-latest.json"), 67 | os.path.join(old_root_path, 68 | config["examples-results-path"], 69 | parent_folder, 70 | image_name+"-vulnerabilities.json")) 71 | 72 | def create_folder(example_folder_path): 73 | """Creates folder for storing the intermediate results of the examples.""" 74 | 75 | config = reader.read_config_file() 76 | directory_path = os.path.join(config["examples-results-path"], example_folder_path) 77 | if not os.path.exists(directory_path): 78 | os.makedirs(directory_path, mode=0o777) 79 | 80 | def print_summary(config_mode, 81 | config_generate_graphs, 82 | no_topology_nodes=0, 83 | no_topology_edges=0, 84 | no_attack_graph_nodes=0, 85 | no_attack_graph_edges=0, 86 | duration_topology=0, 87 | duration_vulnerabilities=0, 88 | duration_vuls_preprocessing=0, 89 | duration_bdf=0, 90 | duration_graph_properties=0, 91 | duration_visualization=0, 92 | duration_total_time=0): 93 | """Function responsible for printing the time and properties summary.""" 94 | 95 | if no_topology_nodes != 0 and \ 96 | no_topology_edges != 0 and \ 97 | no_attack_graph_nodes != 0 and \ 98 | no_attack_graph_edges != 0: 99 | print("\n**********Nodes and edges summary of the topology and attack graphs**********") 100 | 101 | if no_topology_nodes != 0: 102 | print("The number of nodes in the topology graph is "+str(no_topology_nodes)+".") 103 | 104 | if no_topology_edges != 0: 105 | print("The number of edges in the topology graph is "+str(no_topology_edges)+".") 106 | 107 | if no_attack_graph_nodes != 0: 108 | print("The number of nodes in the attack graph is "+str(no_attack_graph_nodes)+".") 109 | 110 | if no_attack_graph_edges != 0: 111 | print("The number of edges in the attack graph is "+str(no_attack_graph_edges)+".") 112 | 113 | print("\n**********Time Summary of the Attack Graph Generation Process**********") 114 | 115 | print("Topology parsing took "+str(duration_topology)+" seconds.") 116 | 117 | if config_mode == "online": 118 | print("Vulnerability parsing took "+str(duration_vulnerabilities)+" seconds.") 119 | 120 | print("The attack graph generation took " + \ 121 | str(duration_vuls_preprocessing+duration_bdf)+" seconds.") 122 | 123 | print(" -Preprocessing of the vulnerabilities took " + \ 124 | str(duration_vuls_preprocessing)+" seconds.") 125 | 126 | print(" -Breadth First Search took "+str(duration_bdf)+" seconds.") 127 | 128 | if duration_graph_properties != 0: 129 | print("Calculation of Graph Properties took "+str(duration_graph_properties)+" seconds.") 130 | 131 | if config_generate_graphs: 132 | print("Attack Graph Visualization took "+str(duration_visualization)+" seconds.") 133 | 134 | if duration_total_time != 0: 135 | print("The total elapsed time is "+str(duration_total_time)+" seconds.") 136 | print("\n\n") 137 | -------------------------------------------------------------------------------- /System/config.yml: -------------------------------------------------------------------------------- 1 | # The location of the folder with the NVD attack rule files. 2 | attack-vector-folder-path: attack_vector_files 3 | 4 | # The locations from where the example-folders are read and where their results are beeing stored. 5 | examples-results-path: examples-results 6 | 7 | # online calculates vulnerabilites with clairctl 8 | # offline skips clairctl and assumes that the vulnerabilities are already calculated. 9 | mode: online # Options {"online", "offline"} 10 | 11 | # This property states if topology and attack graphs are going to be produced. 12 | generate_graphs: True # Options {True, False} 13 | 14 | # This property states if single or multiple vulnerabilties constitute 15 | # an edge between two same nodes 16 | labels_edges: multiple # Options {"single", "multiple"} 17 | 18 | # This property only shows one vulnerability per edge in the attack graph 19 | # We use this in order to have more readable attack graphs. 20 | show_one_vul_per_edge: True # Options {True, False} 21 | 22 | # The rules required to produce pre- and postconditions. They follow a specific pattern. 23 | preconditions-rules: 24 | rule1: 25 | accessVector: '?' 26 | authentication: '?' 27 | accessComplexity: '?' 28 | cpe: '?' 29 | precondition: 'NONE' 30 | rule2: 31 | accessVector: 'LOCAL' 32 | authentication: '?' 33 | accessComplexity: 'LOW' 34 | cpe: 'o' 35 | precondition: 'USER' 36 | rule3: 37 | accessVector: 'LOCAL' 38 | authentication: '?' 39 | accessComplexity: 'HIGH' 40 | cpe: 'o' 41 | precondition: 'ADMIN' 42 | rule6: 43 | accessVector: 'LOCAL' 44 | authentication: 'NONE' 45 | accessComplexity: 'LOW' 46 | cpe: 'h' 47 | precondition: 'USER' 48 | rule7: 49 | accessVector: 'LOCAL' 50 | authentication: 'NONE' 51 | accessComplexity: 'HIGH' 52 | cpe: 'h' 53 | precondition: 'ADMIN' 54 | rule8: 55 | accessVector: '!LOCAL' 56 | authentication: '!NONE' 57 | accessComplexity: 'LOW' 58 | cpe: 'o' 59 | precondition: 'USER' 60 | rule9: 61 | accessVector: '!LOCAL' 62 | authentication: '!NONE' 63 | accessComplexity: 'HIGH' 64 | cpe: 'o' 65 | precondition: 'ADMIN' 66 | rule12: 67 | vocabulary: 68 | - 'allow ... guest OS user' 69 | - 'allow ... PV guest user' 70 | - 'user on a guest operating system' 71 | cpe: '?' 72 | precondition: 'VOS USER' 73 | rule13: 74 | vocabulary: 75 | - 'allow ... guest OS admin' 76 | - 'allow ... PV guest admin' 77 | - 'allow ... guest OS kernel admin' 78 | cpe: '?' 79 | precondition: 'VOS ADMIN' 80 | rule14: 81 | vocabulary: 82 | - 'allows local users' 83 | - 'allowing local users' 84 | - 'allow local users' 85 | - 'allows the local user' 86 | cpe: '?' 87 | precondition: 'USER' 88 | rule15: 89 | vocabulary: 90 | - 'allows local administrators' 91 | - 'allow local administrators' 92 | - 'allows the local administrator' 93 | cpe: '?' 94 | precondition: 'ADMIN' 95 | rule18: 96 | vocabulary: 97 | - 'remote authenticated users' 98 | cpe: 'o' 99 | precondition: 'USER' 100 | rule19: 101 | vocabulary: 102 | - 'remote authenticated admin' 103 | cpe: 'o' 104 | precondition: 'ADMIN' 105 | 106 | postconditions-rules: 107 | rule1: 108 | vocabulary: 109 | - 'gain root' 110 | - 'gain unrestricted, root shell access' 111 | - 'obtain root' 112 | impacts: 'ALL_COMPLETE' 113 | cpe: '?' 114 | postcondition: 'ADMIN' 115 | rule2: 116 | vocabulary: 117 | - 'gain privilege' 118 | - 'gain host OS privilege' 119 | - 'gain admin' 120 | - 'obtain local admin' 121 | - 'gain unauthorized access' 122 | - 'to root' 123 | - 'to the root' 124 | - 'elevate the privilege' 125 | - 'elevate privilege' 126 | - 'root privileges via buffer overflow' 127 | impacts: 'ALL_COMPLETE' 128 | cpe: '?' 129 | postcondition: 'ADMIN' 130 | rule3: 131 | vocabulary: 132 | - 'unspecified vulnerability' 133 | - 'unspecified other impact' 134 | - 'unspecified impact' 135 | - 'other impacts' 136 | impacts: 'ALL_COMPLETE' 137 | cpe: '?' 138 | postcondition: 'ADMIN' 139 | rule4: 140 | vocabulary: 141 | - 'unspecified vulnerability' 142 | - 'unspecified other impact' 143 | - 'unspecified impact' 144 | - 'other impacts' 145 | impacts: 'PARTIAL' 146 | cpe: 'o' 147 | postcondition: 'USER' 148 | rule5: 149 | vocabulary: 150 | - 'gain privilege' 151 | - 'gain unauthorized access' 152 | impacts: 'PARTIAL' 153 | cpe: 'o' 154 | postcondition: 'USER' 155 | rule9: 156 | vocabulary: 157 | - 'obtain password' 158 | - 'obtain credential' 159 | - 'sniff ... credentials' 160 | - 'sniff ... passwords' 161 | - 'steal ... credentials' 162 | - 'steal ... passwords' 163 | impacts: 'ALL_COMPLETE' 164 | cpe: 'o' 165 | postcondition: 'ADMIN' 166 | rule10: 167 | vocabulary: 168 | - 'obtain password' 169 | - 'obtain credential' 170 | - 'sniff ... credentials' 171 | - 'sniff ... passwords' 172 | - 'steal ... credentials' 173 | - 'steal ... passwords' 174 | impacts: 'PARTIAL' 175 | cpe: 'o' 176 | postcondition: 'USER' 177 | rule12: 178 | vocabulary: 179 | - 'cleartext credential' 180 | - 'cleartext password' 181 | - 'obtain plaintext' 182 | - 'obtain cleartext' 183 | - 'discover cleartext' 184 | - 'read network traffic' 185 | - 'un-encrypted' 186 | - 'unencrypted' 187 | - 'intercept transmission' 188 | - 'intercept communication' 189 | - 'obtain and decrypt passwords' 190 | - 'conduct offline password guessing' 191 | - 'bypass authentication' 192 | impacts: 'ALL_COMPLETE' 193 | cpe: 'o' 194 | postcondition: 'ADMIN' 195 | rule13: 196 | vocabulary: 197 | - 'cleartext credential' 198 | - 'cleartext password' 199 | - 'obtain plaintext' 200 | - 'obtain cleartext' 201 | - 'discover cleartext' 202 | - 'read network traffic' 203 | - 'un-encrypted' 204 | - 'unencrypted' 205 | - 'intercept transmission' 206 | - 'intercept communication' 207 | - 'obtain and decrypt passwords' 208 | - 'conduct offline password guessing' 209 | - 'bypass authentication' 210 | impacts: 'PARTIAL' 211 | cpe: 'o' 212 | postcondition: 'USER' 213 | rule15: 214 | vocabulary: 215 | - 'buffer overflow' 216 | - 'command injection' 217 | - 'write arbitrary file' 218 | - 'command execution' 219 | - 'execute command' 220 | - 'execute root command' 221 | - 'execute commands as root' 222 | - 'execute arbitrary' 223 | - 'execute dangerous' 224 | - 'execute php' 225 | - 'execute script' 226 | - 'execute local' 227 | - 'execution of arbitrary' 228 | - 'execution of command' 229 | - 'remote execution' 230 | - 'execute code' 231 | impacts: 'ALL_COMPLETE' 232 | cpe: '?' 233 | postcondition: 'ADMIN' 234 | rule16: 235 | vocabulary: 236 | - 'buffer overflow' 237 | - 'command injection' 238 | - 'write arbitrary file' 239 | - 'command execution' 240 | - 'execute command' 241 | - 'execute root command' 242 | - 'execute commands as root' 243 | - 'execute arbitrary' 244 | - 'execute dangerous' 245 | - 'execute php' 246 | - 'execute script' 247 | - 'execute local' 248 | - 'execution of arbitrary' 249 | - 'execution of command' 250 | - 'remote execution' 251 | - 'execute code' 252 | impacts: 'PARTIAL' 253 | cpe: '?' 254 | postcondition: 'USER' 255 | rule18: 256 | vocabulary: 257 | - '?' 258 | impacts: 'ANY_NONE' 259 | cpe: '?' 260 | postcondition: 'NONE' 261 | 262 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /System/examples/atsea-sample-shop-app-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/atsea-sample-shop-app-master.zip -------------------------------------------------------------------------------- /System/examples/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | networks: 16 | frontend: 17 | driver: bridge 18 | backend: 19 | driver: bridge 20 | -------------------------------------------------------------------------------- /System/examples/exploit-CVE-2016-10033-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/exploit-CVE-2016-10033-master.zip -------------------------------------------------------------------------------- /System/examples/exploit-CVE-2017-7494-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/exploit-CVE-2017-7494-master.zip -------------------------------------------------------------------------------- /System/examples/javaee-demo-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/javaee-demo-master.zip -------------------------------------------------------------------------------- /System/examples/netflix-oss-example-master-modified.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/netflix-oss-example-master-modified.zip -------------------------------------------------------------------------------- /System/examples/output_samples/atsea/attack_graph.dot: -------------------------------------------------------------------------------- 1 | // Attack Graph 2 | digraph { 3 | "atsea_db(USER)" 4 | "atsea_app(ADMIN)" 5 | "atsea_db(ADMIN)" 6 | "atsea_app(USER)" 7 | "outside(ADMIN)" 8 | "atsea_app(USER)" -> "atsea_app(ADMIN)" [label="CVE-2016-10244 9 | CVE-2016-9842 10 | CVE-2016-9843 11 | CVE-2016-9841 12 | CVE-2016-9840" contstraint=false] 13 | "atsea_db(USER)" -> "atsea_db(ADMIN)" [label="CVE-2017-18078 14 | CVE-2017-1000408 15 | CVE-2017-9525 16 | CVE-2017-1000082 17 | CVE-2007-6755 18 | CVE-2018-5730 19 | CVE-2018-6551 20 | CVE-2016-2779 21 | CVE-2017-14062 22 | CVE-2018-1000001 23 | CVE-2018-6485 24 | CVE-2018-7738 25 | CVE-2017-15365 26 | CVE-2017-17522 27 | CVE-2016-9318 28 | CVE-2018-1000030 29 | CVE-2017-5130 30 | CVE-2018-6954 31 | CVE-2013-4392 32 | CVE-2005-2541 33 | CVE-2017-11462 34 | CVE-2018-2755 35 | CVE-2018-5729 36 | CVE-2017-18078 37 | CVE-2017-1000408 38 | CVE-2017-9525 39 | CVE-2017-1000082 40 | CVE-2007-6755 41 | CVE-2018-5730 42 | CVE-2018-6551 43 | CVE-2016-2779 44 | CVE-2017-14062 45 | CVE-2018-1000001 46 | CVE-2018-6485 47 | CVE-2018-7738 48 | CVE-2017-15365 49 | CVE-2017-17522 50 | CVE-2016-9318 51 | CVE-2018-1000030 52 | CVE-2017-5130 53 | CVE-2018-6954 54 | CVE-2013-4392 55 | CVE-2005-2541 56 | CVE-2017-11462 57 | CVE-2018-2755 58 | CVE-2018-5729" contstraint=false] 59 | "atsea_db(ADMIN)" -> "atsea_app(USER)" [label="CVE-2017-6891 60 | CVE-2017-8105 61 | CVE-2017-8287" contstraint=false] 62 | "atsea_db(USER)" -> "atsea_app(ADMIN)" [label="CVE-2016-10244 63 | CVE-2016-9842 64 | CVE-2016-9843 65 | CVE-2016-9841 66 | CVE-2016-9840" contstraint=false] 67 | "outside(ADMIN)" -> "atsea_app(USER)" [label="CVE-2017-6891 68 | CVE-2017-8105 69 | CVE-2017-8287" contstraint=false] 70 | "outside(ADMIN)" -> "atsea_db(USER)" [label="CVE-2016-9427 71 | CVE-2017-7245 72 | CVE-2018-6913 73 | CVE-2017-15670 74 | CVE-2017-7246 75 | CVE-2017-12424 76 | CVE-2017-16879 77 | CVE-2017-1000409 78 | CVE-2018-6797 79 | CVE-2017-15804" contstraint=false] 80 | "atsea_db(USER)" -> "atsea_app(USER)" [label="CVE-2017-6891 81 | CVE-2017-8105 82 | CVE-2017-8287" contstraint=false] 83 | "atsea_db(ADMIN)" -> "atsea_app(ADMIN)" [label="CVE-2016-10244 84 | CVE-2016-9842 85 | CVE-2016-9843 86 | CVE-2016-9841 87 | CVE-2016-9840" contstraint=false] 88 | "outside(ADMIN)" -> "atsea_db(ADMIN)" [label="CVE-2017-18078 89 | CVE-2017-1000408 90 | CVE-2017-9525 91 | CVE-2017-1000082 92 | CVE-2007-6755 93 | CVE-2018-5730 94 | CVE-2018-6551 95 | CVE-2016-2779 96 | CVE-2017-14062 97 | CVE-2018-1000001 98 | CVE-2018-6485 99 | CVE-2018-7738 100 | CVE-2017-15365 101 | CVE-2017-17522 102 | CVE-2016-9318 103 | CVE-2018-1000030 104 | CVE-2017-5130 105 | CVE-2018-6954 106 | CVE-2013-4392 107 | CVE-2005-2541 108 | CVE-2017-11462 109 | CVE-2018-2755 110 | CVE-2018-5729" contstraint=false] 111 | "outside(ADMIN)" -> "atsea_app(ADMIN)" [label="CVE-2016-10244 112 | CVE-2016-9842 113 | CVE-2016-9843 114 | CVE-2016-9841 115 | CVE-2016-9840" contstraint=false] 116 | } 117 | -------------------------------------------------------------------------------- /System/examples/output_samples/atsea/attack_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/atsea/attack_graph.dot.pdf -------------------------------------------------------------------------------- /System/examples/output_samples/atsea/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | outside 4 | atsea_app 5 | atsea_db 6 | "docker host" 7 | atsea_reverse_proxy 8 | atsea_payment_gateway 9 | outside -- atsea_db [contstraint=false] 10 | outside -- atsea_app [contstraint=false] 11 | atsea_app -- "docker host" [contstraint=false] 12 | atsea_app -- atsea_db [contstraint=false] 13 | "docker host" -- atsea_payment_gateway [contstraint=false] 14 | "docker host" -- atsea_reverse_proxy [contstraint=false] 15 | atsea_db -- "docker host" [contstraint=false] 16 | } 17 | -------------------------------------------------------------------------------- /System/examples/output_samples/atsea/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/atsea/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/examples/output_samples/javaee/attack_graph.dot: -------------------------------------------------------------------------------- 1 | // Attack Graph 2 | digraph { 3 | "movieplex7-tomee(USER)" 4 | "outside(ADMIN)" 5 | "movieplex7-tomee(ADMIN)" 6 | "outside(ADMIN)" -> "movieplex7-tomee(USER)" [label="CVE-2017-7245 7 | CVE-2018-1000120 8 | CVE-2017-16879 9 | CVE-2017-11695 10 | CVE-2017-12424 11 | CVE-2017-7246 12 | CVE-2017-11698 13 | CVE-2018-8905 14 | CVE-2017-17095 15 | CVE-2017-15670 16 | CVE-2018-1000035 17 | CVE-2014-8166 18 | CVE-2017-1000409 19 | CVE-2017-15804 20 | CVE-2017-11696" contstraint=false] 21 | "outside(ADMIN)" -> "movieplex7-tomee(ADMIN)" [label="CVE-2017-14062 22 | CVE-2016-3177 23 | CVE-2017-9117 24 | CVE-2018-2633 25 | CVE-2017-5563 26 | CVE-2017-5130 27 | CVE-2018-5360 28 | CVE-2016-9318 29 | CVE-2017-11464 30 | CVE-2017-11697 31 | CVE-2017-2870 32 | CVE-2016-2779 33 | CVE-2018-7999 34 | CVE-2018-7738 35 | CVE-2017-1000408 36 | CVE-2017-15400 37 | CVE-2013-4392 38 | CVE-2017-17942 39 | CVE-2017-11462 40 | CVE-2018-5730 41 | CVE-2007-6755 42 | CVE-2018-2602 43 | CVE-2018-2814 44 | CVE-2017-15131 45 | CVE-2017-6892 46 | CVE-2005-2541 47 | CVE-2017-1000082 48 | CVE-2018-5729 49 | CVE-2018-2637 50 | CVE-2018-2800 51 | CVE-2018-1000001 52 | CVE-2018-2794 53 | CVE-2017-12562 54 | CVE-2018-6485 55 | CVE-2018-6954 56 | CVE-2017-14160 57 | CVE-2018-6551 58 | CVE-2017-18078" contstraint=false] 59 | "movieplex7-tomee(USER)" -> "movieplex7-tomee(ADMIN)" [label="CVE-2017-14062 60 | CVE-2016-3177 61 | CVE-2017-9117 62 | CVE-2018-2633 63 | CVE-2017-5563 64 | CVE-2017-5130 65 | CVE-2018-5360 66 | CVE-2016-9318 67 | CVE-2017-11464 68 | CVE-2017-11697 69 | CVE-2017-2870 70 | CVE-2016-2779 71 | CVE-2018-7999 72 | CVE-2018-7738 73 | CVE-2017-1000408 74 | CVE-2017-15400 75 | CVE-2013-4392 76 | CVE-2017-17942 77 | CVE-2017-11462 78 | CVE-2018-5730 79 | CVE-2007-6755 80 | CVE-2018-2602 81 | CVE-2018-2814 82 | CVE-2017-15131 83 | CVE-2017-6892 84 | CVE-2005-2541 85 | CVE-2017-1000082 86 | CVE-2018-5729 87 | CVE-2018-2637 88 | CVE-2018-2800 89 | CVE-2018-1000001 90 | CVE-2018-2794 91 | CVE-2017-12562 92 | CVE-2018-6485 93 | CVE-2018-6954 94 | CVE-2017-14160 95 | CVE-2018-6551 96 | CVE-2017-18078 97 | CVE-2017-14062 98 | CVE-2016-3177 99 | CVE-2017-9117 100 | CVE-2018-2633 101 | CVE-2017-5563 102 | CVE-2017-5130 103 | CVE-2018-5360 104 | CVE-2016-9318 105 | CVE-2017-11464 106 | CVE-2017-11697 107 | CVE-2017-2870 108 | CVE-2016-2779 109 | CVE-2018-7999 110 | CVE-2018-7738 111 | CVE-2017-1000408 112 | CVE-2017-15400 113 | CVE-2013-4392 114 | CVE-2017-17942 115 | CVE-2017-11462 116 | CVE-2018-5730 117 | CVE-2007-6755 118 | CVE-2018-2602 119 | CVE-2018-2814 120 | CVE-2017-15131 121 | CVE-2017-6892 122 | CVE-2005-2541 123 | CVE-2017-1000082 124 | CVE-2018-5729 125 | CVE-2018-2637 126 | CVE-2018-2800 127 | CVE-2018-1000001 128 | CVE-2018-2794 129 | CVE-2017-12562 130 | CVE-2018-6485 131 | CVE-2018-6954 132 | CVE-2017-14160 133 | CVE-2018-6551 134 | CVE-2017-18078" contstraint=false] 135 | } 136 | -------------------------------------------------------------------------------- /System/examples/output_samples/javaee/attack_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/javaee/attack_graph.dot.pdf -------------------------------------------------------------------------------- /System/examples/output_samples/javaee/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | "docker host" 4 | "movieplex7-tomee" 5 | "react-client" 6 | outside 7 | "movieplex7-tomee" -- "react-client" [contstraint=false] 8 | "react-client" -- outside [contstraint=false] 9 | "docker host" -- "react-client" [contstraint=false] 10 | "docker host" -- "movieplex7-tomee" [contstraint=false] 11 | "movieplex7-tomee" -- outside [contstraint=false] 12 | } 13 | -------------------------------------------------------------------------------- /System/examples/output_samples/javaee/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/javaee/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/examples/output_samples/netflix-oss-example/attack_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/netflix-oss-example/attack_graph.dot.pdf -------------------------------------------------------------------------------- /System/examples/output_samples/netflix-oss-example/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | outside 4 | netflixossexample_configservice 5 | "docker host" 6 | netflixossexample_servicec 7 | netflixossexample_zuul 8 | netflixossexample_turbine 9 | netflixossexample_springclouddashboard 10 | netflixossexample_serviceb 11 | netflixossexample_servicea 12 | netflixossexample_hystrixdashboard 13 | netflixossexample_eureka 14 | netflixossexample_rabbitmq 15 | netflixossexample_zuul -- netflixossexample_eureka [contstraint=false] 16 | netflixossexample_servicea -- netflixossexample_eureka [contstraint=false] 17 | netflixossexample_servicec -- netflixossexample_servicea [contstraint=false] 18 | "docker host" -- netflixossexample_serviceb [contstraint=false] 19 | netflixossexample_springclouddashboard -- netflixossexample_serviceb [contstraint=false] 20 | netflixossexample_springclouddashboard -- netflixossexample_servicea [contstraint=false] 21 | "docker host" -- netflixossexample_springclouddashboard [contstraint=false] 22 | netflixossexample_turbine -- netflixossexample_hystrixdashboard [contstraint=false] 23 | "docker host" -- netflixossexample_rabbitmq [contstraint=false] 24 | "docker host" -- netflixossexample_turbine [contstraint=false] 25 | netflixossexample_servicec -- netflixossexample_serviceb [contstraint=false] 26 | "docker host" -- netflixossexample_servicea [contstraint=false] 27 | netflixossexample_servicec -- netflixossexample_rabbitmq [contstraint=false] 28 | "docker host" -- netflixossexample_zuul [contstraint=false] 29 | netflixossexample_turbine -- netflixossexample_rabbitmq [contstraint=false] 30 | netflixossexample_turbine -- netflixossexample_springclouddashboard [contstraint=false] 31 | outside -- netflixossexample_zuul [contstraint=false] 32 | netflixossexample_serviceb -- netflixossexample_rabbitmq [contstraint=false] 33 | netflixossexample_configservice -- "docker host" [contstraint=false] 34 | netflixossexample_configservice -- netflixossexample_serviceb [contstraint=false] 35 | "docker host" -- netflixossexample_eureka [contstraint=false] 36 | netflixossexample_serviceb -- netflixossexample_servicea [contstraint=false] 37 | netflixossexample_servicec -- netflixossexample_eureka [contstraint=false] 38 | netflixossexample_configservice -- netflixossexample_servicec [contstraint=false] 39 | netflixossexample_springclouddashboard -- netflixossexample_eureka [contstraint=false] 40 | netflixossexample_servicea -- netflixossexample_rabbitmq [contstraint=false] 41 | netflixossexample_configservice -- netflixossexample_servicea [contstraint=false] 42 | netflixossexample_servicec -- netflixossexample_springclouddashboard [contstraint=false] 43 | "docker host" -- netflixossexample_servicec [contstraint=false] 44 | netflixossexample_serviceb -- netflixossexample_eureka [contstraint=false] 45 | "docker host" -- netflixossexample_hystrixdashboard [contstraint=false] 46 | } 47 | -------------------------------------------------------------------------------- /System/examples/output_samples/netflix-oss-example/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/examples/output_samples/netflix-oss-example/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/exportGO.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PATH=$PATH:/usr/local/go/bin 4 | export GOPATH=/usr/local/go/bin 5 | -------------------------------------------------------------------------------- /System/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Main module responsible for the attack graph generation pipeline.""" 3 | 4 | import sys 5 | import os 6 | import time 7 | 8 | from graphviz import Digraph 9 | from components import reader 10 | from components import writer 11 | from components import topology_parser as top_par 12 | from components import vulnerability_parser as vul_par 13 | from components import attack_graph_parser as att_gr_par 14 | 15 | def visualize_attack_graph(labels_edges, 16 | example_folder_path, 17 | nodes, 18 | edges): 19 | """This function visualizes the attack graph with given counter examples.""" 20 | 21 | dot = Digraph(comment="Attack Graph") 22 | for node in nodes: 23 | dot.node(node) 24 | 25 | for edge_name in edges.keys(): 26 | terminal_points = edge_name.split("|") 27 | 28 | edge_vuls = edges[edge_name] 29 | 30 | if labels_edges == "single": 31 | for edge_vul in edge_vuls: 32 | dot.edge(terminal_points[0], 33 | terminal_points[1], 34 | label=edge_vul, 35 | contstraint='false') 36 | 37 | elif labels_edges == "multiple": 38 | desc = "" 39 | for edge_vul in edge_vuls: 40 | if desc == "": 41 | desc += edge_vul 42 | else: 43 | desc += "\n"+edge_vul 44 | dot.edge(terminal_points[0], 45 | terminal_points[1], 46 | label=desc, contstraint='false') 47 | 48 | writer.write_attack_graph(example_folder_path, dot) 49 | print("Vizualizing the graph...") 50 | 51 | 52 | def main(example_folder): 53 | """Main function responsible for running the attack graph generation pipeline.""" 54 | 55 | # Opening the configuration file. 56 | config = reader.read_config_file() 57 | 58 | # Create folder where the result files will be stored. 59 | writer.create_folder(os.path.basename(example_folder)) 60 | 61 | # Parsing the topology of the docker containers. 62 | time_start = time.time() 63 | topology, duration_topology = top_par.parse_topology(example_folder) 64 | duration_topology = time.time() - time_start 65 | print("Time elapsed: "+str(duration_topology)+" seconds.\n") 66 | 67 | # Visualizing the topology graph. 68 | duration_visualization = 0 69 | if config['generate_graphs']: 70 | time_start = time.time() 71 | top_par.create_topology_graph(topology, 72 | example_folder) 73 | duration_visualization = time.time() - time_start 74 | print("Time elapsed: "+str(duration_visualization)+" seconds.\n") 75 | 76 | # Parsing the vulnerabilities for each docker container. 77 | vulnerabilities = {} 78 | duration_vulnerabilities = 0 79 | if config["mode"] == "online": 80 | time_start = time.time() 81 | vul_par.parse_vulnerabilities(example_folder) 82 | duration_vulnerabilities = time.time() - time_start 83 | print("Time elapsed: "+str(duration_vulnerabilities)+" seconds.\n") 84 | 85 | vulnerabilities_folder_path = os.path.join(config['examples-results-path'], 86 | os.path.basename(example_folder)) 87 | vulnerabilities = reader.read_vulnerabilities(vulnerabilities_folder_path, topology.keys()) 88 | 89 | if not vulnerabilities.keys(): 90 | print("There is a mistake with the vulnerabilities. Terminating the function...") 91 | return 92 | 93 | # Getting the attack graph nodes and edges from the attack paths. 94 | # Returns a tuple of the form: 95 | # (attack_graph_nodes, attack_graph_edges, duration_bdf, duration_vul_preprocessing) 96 | att_graph_tuple = att_gr_par.generate_attack_graph(config["attack-vector-folder-path"], 97 | config["preconditions-rules"], 98 | config["postconditions-rules"], 99 | topology, 100 | vulnerabilities, 101 | example_folder) 102 | 103 | print("Time elapsed: "+str(att_graph_tuple[2]+att_graph_tuple[3])+" seconds.\n") 104 | 105 | # Printing the graph properties. 106 | duration_graph_properties = att_gr_par.print_graph_properties(config["labels_edges"], 107 | nodes=att_graph_tuple[0], 108 | edges=att_graph_tuple[1]) 109 | 110 | #print(att_graph_tuple[0]) 111 | #print(len(att_graph_tuple[1].keys())) 112 | 113 | if config["show_one_vul_per_edge"]: 114 | for element in att_graph_tuple[1].keys(): 115 | att_graph_tuple[1][element] = [att_graph_tuple[1][element][0]] 116 | 117 | # Visualizing the attack graph. 118 | if config['generate_graphs']: 119 | time_start = time.time() 120 | visualize_attack_graph(config["labels_edges"], 121 | example_folder, 122 | nodes=att_graph_tuple[0], 123 | edges=att_graph_tuple[1]) 124 | duration_visualization = time.time() - time_start 125 | print("Time elapsed: "+str(duration_visualization)+" seconds.\n") 126 | 127 | # Printing time summary of the attack graph generation. 128 | writer.print_summary(config["mode"], 129 | config['generate_graphs'], 130 | duration_topology=duration_topology, 131 | duration_vulnerabilities=duration_vulnerabilities, 132 | duration_bdf=att_graph_tuple[2], 133 | duration_vuls_preprocessing=att_graph_tuple[3], 134 | duration_graph_properties=duration_graph_properties, 135 | duration_visualization=duration_visualization) 136 | 137 | if __name__ == "__main__": 138 | 139 | # Checks if the command-line input and config file content is valid. 140 | IS_VALID_INPUT = reader.validate_command_line_input(sys.argv) 141 | IS_VALID_CONFIG = reader.validate_config_file() 142 | 143 | if not IS_VALID_CONFIG: 144 | print("The config file is not valid.") 145 | exit() 146 | 147 | if IS_VALID_INPUT: 148 | 149 | # Checks if the docker-compose file is valid. 150 | IS_VALID_COMPOSE = top_par.validation_docker_compose(sys.argv[1]) 151 | if IS_VALID_COMPOSE: 152 | main(sys.argv[1]) 153 | else: 154 | print("Please have a look at the --help.") 155 | -------------------------------------------------------------------------------- /System/test/1000_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/1000_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/1000_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:12586a7772367b4e2ac34e130830238070c0fdd29d6e7c5259d3f7309c4cb8c5 3 | size 23982919 4 | -------------------------------------------------------------------------------- /System/test/100_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba1: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | samba2: 16 | build: ./samba 17 | networks: 18 | - frontend 19 | tty: true 20 | samba3: 21 | build: ./samba 22 | networks: 23 | - frontend 24 | tty: true 25 | samba4: 26 | build: ./samba 27 | networks: 28 | - frontend 29 | tty: true 30 | samba5: 31 | build: ./samba 32 | networks: 33 | - frontend 34 | tty: true 35 | samba6: 36 | build: ./samba 37 | networks: 38 | - frontend 39 | tty: true 40 | samba7: 41 | build: ./samba 42 | networks: 43 | - frontend 44 | tty: true 45 | samba8: 46 | build: ./samba 47 | networks: 48 | - frontend 49 | tty: true 50 | samba9: 51 | build: ./samba 52 | networks: 53 | - frontend 54 | tty: true 55 | samba10: 56 | build: ./samba 57 | networks: 58 | - frontend 59 | tty: true 60 | samba11: 61 | build: ./samba 62 | networks: 63 | - frontend 64 | tty: true 65 | samba12: 66 | build: ./samba 67 | networks: 68 | - frontend 69 | tty: true 70 | samba13: 71 | build: ./samba 72 | networks: 73 | - frontend 74 | tty: true 75 | samba14: 76 | build: ./samba 77 | networks: 78 | - frontend 79 | tty: true 80 | samba15: 81 | build: ./samba 82 | networks: 83 | - frontend 84 | tty: true 85 | samba16: 86 | build: ./samba 87 | networks: 88 | - frontend 89 | tty: true 90 | samba17: 91 | build: ./samba 92 | networks: 93 | - frontend 94 | tty: true 95 | samba18: 96 | build: ./samba 97 | networks: 98 | - frontend 99 | tty: true 100 | samba19: 101 | build: ./samba 102 | networks: 103 | - frontend 104 | tty: true 105 | samba20: 106 | build: ./samba 107 | networks: 108 | - frontend 109 | tty: true 110 | samba21: 111 | build: ./samba 112 | networks: 113 | - frontend 114 | tty: true 115 | samba22: 116 | build: ./samba 117 | networks: 118 | - frontend 119 | tty: true 120 | samba23: 121 | build: ./samba 122 | networks: 123 | - frontend 124 | tty: true 125 | samba24: 126 | build: ./samba 127 | networks: 128 | - frontend 129 | tty: true 130 | samba25: 131 | build: ./samba 132 | networks: 133 | - frontend 134 | tty: true 135 | samba26: 136 | build: ./samba 137 | networks: 138 | - frontend 139 | tty: true 140 | samba27: 141 | build: ./samba 142 | networks: 143 | - frontend 144 | tty: true 145 | samba28: 146 | build: ./samba 147 | networks: 148 | - frontend 149 | tty: true 150 | samba29: 151 | build: ./samba 152 | networks: 153 | - frontend 154 | tty: true 155 | samba30: 156 | build: ./samba 157 | networks: 158 | - frontend 159 | tty: true 160 | samba31: 161 | build: ./samba 162 | networks: 163 | - frontend 164 | tty: true 165 | samba32: 166 | build: ./samba 167 | networks: 168 | - frontend 169 | tty: true 170 | samba33: 171 | build: ./samba 172 | networks: 173 | - frontend 174 | tty: true 175 | samba34: 176 | build: ./samba 177 | networks: 178 | - frontend 179 | tty: true 180 | samba35: 181 | build: ./samba 182 | networks: 183 | - frontend 184 | tty: true 185 | samba36: 186 | build: ./samba 187 | networks: 188 | - frontend 189 | tty: true 190 | samba37: 191 | build: ./samba 192 | networks: 193 | - frontend 194 | tty: true 195 | samba38: 196 | build: ./samba 197 | networks: 198 | - frontend 199 | tty: true 200 | samba39: 201 | build: ./samba 202 | networks: 203 | - frontend 204 | tty: true 205 | samba40: 206 | build: ./samba 207 | networks: 208 | - frontend 209 | tty: true 210 | samba41: 211 | build: ./samba 212 | networks: 213 | - frontend 214 | tty: true 215 | samba42: 216 | build: ./samba 217 | networks: 218 | - frontend 219 | tty: true 220 | samba43: 221 | build: ./samba 222 | networks: 223 | - frontend 224 | tty: true 225 | samba44: 226 | build: ./samba 227 | networks: 228 | - frontend 229 | tty: true 230 | samba45: 231 | build: ./samba 232 | networks: 233 | - frontend 234 | tty: true 235 | samba46: 236 | build: ./samba 237 | networks: 238 | - frontend 239 | tty: true 240 | samba47: 241 | build: ./samba 242 | networks: 243 | - frontend 244 | tty: true 245 | samba48: 246 | build: ./samba 247 | networks: 248 | - frontend 249 | tty: true 250 | samba49: 251 | build: ./samba 252 | networks: 253 | - frontend 254 | tty: true 255 | samba50: 256 | build: ./samba 257 | networks: 258 | - frontend 259 | tty: true 260 | samba51: 261 | build: ./samba 262 | networks: 263 | - frontend 264 | tty: true 265 | samba52: 266 | build: ./samba 267 | networks: 268 | - frontend 269 | tty: true 270 | samba53: 271 | build: ./samba 272 | networks: 273 | - frontend 274 | tty: true 275 | samba54: 276 | build: ./samba 277 | networks: 278 | - frontend 279 | tty: true 280 | samba55: 281 | build: ./samba 282 | networks: 283 | - frontend 284 | tty: true 285 | samba56: 286 | build: ./samba 287 | networks: 288 | - frontend 289 | tty: true 290 | samba57: 291 | build: ./samba 292 | networks: 293 | - frontend 294 | tty: true 295 | samba58: 296 | build: ./samba 297 | networks: 298 | - frontend 299 | tty: true 300 | samba59: 301 | build: ./samba 302 | networks: 303 | - frontend 304 | tty: true 305 | samba60: 306 | build: ./samba 307 | networks: 308 | - frontend 309 | tty: true 310 | samba61: 311 | build: ./samba 312 | networks: 313 | - frontend 314 | tty: true 315 | samba62: 316 | build: ./samba 317 | networks: 318 | - frontend 319 | tty: true 320 | samba63: 321 | build: ./samba 322 | networks: 323 | - frontend 324 | tty: true 325 | samba64: 326 | build: ./samba 327 | networks: 328 | - frontend 329 | tty: true 330 | samba65: 331 | build: ./samba 332 | networks: 333 | - frontend 334 | tty: true 335 | samba66: 336 | build: ./samba 337 | networks: 338 | - frontend 339 | tty: true 340 | samba67: 341 | build: ./samba 342 | networks: 343 | - frontend 344 | tty: true 345 | samba68: 346 | build: ./samba 347 | networks: 348 | - frontend 349 | tty: true 350 | samba69: 351 | build: ./samba 352 | networks: 353 | - frontend 354 | tty: true 355 | samba70: 356 | build: ./samba 357 | networks: 358 | - frontend 359 | tty: true 360 | samba71: 361 | build: ./samba 362 | networks: 363 | - frontend 364 | tty: true 365 | samba72: 366 | build: ./samba 367 | networks: 368 | - frontend 369 | tty: true 370 | samba73: 371 | build: ./samba 372 | networks: 373 | - frontend 374 | tty: true 375 | samba74: 376 | build: ./samba 377 | networks: 378 | - frontend 379 | tty: true 380 | samba75: 381 | build: ./samba 382 | networks: 383 | - frontend 384 | tty: true 385 | samba76: 386 | build: ./samba 387 | networks: 388 | - frontend 389 | tty: true 390 | samba77: 391 | build: ./samba 392 | networks: 393 | - frontend 394 | tty: true 395 | samba78: 396 | build: ./samba 397 | networks: 398 | - frontend 399 | tty: true 400 | samba79: 401 | build: ./samba 402 | networks: 403 | - frontend 404 | tty: true 405 | samba80: 406 | build: ./samba 407 | networks: 408 | - frontend 409 | tty: true 410 | samba81: 411 | build: ./samba 412 | networks: 413 | - frontend 414 | tty: true 415 | samba82: 416 | build: ./samba 417 | networks: 418 | - frontend 419 | tty: true 420 | samba83: 421 | build: ./samba 422 | networks: 423 | - frontend 424 | tty: true 425 | samba84: 426 | build: ./samba 427 | networks: 428 | - frontend 429 | tty: true 430 | samba85: 431 | build: ./samba 432 | networks: 433 | - frontend 434 | tty: true 435 | samba86: 436 | build: ./samba 437 | networks: 438 | - frontend 439 | tty: true 440 | samba87: 441 | build: ./samba 442 | networks: 443 | - frontend 444 | tty: true 445 | samba88: 446 | build: ./samba 447 | networks: 448 | - frontend 449 | tty: true 450 | samba89: 451 | build: ./samba 452 | networks: 453 | - frontend 454 | tty: true 455 | samba90: 456 | build: ./samba 457 | networks: 458 | - frontend 459 | tty: true 460 | samba91: 461 | build: ./samba 462 | networks: 463 | - frontend 464 | tty: true 465 | samba92: 466 | build: ./samba 467 | networks: 468 | - frontend 469 | tty: true 470 | samba93: 471 | build: ./samba 472 | networks: 473 | - frontend 474 | tty: true 475 | samba94: 476 | build: ./samba 477 | networks: 478 | - frontend 479 | tty: true 480 | samba95: 481 | build: ./samba 482 | networks: 483 | - frontend 484 | tty: true 485 | samba96: 486 | build: ./samba 487 | networks: 488 | - frontend 489 | tty: true 490 | samba97: 491 | build: ./samba 492 | networks: 493 | - frontend 494 | tty: true 495 | samba98: 496 | build: ./samba 497 | networks: 498 | - frontend 499 | tty: true 500 | samba99: 501 | build: ./samba 502 | networks: 503 | - frontend 504 | tty: true 505 | samba100: 506 | build: ./samba 507 | networks: 508 | - frontend 509 | tty: true 510 | networks: 511 | frontend: 512 | driver: bridge 513 | backend: 514 | driver: bridge 515 | -------------------------------------------------------------------------------- /System/test/100_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/100_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/100_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1ea4181bad79ddfe57494137bf0b8ceb3afa02a09d581deb7a67b729fbf25f2f 3 | size 227814 4 | -------------------------------------------------------------------------------- /System/test/1_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | 16 | networks: 17 | frontend: 18 | driver: bridge 19 | backend: 20 | driver: bridge 21 | -------------------------------------------------------------------------------- /System/test/1_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/1_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/1_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:278b19714885b002c8bc218575726fa9fbb4311da959e25678d27aa511f4f073 3 | size 217 4 | -------------------------------------------------------------------------------- /System/test/1_example/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | outside 4 | "docker host" 5 | "1example_phpmailer" 6 | "1example_samba" 7 | outside -- "1example_phpmailer" [contstraint=false] 8 | "docker host" -- "1example_phpmailer" [contstraint=false] 9 | "docker host" -- "1example_samba" [contstraint=false] 10 | "1example_phpmailer" -- "1example_samba" [contstraint=false] 11 | } 12 | -------------------------------------------------------------------------------- /System/test/1_example/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/test/1_example/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/test/20_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba1: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | samba2: 16 | build: ./samba 17 | networks: 18 | - frontend 19 | tty: true 20 | samba3: 21 | build: ./samba 22 | networks: 23 | - frontend 24 | tty: true 25 | samba4: 26 | build: ./samba 27 | networks: 28 | - frontend 29 | tty: true 30 | samba5: 31 | build: ./samba 32 | networks: 33 | - frontend 34 | tty: true 35 | samba6: 36 | build: ./samba 37 | networks: 38 | - frontend 39 | tty: true 40 | samba7: 41 | build: ./samba 42 | networks: 43 | - frontend 44 | tty: true 45 | samba8: 46 | build: ./samba 47 | networks: 48 | - frontend 49 | tty: true 50 | samba9: 51 | build: ./samba 52 | networks: 53 | - frontend 54 | tty: true 55 | samba10: 56 | build: ./samba 57 | networks: 58 | - frontend 59 | tty: true 60 | samba11: 61 | build: ./samba 62 | networks: 63 | - frontend 64 | tty: true 65 | samba12: 66 | build: ./samba 67 | networks: 68 | - frontend 69 | tty: true 70 | samba13: 71 | build: ./samba 72 | networks: 73 | - frontend 74 | tty: true 75 | samba14: 76 | build: ./samba 77 | networks: 78 | - frontend 79 | tty: true 80 | samba15: 81 | build: ./samba 82 | networks: 83 | - frontend 84 | tty: true 85 | samba16: 86 | build: ./samba 87 | networks: 88 | - frontend 89 | tty: true 90 | samba17: 91 | build: ./samba 92 | networks: 93 | - frontend 94 | tty: true 95 | samba18: 96 | build: ./samba 97 | networks: 98 | - frontend 99 | tty: true 100 | samba19: 101 | build: ./samba 102 | networks: 103 | - frontend 104 | tty: true 105 | samba20: 106 | build: ./samba 107 | networks: 108 | - frontend 109 | tty: true 110 | 111 | networks: 112 | frontend: 113 | driver: bridge 114 | backend: 115 | driver: bridge 116 | -------------------------------------------------------------------------------- /System/test/20_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/20_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/20_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1c70affa5440447e21b338c6ee09ba8ba5b50cefb28811f20044f30998b3c85d 3 | size 9969 4 | -------------------------------------------------------------------------------- /System/test/20_example/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | outside 4 | "docker host" 5 | "20example_phpmailer" 6 | "20example_samba1" 7 | "20example_samba2" 8 | "20example_samba3" 9 | "20example_samba4" 10 | "20example_samba5" 11 | "20example_samba6" 12 | "20example_samba7" 13 | "20example_samba8" 14 | "20example_samba9" 15 | "20example_samba10" 16 | "20example_samba11" 17 | "20example_samba12" 18 | "20example_samba13" 19 | "20example_samba14" 20 | "20example_samba15" 21 | "20example_samba16" 22 | "20example_samba17" 23 | "20example_samba18" 24 | "20example_samba19" 25 | "20example_samba20" 26 | outside -- "20example_phpmailer" [contstraint=false] 27 | "docker host" -- "20example_phpmailer" [contstraint=false] 28 | "docker host" -- "20example_samba1" [contstraint=false] 29 | "docker host" -- "20example_samba2" [contstraint=false] 30 | "docker host" -- "20example_samba3" [contstraint=false] 31 | "docker host" -- "20example_samba4" [contstraint=false] 32 | "docker host" -- "20example_samba5" [contstraint=false] 33 | "docker host" -- "20example_samba6" [contstraint=false] 34 | "docker host" -- "20example_samba7" [contstraint=false] 35 | "docker host" -- "20example_samba8" [contstraint=false] 36 | "docker host" -- "20example_samba9" [contstraint=false] 37 | "docker host" -- "20example_samba10" [contstraint=false] 38 | "docker host" -- "20example_samba11" [contstraint=false] 39 | "docker host" -- "20example_samba12" [contstraint=false] 40 | "docker host" -- "20example_samba13" [contstraint=false] 41 | "docker host" -- "20example_samba14" [contstraint=false] 42 | "docker host" -- "20example_samba15" [contstraint=false] 43 | "docker host" -- "20example_samba16" [contstraint=false] 44 | "docker host" -- "20example_samba17" [contstraint=false] 45 | "docker host" -- "20example_samba18" [contstraint=false] 46 | "docker host" -- "20example_samba19" [contstraint=false] 47 | "docker host" -- "20example_samba20" [contstraint=false] 48 | "20example_phpmailer" -- "20example_samba1" [contstraint=false] 49 | "20example_phpmailer" -- "20example_samba2" [contstraint=false] 50 | "20example_phpmailer" -- "20example_samba3" [contstraint=false] 51 | "20example_phpmailer" -- "20example_samba4" [contstraint=false] 52 | "20example_phpmailer" -- "20example_samba5" [contstraint=false] 53 | "20example_phpmailer" -- "20example_samba6" [contstraint=false] 54 | "20example_phpmailer" -- "20example_samba7" [contstraint=false] 55 | "20example_phpmailer" -- "20example_samba8" [contstraint=false] 56 | "20example_phpmailer" -- "20example_samba9" [contstraint=false] 57 | "20example_phpmailer" -- "20example_samba10" [contstraint=false] 58 | "20example_phpmailer" -- "20example_samba11" [contstraint=false] 59 | "20example_phpmailer" -- "20example_samba12" [contstraint=false] 60 | "20example_phpmailer" -- "20example_samba13" [contstraint=false] 61 | "20example_phpmailer" -- "20example_samba14" [contstraint=false] 62 | "20example_phpmailer" -- "20example_samba15" [contstraint=false] 63 | "20example_phpmailer" -- "20example_samba16" [contstraint=false] 64 | "20example_phpmailer" -- "20example_samba17" [contstraint=false] 65 | "20example_phpmailer" -- "20example_samba18" [contstraint=false] 66 | "20example_phpmailer" -- "20example_samba19" [contstraint=false] 67 | "20example_phpmailer" -- "20example_samba20" [contstraint=false] 68 | "20example_samba1" -- "20example_samba2" [contstraint=false] 69 | "20example_samba1" -- "20example_samba3" [contstraint=false] 70 | "20example_samba1" -- "20example_samba4" [contstraint=false] 71 | "20example_samba1" -- "20example_samba5" [contstraint=false] 72 | "20example_samba1" -- "20example_samba6" [contstraint=false] 73 | "20example_samba1" -- "20example_samba7" [contstraint=false] 74 | "20example_samba1" -- "20example_samba8" [contstraint=false] 75 | "20example_samba1" -- "20example_samba9" [contstraint=false] 76 | "20example_samba1" -- "20example_samba10" [contstraint=false] 77 | "20example_samba1" -- "20example_samba11" [contstraint=false] 78 | "20example_samba1" -- "20example_samba12" [contstraint=false] 79 | "20example_samba1" -- "20example_samba13" [contstraint=false] 80 | "20example_samba1" -- "20example_samba14" [contstraint=false] 81 | "20example_samba1" -- "20example_samba15" [contstraint=false] 82 | "20example_samba1" -- "20example_samba16" [contstraint=false] 83 | "20example_samba1" -- "20example_samba17" [contstraint=false] 84 | "20example_samba1" -- "20example_samba18" [contstraint=false] 85 | "20example_samba1" -- "20example_samba19" [contstraint=false] 86 | "20example_samba1" -- "20example_samba20" [contstraint=false] 87 | "20example_samba2" -- "20example_samba3" [contstraint=false] 88 | "20example_samba2" -- "20example_samba4" [contstraint=false] 89 | "20example_samba2" -- "20example_samba5" [contstraint=false] 90 | "20example_samba2" -- "20example_samba6" [contstraint=false] 91 | "20example_samba2" -- "20example_samba7" [contstraint=false] 92 | "20example_samba2" -- "20example_samba8" [contstraint=false] 93 | "20example_samba2" -- "20example_samba9" [contstraint=false] 94 | "20example_samba2" -- "20example_samba10" [contstraint=false] 95 | "20example_samba2" -- "20example_samba11" [contstraint=false] 96 | "20example_samba2" -- "20example_samba12" [contstraint=false] 97 | "20example_samba2" -- "20example_samba13" [contstraint=false] 98 | "20example_samba2" -- "20example_samba14" [contstraint=false] 99 | "20example_samba2" -- "20example_samba15" [contstraint=false] 100 | "20example_samba2" -- "20example_samba16" [contstraint=false] 101 | "20example_samba2" -- "20example_samba17" [contstraint=false] 102 | "20example_samba2" -- "20example_samba18" [contstraint=false] 103 | "20example_samba2" -- "20example_samba19" [contstraint=false] 104 | "20example_samba2" -- "20example_samba20" [contstraint=false] 105 | "20example_samba3" -- "20example_samba4" [contstraint=false] 106 | "20example_samba3" -- "20example_samba5" [contstraint=false] 107 | "20example_samba3" -- "20example_samba6" [contstraint=false] 108 | "20example_samba3" -- "20example_samba7" [contstraint=false] 109 | "20example_samba3" -- "20example_samba8" [contstraint=false] 110 | "20example_samba3" -- "20example_samba9" [contstraint=false] 111 | "20example_samba3" -- "20example_samba10" [contstraint=false] 112 | "20example_samba3" -- "20example_samba11" [contstraint=false] 113 | "20example_samba3" -- "20example_samba12" [contstraint=false] 114 | "20example_samba3" -- "20example_samba13" [contstraint=false] 115 | "20example_samba3" -- "20example_samba14" [contstraint=false] 116 | "20example_samba3" -- "20example_samba15" [contstraint=false] 117 | "20example_samba3" -- "20example_samba16" [contstraint=false] 118 | "20example_samba3" -- "20example_samba17" [contstraint=false] 119 | "20example_samba3" -- "20example_samba18" [contstraint=false] 120 | "20example_samba3" -- "20example_samba19" [contstraint=false] 121 | "20example_samba3" -- "20example_samba20" [contstraint=false] 122 | "20example_samba4" -- "20example_samba5" [contstraint=false] 123 | "20example_samba4" -- "20example_samba6" [contstraint=false] 124 | "20example_samba4" -- "20example_samba7" [contstraint=false] 125 | "20example_samba4" -- "20example_samba8" [contstraint=false] 126 | "20example_samba4" -- "20example_samba9" [contstraint=false] 127 | "20example_samba4" -- "20example_samba10" [contstraint=false] 128 | "20example_samba4" -- "20example_samba11" [contstraint=false] 129 | "20example_samba4" -- "20example_samba12" [contstraint=false] 130 | "20example_samba4" -- "20example_samba13" [contstraint=false] 131 | "20example_samba4" -- "20example_samba14" [contstraint=false] 132 | "20example_samba4" -- "20example_samba15" [contstraint=false] 133 | "20example_samba4" -- "20example_samba16" [contstraint=false] 134 | "20example_samba4" -- "20example_samba17" [contstraint=false] 135 | "20example_samba4" -- "20example_samba18" [contstraint=false] 136 | "20example_samba4" -- "20example_samba19" [contstraint=false] 137 | "20example_samba4" -- "20example_samba20" [contstraint=false] 138 | "20example_samba5" -- "20example_samba6" [contstraint=false] 139 | "20example_samba5" -- "20example_samba7" [contstraint=false] 140 | "20example_samba5" -- "20example_samba8" [contstraint=false] 141 | "20example_samba5" -- "20example_samba9" [contstraint=false] 142 | "20example_samba5" -- "20example_samba10" [contstraint=false] 143 | "20example_samba5" -- "20example_samba11" [contstraint=false] 144 | "20example_samba5" -- "20example_samba12" [contstraint=false] 145 | "20example_samba5" -- "20example_samba13" [contstraint=false] 146 | "20example_samba5" -- "20example_samba14" [contstraint=false] 147 | "20example_samba5" -- "20example_samba15" [contstraint=false] 148 | "20example_samba5" -- "20example_samba16" [contstraint=false] 149 | "20example_samba5" -- "20example_samba17" [contstraint=false] 150 | "20example_samba5" -- "20example_samba18" [contstraint=false] 151 | "20example_samba5" -- "20example_samba19" [contstraint=false] 152 | "20example_samba5" -- "20example_samba20" [contstraint=false] 153 | "20example_samba6" -- "20example_samba7" [contstraint=false] 154 | "20example_samba6" -- "20example_samba8" [contstraint=false] 155 | "20example_samba6" -- "20example_samba9" [contstraint=false] 156 | "20example_samba6" -- "20example_samba10" [contstraint=false] 157 | "20example_samba6" -- "20example_samba11" [contstraint=false] 158 | "20example_samba6" -- "20example_samba12" [contstraint=false] 159 | "20example_samba6" -- "20example_samba13" [contstraint=false] 160 | "20example_samba6" -- "20example_samba14" [contstraint=false] 161 | "20example_samba6" -- "20example_samba15" [contstraint=false] 162 | "20example_samba6" -- "20example_samba16" [contstraint=false] 163 | "20example_samba6" -- "20example_samba17" [contstraint=false] 164 | "20example_samba6" -- "20example_samba18" [contstraint=false] 165 | "20example_samba6" -- "20example_samba19" [contstraint=false] 166 | "20example_samba6" -- "20example_samba20" [contstraint=false] 167 | "20example_samba7" -- "20example_samba8" [contstraint=false] 168 | "20example_samba7" -- "20example_samba9" [contstraint=false] 169 | "20example_samba7" -- "20example_samba10" [contstraint=false] 170 | "20example_samba7" -- "20example_samba11" [contstraint=false] 171 | "20example_samba7" -- "20example_samba12" [contstraint=false] 172 | "20example_samba7" -- "20example_samba13" [contstraint=false] 173 | "20example_samba7" -- "20example_samba14" [contstraint=false] 174 | "20example_samba7" -- "20example_samba15" [contstraint=false] 175 | "20example_samba7" -- "20example_samba16" [contstraint=false] 176 | "20example_samba7" -- "20example_samba17" [contstraint=false] 177 | "20example_samba7" -- "20example_samba18" [contstraint=false] 178 | "20example_samba7" -- "20example_samba19" [contstraint=false] 179 | "20example_samba7" -- "20example_samba20" [contstraint=false] 180 | "20example_samba8" -- "20example_samba9" [contstraint=false] 181 | "20example_samba8" -- "20example_samba10" [contstraint=false] 182 | "20example_samba8" -- "20example_samba11" [contstraint=false] 183 | "20example_samba8" -- "20example_samba12" [contstraint=false] 184 | "20example_samba8" -- "20example_samba13" [contstraint=false] 185 | "20example_samba8" -- "20example_samba14" [contstraint=false] 186 | "20example_samba8" -- "20example_samba15" [contstraint=false] 187 | "20example_samba8" -- "20example_samba16" [contstraint=false] 188 | "20example_samba8" -- "20example_samba17" [contstraint=false] 189 | "20example_samba8" -- "20example_samba18" [contstraint=false] 190 | "20example_samba8" -- "20example_samba19" [contstraint=false] 191 | "20example_samba8" -- "20example_samba20" [contstraint=false] 192 | "20example_samba9" -- "20example_samba10" [contstraint=false] 193 | "20example_samba9" -- "20example_samba11" [contstraint=false] 194 | "20example_samba9" -- "20example_samba12" [contstraint=false] 195 | "20example_samba9" -- "20example_samba13" [contstraint=false] 196 | "20example_samba9" -- "20example_samba14" [contstraint=false] 197 | "20example_samba9" -- "20example_samba15" [contstraint=false] 198 | "20example_samba9" -- "20example_samba16" [contstraint=false] 199 | "20example_samba9" -- "20example_samba17" [contstraint=false] 200 | "20example_samba9" -- "20example_samba18" [contstraint=false] 201 | "20example_samba9" -- "20example_samba19" [contstraint=false] 202 | "20example_samba9" -- "20example_samba20" [contstraint=false] 203 | "20example_samba10" -- "20example_samba11" [contstraint=false] 204 | "20example_samba10" -- "20example_samba12" [contstraint=false] 205 | "20example_samba10" -- "20example_samba13" [contstraint=false] 206 | "20example_samba10" -- "20example_samba14" [contstraint=false] 207 | "20example_samba10" -- "20example_samba15" [contstraint=false] 208 | "20example_samba10" -- "20example_samba16" [contstraint=false] 209 | "20example_samba10" -- "20example_samba17" [contstraint=false] 210 | "20example_samba10" -- "20example_samba18" [contstraint=false] 211 | "20example_samba10" -- "20example_samba19" [contstraint=false] 212 | "20example_samba10" -- "20example_samba20" [contstraint=false] 213 | "20example_samba11" -- "20example_samba12" [contstraint=false] 214 | "20example_samba11" -- "20example_samba13" [contstraint=false] 215 | "20example_samba11" -- "20example_samba14" [contstraint=false] 216 | "20example_samba11" -- "20example_samba15" [contstraint=false] 217 | "20example_samba11" -- "20example_samba16" [contstraint=false] 218 | "20example_samba11" -- "20example_samba17" [contstraint=false] 219 | "20example_samba11" -- "20example_samba18" [contstraint=false] 220 | "20example_samba11" -- "20example_samba19" [contstraint=false] 221 | "20example_samba11" -- "20example_samba20" [contstraint=false] 222 | "20example_samba12" -- "20example_samba13" [contstraint=false] 223 | "20example_samba12" -- "20example_samba14" [contstraint=false] 224 | "20example_samba12" -- "20example_samba15" [contstraint=false] 225 | "20example_samba12" -- "20example_samba16" [contstraint=false] 226 | "20example_samba12" -- "20example_samba17" [contstraint=false] 227 | "20example_samba12" -- "20example_samba18" [contstraint=false] 228 | "20example_samba12" -- "20example_samba19" [contstraint=false] 229 | "20example_samba12" -- "20example_samba20" [contstraint=false] 230 | "20example_samba13" -- "20example_samba14" [contstraint=false] 231 | "20example_samba13" -- "20example_samba15" [contstraint=false] 232 | "20example_samba13" -- "20example_samba16" [contstraint=false] 233 | "20example_samba13" -- "20example_samba17" [contstraint=false] 234 | "20example_samba13" -- "20example_samba18" [contstraint=false] 235 | "20example_samba13" -- "20example_samba19" [contstraint=false] 236 | "20example_samba13" -- "20example_samba20" [contstraint=false] 237 | "20example_samba14" -- "20example_samba15" [contstraint=false] 238 | "20example_samba14" -- "20example_samba16" [contstraint=false] 239 | "20example_samba14" -- "20example_samba17" [contstraint=false] 240 | "20example_samba14" -- "20example_samba18" [contstraint=false] 241 | "20example_samba14" -- "20example_samba19" [contstraint=false] 242 | "20example_samba14" -- "20example_samba20" [contstraint=false] 243 | "20example_samba15" -- "20example_samba16" [contstraint=false] 244 | "20example_samba15" -- "20example_samba17" [contstraint=false] 245 | "20example_samba15" -- "20example_samba18" [contstraint=false] 246 | "20example_samba15" -- "20example_samba19" [contstraint=false] 247 | "20example_samba15" -- "20example_samba20" [contstraint=false] 248 | "20example_samba16" -- "20example_samba17" [contstraint=false] 249 | "20example_samba16" -- "20example_samba18" [contstraint=false] 250 | "20example_samba16" -- "20example_samba19" [contstraint=false] 251 | "20example_samba16" -- "20example_samba20" [contstraint=false] 252 | "20example_samba17" -- "20example_samba18" [contstraint=false] 253 | "20example_samba17" -- "20example_samba19" [contstraint=false] 254 | "20example_samba17" -- "20example_samba20" [contstraint=false] 255 | "20example_samba18" -- "20example_samba19" [contstraint=false] 256 | "20example_samba18" -- "20example_samba20" [contstraint=false] 257 | "20example_samba19" -- "20example_samba20" [contstraint=false] 258 | } 259 | -------------------------------------------------------------------------------- /System/test/20_example/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/test/20_example/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/test/500_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | backend: 3 | driver: bridge 4 | frontend: 5 | driver: bridge 6 | services: 7 | phpmailer: 8 | build: ./phpmailer 9 | networks: 10 | - frontend 11 | ports: 12 | - 80 13 | samba1: 14 | build: ./samba 15 | networks: 16 | - frontend 17 | tty: true 18 | samba10: 19 | build: ./samba 20 | networks: 21 | - frontend 22 | tty: true 23 | samba100: 24 | build: ./samba 25 | networks: 26 | - frontend 27 | tty: true 28 | samba101: 29 | build: ./samba 30 | networks: 31 | - frontend 32 | tty: true 33 | samba102: 34 | build: ./samba 35 | networks: 36 | - frontend 37 | tty: true 38 | samba103: 39 | build: ./samba 40 | networks: 41 | - frontend 42 | tty: true 43 | samba104: 44 | build: ./samba 45 | networks: 46 | - frontend 47 | tty: true 48 | samba105: 49 | build: ./samba 50 | networks: 51 | - frontend 52 | tty: true 53 | samba106: 54 | build: ./samba 55 | networks: 56 | - frontend 57 | tty: true 58 | samba107: 59 | build: ./samba 60 | networks: 61 | - frontend 62 | tty: true 63 | samba108: 64 | build: ./samba 65 | networks: 66 | - frontend 67 | tty: true 68 | samba109: 69 | build: ./samba 70 | networks: 71 | - frontend 72 | tty: true 73 | samba11: 74 | build: ./samba 75 | networks: 76 | - frontend 77 | tty: true 78 | samba110: 79 | build: ./samba 80 | networks: 81 | - frontend 82 | tty: true 83 | samba111: 84 | build: ./samba 85 | networks: 86 | - frontend 87 | tty: true 88 | samba112: 89 | build: ./samba 90 | networks: 91 | - frontend 92 | tty: true 93 | samba113: 94 | build: ./samba 95 | networks: 96 | - frontend 97 | tty: true 98 | samba114: 99 | build: ./samba 100 | networks: 101 | - frontend 102 | tty: true 103 | samba115: 104 | build: ./samba 105 | networks: 106 | - frontend 107 | tty: true 108 | samba116: 109 | build: ./samba 110 | networks: 111 | - frontend 112 | tty: true 113 | samba117: 114 | build: ./samba 115 | networks: 116 | - frontend 117 | tty: true 118 | samba118: 119 | build: ./samba 120 | networks: 121 | - frontend 122 | tty: true 123 | samba119: 124 | build: ./samba 125 | networks: 126 | - frontend 127 | tty: true 128 | samba12: 129 | build: ./samba 130 | networks: 131 | - frontend 132 | tty: true 133 | samba120: 134 | build: ./samba 135 | networks: 136 | - frontend 137 | tty: true 138 | samba121: 139 | build: ./samba 140 | networks: 141 | - frontend 142 | tty: true 143 | samba122: 144 | build: ./samba 145 | networks: 146 | - frontend 147 | tty: true 148 | samba123: 149 | build: ./samba 150 | networks: 151 | - frontend 152 | tty: true 153 | samba124: 154 | build: ./samba 155 | networks: 156 | - frontend 157 | tty: true 158 | samba125: 159 | build: ./samba 160 | networks: 161 | - frontend 162 | tty: true 163 | samba126: 164 | build: ./samba 165 | networks: 166 | - frontend 167 | tty: true 168 | samba127: 169 | build: ./samba 170 | networks: 171 | - frontend 172 | tty: true 173 | samba128: 174 | build: ./samba 175 | networks: 176 | - frontend 177 | tty: true 178 | samba129: 179 | build: ./samba 180 | networks: 181 | - frontend 182 | tty: true 183 | samba13: 184 | build: ./samba 185 | networks: 186 | - frontend 187 | tty: true 188 | samba130: 189 | build: ./samba 190 | networks: 191 | - frontend 192 | tty: true 193 | samba131: 194 | build: ./samba 195 | networks: 196 | - frontend 197 | tty: true 198 | samba132: 199 | build: ./samba 200 | networks: 201 | - frontend 202 | tty: true 203 | samba133: 204 | build: ./samba 205 | networks: 206 | - frontend 207 | tty: true 208 | samba134: 209 | build: ./samba 210 | networks: 211 | - frontend 212 | tty: true 213 | samba135: 214 | build: ./samba 215 | networks: 216 | - frontend 217 | tty: true 218 | samba136: 219 | build: ./samba 220 | networks: 221 | - frontend 222 | tty: true 223 | samba137: 224 | build: ./samba 225 | networks: 226 | - frontend 227 | tty: true 228 | samba138: 229 | build: ./samba 230 | networks: 231 | - frontend 232 | tty: true 233 | samba139: 234 | build: ./samba 235 | networks: 236 | - frontend 237 | tty: true 238 | samba14: 239 | build: ./samba 240 | networks: 241 | - frontend 242 | tty: true 243 | samba140: 244 | build: ./samba 245 | networks: 246 | - frontend 247 | tty: true 248 | samba141: 249 | build: ./samba 250 | networks: 251 | - frontend 252 | tty: true 253 | samba142: 254 | build: ./samba 255 | networks: 256 | - frontend 257 | tty: true 258 | samba143: 259 | build: ./samba 260 | networks: 261 | - frontend 262 | tty: true 263 | samba144: 264 | build: ./samba 265 | networks: 266 | - frontend 267 | tty: true 268 | samba145: 269 | build: ./samba 270 | networks: 271 | - frontend 272 | tty: true 273 | samba146: 274 | build: ./samba 275 | networks: 276 | - frontend 277 | tty: true 278 | samba147: 279 | build: ./samba 280 | networks: 281 | - frontend 282 | tty: true 283 | samba148: 284 | build: ./samba 285 | networks: 286 | - frontend 287 | tty: true 288 | samba149: 289 | build: ./samba 290 | networks: 291 | - frontend 292 | tty: true 293 | samba15: 294 | build: ./samba 295 | networks: 296 | - frontend 297 | tty: true 298 | samba150: 299 | build: ./samba 300 | networks: 301 | - frontend 302 | tty: true 303 | samba151: 304 | build: ./samba 305 | networks: 306 | - frontend 307 | tty: true 308 | samba152: 309 | build: ./samba 310 | networks: 311 | - frontend 312 | tty: true 313 | samba153: 314 | build: ./samba 315 | networks: 316 | - frontend 317 | tty: true 318 | samba154: 319 | build: ./samba 320 | networks: 321 | - frontend 322 | tty: true 323 | samba155: 324 | build: ./samba 325 | networks: 326 | - frontend 327 | tty: true 328 | samba156: 329 | build: ./samba 330 | networks: 331 | - frontend 332 | tty: true 333 | samba157: 334 | build: ./samba 335 | networks: 336 | - frontend 337 | tty: true 338 | samba158: 339 | build: ./samba 340 | networks: 341 | - frontend 342 | tty: true 343 | samba159: 344 | build: ./samba 345 | networks: 346 | - frontend 347 | tty: true 348 | samba16: 349 | build: ./samba 350 | networks: 351 | - frontend 352 | tty: true 353 | samba160: 354 | build: ./samba 355 | networks: 356 | - frontend 357 | tty: true 358 | samba161: 359 | build: ./samba 360 | networks: 361 | - frontend 362 | tty: true 363 | samba162: 364 | build: ./samba 365 | networks: 366 | - frontend 367 | tty: true 368 | samba163: 369 | build: ./samba 370 | networks: 371 | - frontend 372 | tty: true 373 | samba164: 374 | build: ./samba 375 | networks: 376 | - frontend 377 | tty: true 378 | samba165: 379 | build: ./samba 380 | networks: 381 | - frontend 382 | tty: true 383 | samba166: 384 | build: ./samba 385 | networks: 386 | - frontend 387 | tty: true 388 | samba167: 389 | build: ./samba 390 | networks: 391 | - frontend 392 | tty: true 393 | samba168: 394 | build: ./samba 395 | networks: 396 | - frontend 397 | tty: true 398 | samba169: 399 | build: ./samba 400 | networks: 401 | - frontend 402 | tty: true 403 | samba17: 404 | build: ./samba 405 | networks: 406 | - frontend 407 | tty: true 408 | samba170: 409 | build: ./samba 410 | networks: 411 | - frontend 412 | tty: true 413 | samba171: 414 | build: ./samba 415 | networks: 416 | - frontend 417 | tty: true 418 | samba172: 419 | build: ./samba 420 | networks: 421 | - frontend 422 | tty: true 423 | samba173: 424 | build: ./samba 425 | networks: 426 | - frontend 427 | tty: true 428 | samba174: 429 | build: ./samba 430 | networks: 431 | - frontend 432 | tty: true 433 | samba175: 434 | build: ./samba 435 | networks: 436 | - frontend 437 | tty: true 438 | samba176: 439 | build: ./samba 440 | networks: 441 | - frontend 442 | tty: true 443 | samba177: 444 | build: ./samba 445 | networks: 446 | - frontend 447 | tty: true 448 | samba178: 449 | build: ./samba 450 | networks: 451 | - frontend 452 | tty: true 453 | samba179: 454 | build: ./samba 455 | networks: 456 | - frontend 457 | tty: true 458 | samba18: 459 | build: ./samba 460 | networks: 461 | - frontend 462 | tty: true 463 | samba180: 464 | build: ./samba 465 | networks: 466 | - frontend 467 | tty: true 468 | samba181: 469 | build: ./samba 470 | networks: 471 | - frontend 472 | tty: true 473 | samba182: 474 | build: ./samba 475 | networks: 476 | - frontend 477 | tty: true 478 | samba183: 479 | build: ./samba 480 | networks: 481 | - frontend 482 | tty: true 483 | samba184: 484 | build: ./samba 485 | networks: 486 | - frontend 487 | tty: true 488 | samba185: 489 | build: ./samba 490 | networks: 491 | - frontend 492 | tty: true 493 | samba186: 494 | build: ./samba 495 | networks: 496 | - frontend 497 | tty: true 498 | samba187: 499 | build: ./samba 500 | networks: 501 | - frontend 502 | tty: true 503 | samba188: 504 | build: ./samba 505 | networks: 506 | - frontend 507 | tty: true 508 | samba189: 509 | build: ./samba 510 | networks: 511 | - frontend 512 | tty: true 513 | samba19: 514 | build: ./samba 515 | networks: 516 | - frontend 517 | tty: true 518 | samba190: 519 | build: ./samba 520 | networks: 521 | - frontend 522 | tty: true 523 | samba191: 524 | build: ./samba 525 | networks: 526 | - frontend 527 | tty: true 528 | samba192: 529 | build: ./samba 530 | networks: 531 | - frontend 532 | tty: true 533 | samba193: 534 | build: ./samba 535 | networks: 536 | - frontend 537 | tty: true 538 | samba194: 539 | build: ./samba 540 | networks: 541 | - frontend 542 | tty: true 543 | samba195: 544 | build: ./samba 545 | networks: 546 | - frontend 547 | tty: true 548 | samba196: 549 | build: ./samba 550 | networks: 551 | - frontend 552 | tty: true 553 | samba197: 554 | build: ./samba 555 | networks: 556 | - frontend 557 | tty: true 558 | samba198: 559 | build: ./samba 560 | networks: 561 | - frontend 562 | tty: true 563 | samba199: 564 | build: ./samba 565 | networks: 566 | - frontend 567 | tty: true 568 | samba2: 569 | build: ./samba 570 | networks: 571 | - frontend 572 | tty: true 573 | samba20: 574 | build: ./samba 575 | networks: 576 | - frontend 577 | tty: true 578 | samba200: 579 | build: ./samba 580 | networks: 581 | - frontend 582 | tty: true 583 | samba201: 584 | build: ./samba 585 | networks: 586 | - frontend 587 | tty: true 588 | samba202: 589 | build: ./samba 590 | networks: 591 | - frontend 592 | tty: true 593 | samba203: 594 | build: ./samba 595 | networks: 596 | - frontend 597 | tty: true 598 | samba204: 599 | build: ./samba 600 | networks: 601 | - frontend 602 | tty: true 603 | samba205: 604 | build: ./samba 605 | networks: 606 | - frontend 607 | tty: true 608 | samba206: 609 | build: ./samba 610 | networks: 611 | - frontend 612 | tty: true 613 | samba207: 614 | build: ./samba 615 | networks: 616 | - frontend 617 | tty: true 618 | samba208: 619 | build: ./samba 620 | networks: 621 | - frontend 622 | tty: true 623 | samba209: 624 | build: ./samba 625 | networks: 626 | - frontend 627 | tty: true 628 | samba21: 629 | build: ./samba 630 | networks: 631 | - frontend 632 | tty: true 633 | samba210: 634 | build: ./samba 635 | networks: 636 | - frontend 637 | tty: true 638 | samba211: 639 | build: ./samba 640 | networks: 641 | - frontend 642 | tty: true 643 | samba212: 644 | build: ./samba 645 | networks: 646 | - frontend 647 | tty: true 648 | samba213: 649 | build: ./samba 650 | networks: 651 | - frontend 652 | tty: true 653 | samba214: 654 | build: ./samba 655 | networks: 656 | - frontend 657 | tty: true 658 | samba215: 659 | build: ./samba 660 | networks: 661 | - frontend 662 | tty: true 663 | samba216: 664 | build: ./samba 665 | networks: 666 | - frontend 667 | tty: true 668 | samba217: 669 | build: ./samba 670 | networks: 671 | - frontend 672 | tty: true 673 | samba218: 674 | build: ./samba 675 | networks: 676 | - frontend 677 | tty: true 678 | samba219: 679 | build: ./samba 680 | networks: 681 | - frontend 682 | tty: true 683 | samba22: 684 | build: ./samba 685 | networks: 686 | - frontend 687 | tty: true 688 | samba220: 689 | build: ./samba 690 | networks: 691 | - frontend 692 | tty: true 693 | samba221: 694 | build: ./samba 695 | networks: 696 | - frontend 697 | tty: true 698 | samba222: 699 | build: ./samba 700 | networks: 701 | - frontend 702 | tty: true 703 | samba223: 704 | build: ./samba 705 | networks: 706 | - frontend 707 | tty: true 708 | samba224: 709 | build: ./samba 710 | networks: 711 | - frontend 712 | tty: true 713 | samba225: 714 | build: ./samba 715 | networks: 716 | - frontend 717 | tty: true 718 | samba226: 719 | build: ./samba 720 | networks: 721 | - frontend 722 | tty: true 723 | samba227: 724 | build: ./samba 725 | networks: 726 | - frontend 727 | tty: true 728 | samba228: 729 | build: ./samba 730 | networks: 731 | - frontend 732 | tty: true 733 | samba229: 734 | build: ./samba 735 | networks: 736 | - frontend 737 | tty: true 738 | samba23: 739 | build: ./samba 740 | networks: 741 | - frontend 742 | tty: true 743 | samba230: 744 | build: ./samba 745 | networks: 746 | - frontend 747 | tty: true 748 | samba231: 749 | build: ./samba 750 | networks: 751 | - frontend 752 | tty: true 753 | samba232: 754 | build: ./samba 755 | networks: 756 | - frontend 757 | tty: true 758 | samba233: 759 | build: ./samba 760 | networks: 761 | - frontend 762 | tty: true 763 | samba234: 764 | build: ./samba 765 | networks: 766 | - frontend 767 | tty: true 768 | samba235: 769 | build: ./samba 770 | networks: 771 | - frontend 772 | tty: true 773 | samba236: 774 | build: ./samba 775 | networks: 776 | - frontend 777 | tty: true 778 | samba237: 779 | build: ./samba 780 | networks: 781 | - frontend 782 | tty: true 783 | samba238: 784 | build: ./samba 785 | networks: 786 | - frontend 787 | tty: true 788 | samba239: 789 | build: ./samba 790 | networks: 791 | - frontend 792 | tty: true 793 | samba24: 794 | build: ./samba 795 | networks: 796 | - frontend 797 | tty: true 798 | samba240: 799 | build: ./samba 800 | networks: 801 | - frontend 802 | tty: true 803 | samba241: 804 | build: ./samba 805 | networks: 806 | - frontend 807 | tty: true 808 | samba242: 809 | build: ./samba 810 | networks: 811 | - frontend 812 | tty: true 813 | samba243: 814 | build: ./samba 815 | networks: 816 | - frontend 817 | tty: true 818 | samba244: 819 | build: ./samba 820 | networks: 821 | - frontend 822 | tty: true 823 | samba245: 824 | build: ./samba 825 | networks: 826 | - frontend 827 | tty: true 828 | samba246: 829 | build: ./samba 830 | networks: 831 | - frontend 832 | tty: true 833 | samba247: 834 | build: ./samba 835 | networks: 836 | - frontend 837 | tty: true 838 | samba248: 839 | build: ./samba 840 | networks: 841 | - frontend 842 | tty: true 843 | samba249: 844 | build: ./samba 845 | networks: 846 | - frontend 847 | tty: true 848 | samba25: 849 | build: ./samba 850 | networks: 851 | - frontend 852 | tty: true 853 | samba250: 854 | build: ./samba 855 | networks: 856 | - frontend 857 | tty: true 858 | samba251: 859 | build: ./samba 860 | networks: 861 | - frontend 862 | tty: true 863 | samba252: 864 | build: ./samba 865 | networks: 866 | - frontend 867 | tty: true 868 | samba253: 869 | build: ./samba 870 | networks: 871 | - frontend 872 | tty: true 873 | samba254: 874 | build: ./samba 875 | networks: 876 | - frontend 877 | tty: true 878 | samba255: 879 | build: ./samba 880 | networks: 881 | - frontend 882 | tty: true 883 | samba256: 884 | build: ./samba 885 | networks: 886 | - frontend 887 | tty: true 888 | samba257: 889 | build: ./samba 890 | networks: 891 | - frontend 892 | tty: true 893 | samba258: 894 | build: ./samba 895 | networks: 896 | - frontend 897 | tty: true 898 | samba259: 899 | build: ./samba 900 | networks: 901 | - frontend 902 | tty: true 903 | samba26: 904 | build: ./samba 905 | networks: 906 | - frontend 907 | tty: true 908 | samba260: 909 | build: ./samba 910 | networks: 911 | - frontend 912 | tty: true 913 | samba261: 914 | build: ./samba 915 | networks: 916 | - frontend 917 | tty: true 918 | samba262: 919 | build: ./samba 920 | networks: 921 | - frontend 922 | tty: true 923 | samba263: 924 | build: ./samba 925 | networks: 926 | - frontend 927 | tty: true 928 | samba264: 929 | build: ./samba 930 | networks: 931 | - frontend 932 | tty: true 933 | samba265: 934 | build: ./samba 935 | networks: 936 | - frontend 937 | tty: true 938 | samba266: 939 | build: ./samba 940 | networks: 941 | - frontend 942 | tty: true 943 | samba267: 944 | build: ./samba 945 | networks: 946 | - frontend 947 | tty: true 948 | samba268: 949 | build: ./samba 950 | networks: 951 | - frontend 952 | tty: true 953 | samba269: 954 | build: ./samba 955 | networks: 956 | - frontend 957 | tty: true 958 | samba27: 959 | build: ./samba 960 | networks: 961 | - frontend 962 | tty: true 963 | samba270: 964 | build: ./samba 965 | networks: 966 | - frontend 967 | tty: true 968 | samba271: 969 | build: ./samba 970 | networks: 971 | - frontend 972 | tty: true 973 | samba272: 974 | build: ./samba 975 | networks: 976 | - frontend 977 | tty: true 978 | samba273: 979 | build: ./samba 980 | networks: 981 | - frontend 982 | tty: true 983 | samba274: 984 | build: ./samba 985 | networks: 986 | - frontend 987 | tty: true 988 | samba275: 989 | build: ./samba 990 | networks: 991 | - frontend 992 | tty: true 993 | samba276: 994 | build: ./samba 995 | networks: 996 | - frontend 997 | tty: true 998 | samba277: 999 | build: ./samba 1000 | networks: 1001 | - frontend 1002 | tty: true 1003 | samba278: 1004 | build: ./samba 1005 | networks: 1006 | - frontend 1007 | tty: true 1008 | samba279: 1009 | build: ./samba 1010 | networks: 1011 | - frontend 1012 | tty: true 1013 | samba28: 1014 | build: ./samba 1015 | networks: 1016 | - frontend 1017 | tty: true 1018 | samba280: 1019 | build: ./samba 1020 | networks: 1021 | - frontend 1022 | tty: true 1023 | samba281: 1024 | build: ./samba 1025 | networks: 1026 | - frontend 1027 | tty: true 1028 | samba282: 1029 | build: ./samba 1030 | networks: 1031 | - frontend 1032 | tty: true 1033 | samba283: 1034 | build: ./samba 1035 | networks: 1036 | - frontend 1037 | tty: true 1038 | samba284: 1039 | build: ./samba 1040 | networks: 1041 | - frontend 1042 | tty: true 1043 | samba285: 1044 | build: ./samba 1045 | networks: 1046 | - frontend 1047 | tty: true 1048 | samba286: 1049 | build: ./samba 1050 | networks: 1051 | - frontend 1052 | tty: true 1053 | samba287: 1054 | build: ./samba 1055 | networks: 1056 | - frontend 1057 | tty: true 1058 | samba288: 1059 | build: ./samba 1060 | networks: 1061 | - frontend 1062 | tty: true 1063 | samba289: 1064 | build: ./samba 1065 | networks: 1066 | - frontend 1067 | tty: true 1068 | samba29: 1069 | build: ./samba 1070 | networks: 1071 | - frontend 1072 | tty: true 1073 | samba290: 1074 | build: ./samba 1075 | networks: 1076 | - frontend 1077 | tty: true 1078 | samba291: 1079 | build: ./samba 1080 | networks: 1081 | - frontend 1082 | tty: true 1083 | samba292: 1084 | build: ./samba 1085 | networks: 1086 | - frontend 1087 | tty: true 1088 | samba293: 1089 | build: ./samba 1090 | networks: 1091 | - frontend 1092 | tty: true 1093 | samba294: 1094 | build: ./samba 1095 | networks: 1096 | - frontend 1097 | tty: true 1098 | samba295: 1099 | build: ./samba 1100 | networks: 1101 | - frontend 1102 | tty: true 1103 | samba296: 1104 | build: ./samba 1105 | networks: 1106 | - frontend 1107 | tty: true 1108 | samba297: 1109 | build: ./samba 1110 | networks: 1111 | - frontend 1112 | tty: true 1113 | samba298: 1114 | build: ./samba 1115 | networks: 1116 | - frontend 1117 | tty: true 1118 | samba299: 1119 | build: ./samba 1120 | networks: 1121 | - frontend 1122 | tty: true 1123 | samba3: 1124 | build: ./samba 1125 | networks: 1126 | - frontend 1127 | tty: true 1128 | samba30: 1129 | build: ./samba 1130 | networks: 1131 | - frontend 1132 | tty: true 1133 | samba300: 1134 | build: ./samba 1135 | networks: 1136 | - frontend 1137 | tty: true 1138 | samba301: 1139 | build: ./samba 1140 | networks: 1141 | - frontend 1142 | tty: true 1143 | samba302: 1144 | build: ./samba 1145 | networks: 1146 | - frontend 1147 | tty: true 1148 | samba303: 1149 | build: ./samba 1150 | networks: 1151 | - frontend 1152 | tty: true 1153 | samba304: 1154 | build: ./samba 1155 | networks: 1156 | - frontend 1157 | tty: true 1158 | samba305: 1159 | build: ./samba 1160 | networks: 1161 | - frontend 1162 | tty: true 1163 | samba306: 1164 | build: ./samba 1165 | networks: 1166 | - frontend 1167 | tty: true 1168 | samba307: 1169 | build: ./samba 1170 | networks: 1171 | - frontend 1172 | tty: true 1173 | samba308: 1174 | build: ./samba 1175 | networks: 1176 | - frontend 1177 | tty: true 1178 | samba309: 1179 | build: ./samba 1180 | networks: 1181 | - frontend 1182 | tty: true 1183 | samba31: 1184 | build: ./samba 1185 | networks: 1186 | - frontend 1187 | tty: true 1188 | samba310: 1189 | build: ./samba 1190 | networks: 1191 | - frontend 1192 | tty: true 1193 | samba311: 1194 | build: ./samba 1195 | networks: 1196 | - frontend 1197 | tty: true 1198 | samba312: 1199 | build: ./samba 1200 | networks: 1201 | - frontend 1202 | tty: true 1203 | samba313: 1204 | build: ./samba 1205 | networks: 1206 | - frontend 1207 | tty: true 1208 | samba314: 1209 | build: ./samba 1210 | networks: 1211 | - frontend 1212 | tty: true 1213 | samba315: 1214 | build: ./samba 1215 | networks: 1216 | - frontend 1217 | tty: true 1218 | samba316: 1219 | build: ./samba 1220 | networks: 1221 | - frontend 1222 | tty: true 1223 | samba317: 1224 | build: ./samba 1225 | networks: 1226 | - frontend 1227 | tty: true 1228 | samba318: 1229 | build: ./samba 1230 | networks: 1231 | - frontend 1232 | tty: true 1233 | samba319: 1234 | build: ./samba 1235 | networks: 1236 | - frontend 1237 | tty: true 1238 | samba32: 1239 | build: ./samba 1240 | networks: 1241 | - frontend 1242 | tty: true 1243 | samba320: 1244 | build: ./samba 1245 | networks: 1246 | - frontend 1247 | tty: true 1248 | samba321: 1249 | build: ./samba 1250 | networks: 1251 | - frontend 1252 | tty: true 1253 | samba322: 1254 | build: ./samba 1255 | networks: 1256 | - frontend 1257 | tty: true 1258 | samba323: 1259 | build: ./samba 1260 | networks: 1261 | - frontend 1262 | tty: true 1263 | samba324: 1264 | build: ./samba 1265 | networks: 1266 | - frontend 1267 | tty: true 1268 | samba325: 1269 | build: ./samba 1270 | networks: 1271 | - frontend 1272 | tty: true 1273 | samba326: 1274 | build: ./samba 1275 | networks: 1276 | - frontend 1277 | tty: true 1278 | samba327: 1279 | build: ./samba 1280 | networks: 1281 | - frontend 1282 | tty: true 1283 | samba328: 1284 | build: ./samba 1285 | networks: 1286 | - frontend 1287 | tty: true 1288 | samba329: 1289 | build: ./samba 1290 | networks: 1291 | - frontend 1292 | tty: true 1293 | samba33: 1294 | build: ./samba 1295 | networks: 1296 | - frontend 1297 | tty: true 1298 | samba330: 1299 | build: ./samba 1300 | networks: 1301 | - frontend 1302 | tty: true 1303 | samba331: 1304 | build: ./samba 1305 | networks: 1306 | - frontend 1307 | tty: true 1308 | samba332: 1309 | build: ./samba 1310 | networks: 1311 | - frontend 1312 | tty: true 1313 | samba333: 1314 | build: ./samba 1315 | networks: 1316 | - frontend 1317 | tty: true 1318 | samba334: 1319 | build: ./samba 1320 | networks: 1321 | - frontend 1322 | tty: true 1323 | samba335: 1324 | build: ./samba 1325 | networks: 1326 | - frontend 1327 | tty: true 1328 | samba336: 1329 | build: ./samba 1330 | networks: 1331 | - frontend 1332 | tty: true 1333 | samba337: 1334 | build: ./samba 1335 | networks: 1336 | - frontend 1337 | tty: true 1338 | samba338: 1339 | build: ./samba 1340 | networks: 1341 | - frontend 1342 | tty: true 1343 | samba339: 1344 | build: ./samba 1345 | networks: 1346 | - frontend 1347 | tty: true 1348 | samba34: 1349 | build: ./samba 1350 | networks: 1351 | - frontend 1352 | tty: true 1353 | samba340: 1354 | build: ./samba 1355 | networks: 1356 | - frontend 1357 | tty: true 1358 | samba341: 1359 | build: ./samba 1360 | networks: 1361 | - frontend 1362 | tty: true 1363 | samba342: 1364 | build: ./samba 1365 | networks: 1366 | - frontend 1367 | tty: true 1368 | samba343: 1369 | build: ./samba 1370 | networks: 1371 | - frontend 1372 | tty: true 1373 | samba344: 1374 | build: ./samba 1375 | networks: 1376 | - frontend 1377 | tty: true 1378 | samba345: 1379 | build: ./samba 1380 | networks: 1381 | - frontend 1382 | tty: true 1383 | samba346: 1384 | build: ./samba 1385 | networks: 1386 | - frontend 1387 | tty: true 1388 | samba347: 1389 | build: ./samba 1390 | networks: 1391 | - frontend 1392 | tty: true 1393 | samba348: 1394 | build: ./samba 1395 | networks: 1396 | - frontend 1397 | tty: true 1398 | samba349: 1399 | build: ./samba 1400 | networks: 1401 | - frontend 1402 | tty: true 1403 | samba35: 1404 | build: ./samba 1405 | networks: 1406 | - frontend 1407 | tty: true 1408 | samba350: 1409 | build: ./samba 1410 | networks: 1411 | - frontend 1412 | tty: true 1413 | samba351: 1414 | build: ./samba 1415 | networks: 1416 | - frontend 1417 | tty: true 1418 | samba352: 1419 | build: ./samba 1420 | networks: 1421 | - frontend 1422 | tty: true 1423 | samba353: 1424 | build: ./samba 1425 | networks: 1426 | - frontend 1427 | tty: true 1428 | samba354: 1429 | build: ./samba 1430 | networks: 1431 | - frontend 1432 | tty: true 1433 | samba355: 1434 | build: ./samba 1435 | networks: 1436 | - frontend 1437 | tty: true 1438 | samba356: 1439 | build: ./samba 1440 | networks: 1441 | - frontend 1442 | tty: true 1443 | samba357: 1444 | build: ./samba 1445 | networks: 1446 | - frontend 1447 | tty: true 1448 | samba358: 1449 | build: ./samba 1450 | networks: 1451 | - frontend 1452 | tty: true 1453 | samba359: 1454 | build: ./samba 1455 | networks: 1456 | - frontend 1457 | tty: true 1458 | samba36: 1459 | build: ./samba 1460 | networks: 1461 | - frontend 1462 | tty: true 1463 | samba360: 1464 | build: ./samba 1465 | networks: 1466 | - frontend 1467 | tty: true 1468 | samba361: 1469 | build: ./samba 1470 | networks: 1471 | - frontend 1472 | tty: true 1473 | samba362: 1474 | build: ./samba 1475 | networks: 1476 | - frontend 1477 | tty: true 1478 | samba363: 1479 | build: ./samba 1480 | networks: 1481 | - frontend 1482 | tty: true 1483 | samba364: 1484 | build: ./samba 1485 | networks: 1486 | - frontend 1487 | tty: true 1488 | samba365: 1489 | build: ./samba 1490 | networks: 1491 | - frontend 1492 | tty: true 1493 | samba366: 1494 | build: ./samba 1495 | networks: 1496 | - frontend 1497 | tty: true 1498 | samba367: 1499 | build: ./samba 1500 | networks: 1501 | - frontend 1502 | tty: true 1503 | samba368: 1504 | build: ./samba 1505 | networks: 1506 | - frontend 1507 | tty: true 1508 | samba369: 1509 | build: ./samba 1510 | networks: 1511 | - frontend 1512 | tty: true 1513 | samba37: 1514 | build: ./samba 1515 | networks: 1516 | - frontend 1517 | tty: true 1518 | samba370: 1519 | build: ./samba 1520 | networks: 1521 | - frontend 1522 | tty: true 1523 | samba371: 1524 | build: ./samba 1525 | networks: 1526 | - frontend 1527 | tty: true 1528 | samba372: 1529 | build: ./samba 1530 | networks: 1531 | - frontend 1532 | tty: true 1533 | samba373: 1534 | build: ./samba 1535 | networks: 1536 | - frontend 1537 | tty: true 1538 | samba374: 1539 | build: ./samba 1540 | networks: 1541 | - frontend 1542 | tty: true 1543 | samba375: 1544 | build: ./samba 1545 | networks: 1546 | - frontend 1547 | tty: true 1548 | samba376: 1549 | build: ./samba 1550 | networks: 1551 | - frontend 1552 | tty: true 1553 | samba377: 1554 | build: ./samba 1555 | networks: 1556 | - frontend 1557 | tty: true 1558 | samba378: 1559 | build: ./samba 1560 | networks: 1561 | - frontend 1562 | tty: true 1563 | samba379: 1564 | build: ./samba 1565 | networks: 1566 | - frontend 1567 | tty: true 1568 | samba38: 1569 | build: ./samba 1570 | networks: 1571 | - frontend 1572 | tty: true 1573 | samba380: 1574 | build: ./samba 1575 | networks: 1576 | - frontend 1577 | tty: true 1578 | samba381: 1579 | build: ./samba 1580 | networks: 1581 | - frontend 1582 | tty: true 1583 | samba382: 1584 | build: ./samba 1585 | networks: 1586 | - frontend 1587 | tty: true 1588 | samba383: 1589 | build: ./samba 1590 | networks: 1591 | - frontend 1592 | tty: true 1593 | samba384: 1594 | build: ./samba 1595 | networks: 1596 | - frontend 1597 | tty: true 1598 | samba385: 1599 | build: ./samba 1600 | networks: 1601 | - frontend 1602 | tty: true 1603 | samba386: 1604 | build: ./samba 1605 | networks: 1606 | - frontend 1607 | tty: true 1608 | samba387: 1609 | build: ./samba 1610 | networks: 1611 | - frontend 1612 | tty: true 1613 | samba388: 1614 | build: ./samba 1615 | networks: 1616 | - frontend 1617 | tty: true 1618 | samba389: 1619 | build: ./samba 1620 | networks: 1621 | - frontend 1622 | tty: true 1623 | samba39: 1624 | build: ./samba 1625 | networks: 1626 | - frontend 1627 | tty: true 1628 | samba390: 1629 | build: ./samba 1630 | networks: 1631 | - frontend 1632 | tty: true 1633 | samba391: 1634 | build: ./samba 1635 | networks: 1636 | - frontend 1637 | tty: true 1638 | samba392: 1639 | build: ./samba 1640 | networks: 1641 | - frontend 1642 | tty: true 1643 | samba393: 1644 | build: ./samba 1645 | networks: 1646 | - frontend 1647 | tty: true 1648 | samba394: 1649 | build: ./samba 1650 | networks: 1651 | - frontend 1652 | tty: true 1653 | samba395: 1654 | build: ./samba 1655 | networks: 1656 | - frontend 1657 | tty: true 1658 | samba396: 1659 | build: ./samba 1660 | networks: 1661 | - frontend 1662 | tty: true 1663 | samba397: 1664 | build: ./samba 1665 | networks: 1666 | - frontend 1667 | tty: true 1668 | samba398: 1669 | build: ./samba 1670 | networks: 1671 | - frontend 1672 | tty: true 1673 | samba399: 1674 | build: ./samba 1675 | networks: 1676 | - frontend 1677 | tty: true 1678 | samba4: 1679 | build: ./samba 1680 | networks: 1681 | - frontend 1682 | tty: true 1683 | samba40: 1684 | build: ./samba 1685 | networks: 1686 | - frontend 1687 | tty: true 1688 | samba400: 1689 | build: ./samba 1690 | networks: 1691 | - frontend 1692 | tty: true 1693 | samba401: 1694 | build: ./samba 1695 | networks: 1696 | - frontend 1697 | tty: true 1698 | samba402: 1699 | build: ./samba 1700 | networks: 1701 | - frontend 1702 | tty: true 1703 | samba403: 1704 | build: ./samba 1705 | networks: 1706 | - frontend 1707 | tty: true 1708 | samba404: 1709 | build: ./samba 1710 | networks: 1711 | - frontend 1712 | tty: true 1713 | samba405: 1714 | build: ./samba 1715 | networks: 1716 | - frontend 1717 | tty: true 1718 | samba406: 1719 | build: ./samba 1720 | networks: 1721 | - frontend 1722 | tty: true 1723 | samba407: 1724 | build: ./samba 1725 | networks: 1726 | - frontend 1727 | tty: true 1728 | samba408: 1729 | build: ./samba 1730 | networks: 1731 | - frontend 1732 | tty: true 1733 | samba409: 1734 | build: ./samba 1735 | networks: 1736 | - frontend 1737 | tty: true 1738 | samba41: 1739 | build: ./samba 1740 | networks: 1741 | - frontend 1742 | tty: true 1743 | samba410: 1744 | build: ./samba 1745 | networks: 1746 | - frontend 1747 | tty: true 1748 | samba411: 1749 | build: ./samba 1750 | networks: 1751 | - frontend 1752 | tty: true 1753 | samba412: 1754 | build: ./samba 1755 | networks: 1756 | - frontend 1757 | tty: true 1758 | samba413: 1759 | build: ./samba 1760 | networks: 1761 | - frontend 1762 | tty: true 1763 | samba414: 1764 | build: ./samba 1765 | networks: 1766 | - frontend 1767 | tty: true 1768 | samba415: 1769 | build: ./samba 1770 | networks: 1771 | - frontend 1772 | tty: true 1773 | samba416: 1774 | build: ./samba 1775 | networks: 1776 | - frontend 1777 | tty: true 1778 | samba417: 1779 | build: ./samba 1780 | networks: 1781 | - frontend 1782 | tty: true 1783 | samba418: 1784 | build: ./samba 1785 | networks: 1786 | - frontend 1787 | tty: true 1788 | samba419: 1789 | build: ./samba 1790 | networks: 1791 | - frontend 1792 | tty: true 1793 | samba42: 1794 | build: ./samba 1795 | networks: 1796 | - frontend 1797 | tty: true 1798 | samba420: 1799 | build: ./samba 1800 | networks: 1801 | - frontend 1802 | tty: true 1803 | samba421: 1804 | build: ./samba 1805 | networks: 1806 | - frontend 1807 | tty: true 1808 | samba422: 1809 | build: ./samba 1810 | networks: 1811 | - frontend 1812 | tty: true 1813 | samba423: 1814 | build: ./samba 1815 | networks: 1816 | - frontend 1817 | tty: true 1818 | samba424: 1819 | build: ./samba 1820 | networks: 1821 | - frontend 1822 | tty: true 1823 | samba425: 1824 | build: ./samba 1825 | networks: 1826 | - frontend 1827 | tty: true 1828 | samba426: 1829 | build: ./samba 1830 | networks: 1831 | - frontend 1832 | tty: true 1833 | samba427: 1834 | build: ./samba 1835 | networks: 1836 | - frontend 1837 | tty: true 1838 | samba428: 1839 | build: ./samba 1840 | networks: 1841 | - frontend 1842 | tty: true 1843 | samba429: 1844 | build: ./samba 1845 | networks: 1846 | - frontend 1847 | tty: true 1848 | samba43: 1849 | build: ./samba 1850 | networks: 1851 | - frontend 1852 | tty: true 1853 | samba430: 1854 | build: ./samba 1855 | networks: 1856 | - frontend 1857 | tty: true 1858 | samba431: 1859 | build: ./samba 1860 | networks: 1861 | - frontend 1862 | tty: true 1863 | samba432: 1864 | build: ./samba 1865 | networks: 1866 | - frontend 1867 | tty: true 1868 | samba433: 1869 | build: ./samba 1870 | networks: 1871 | - frontend 1872 | tty: true 1873 | samba434: 1874 | build: ./samba 1875 | networks: 1876 | - frontend 1877 | tty: true 1878 | samba435: 1879 | build: ./samba 1880 | networks: 1881 | - frontend 1882 | tty: true 1883 | samba436: 1884 | build: ./samba 1885 | networks: 1886 | - frontend 1887 | tty: true 1888 | samba437: 1889 | build: ./samba 1890 | networks: 1891 | - frontend 1892 | tty: true 1893 | samba438: 1894 | build: ./samba 1895 | networks: 1896 | - frontend 1897 | tty: true 1898 | samba439: 1899 | build: ./samba 1900 | networks: 1901 | - frontend 1902 | tty: true 1903 | samba44: 1904 | build: ./samba 1905 | networks: 1906 | - frontend 1907 | tty: true 1908 | samba440: 1909 | build: ./samba 1910 | networks: 1911 | - frontend 1912 | tty: true 1913 | samba441: 1914 | build: ./samba 1915 | networks: 1916 | - frontend 1917 | tty: true 1918 | samba442: 1919 | build: ./samba 1920 | networks: 1921 | - frontend 1922 | tty: true 1923 | samba443: 1924 | build: ./samba 1925 | networks: 1926 | - frontend 1927 | tty: true 1928 | samba444: 1929 | build: ./samba 1930 | networks: 1931 | - frontend 1932 | tty: true 1933 | samba445: 1934 | build: ./samba 1935 | networks: 1936 | - frontend 1937 | tty: true 1938 | samba446: 1939 | build: ./samba 1940 | networks: 1941 | - frontend 1942 | tty: true 1943 | samba447: 1944 | build: ./samba 1945 | networks: 1946 | - frontend 1947 | tty: true 1948 | samba448: 1949 | build: ./samba 1950 | networks: 1951 | - frontend 1952 | tty: true 1953 | samba449: 1954 | build: ./samba 1955 | networks: 1956 | - frontend 1957 | tty: true 1958 | samba45: 1959 | build: ./samba 1960 | networks: 1961 | - frontend 1962 | tty: true 1963 | samba450: 1964 | build: ./samba 1965 | networks: 1966 | - frontend 1967 | tty: true 1968 | samba451: 1969 | build: ./samba 1970 | networks: 1971 | - frontend 1972 | tty: true 1973 | samba452: 1974 | build: ./samba 1975 | networks: 1976 | - frontend 1977 | tty: true 1978 | samba453: 1979 | build: ./samba 1980 | networks: 1981 | - frontend 1982 | tty: true 1983 | samba454: 1984 | build: ./samba 1985 | networks: 1986 | - frontend 1987 | tty: true 1988 | samba455: 1989 | build: ./samba 1990 | networks: 1991 | - frontend 1992 | tty: true 1993 | samba456: 1994 | build: ./samba 1995 | networks: 1996 | - frontend 1997 | tty: true 1998 | samba457: 1999 | build: ./samba 2000 | networks: 2001 | - frontend 2002 | tty: true 2003 | samba458: 2004 | build: ./samba 2005 | networks: 2006 | - frontend 2007 | tty: true 2008 | samba459: 2009 | build: ./samba 2010 | networks: 2011 | - frontend 2012 | tty: true 2013 | samba46: 2014 | build: ./samba 2015 | networks: 2016 | - frontend 2017 | tty: true 2018 | samba460: 2019 | build: ./samba 2020 | networks: 2021 | - frontend 2022 | tty: true 2023 | samba461: 2024 | build: ./samba 2025 | networks: 2026 | - frontend 2027 | tty: true 2028 | samba462: 2029 | build: ./samba 2030 | networks: 2031 | - frontend 2032 | tty: true 2033 | samba463: 2034 | build: ./samba 2035 | networks: 2036 | - frontend 2037 | tty: true 2038 | samba464: 2039 | build: ./samba 2040 | networks: 2041 | - frontend 2042 | tty: true 2043 | samba465: 2044 | build: ./samba 2045 | networks: 2046 | - frontend 2047 | tty: true 2048 | samba466: 2049 | build: ./samba 2050 | networks: 2051 | - frontend 2052 | tty: true 2053 | samba467: 2054 | build: ./samba 2055 | networks: 2056 | - frontend 2057 | tty: true 2058 | samba468: 2059 | build: ./samba 2060 | networks: 2061 | - frontend 2062 | tty: true 2063 | samba469: 2064 | build: ./samba 2065 | networks: 2066 | - frontend 2067 | tty: true 2068 | samba47: 2069 | build: ./samba 2070 | networks: 2071 | - frontend 2072 | tty: true 2073 | samba470: 2074 | build: ./samba 2075 | networks: 2076 | - frontend 2077 | tty: true 2078 | samba471: 2079 | build: ./samba 2080 | networks: 2081 | - frontend 2082 | tty: true 2083 | samba472: 2084 | build: ./samba 2085 | networks: 2086 | - frontend 2087 | tty: true 2088 | samba473: 2089 | build: ./samba 2090 | networks: 2091 | - frontend 2092 | tty: true 2093 | samba474: 2094 | build: ./samba 2095 | networks: 2096 | - frontend 2097 | tty: true 2098 | samba475: 2099 | build: ./samba 2100 | networks: 2101 | - frontend 2102 | tty: true 2103 | samba476: 2104 | build: ./samba 2105 | networks: 2106 | - frontend 2107 | tty: true 2108 | samba477: 2109 | build: ./samba 2110 | networks: 2111 | - frontend 2112 | tty: true 2113 | samba478: 2114 | build: ./samba 2115 | networks: 2116 | - frontend 2117 | tty: true 2118 | samba479: 2119 | build: ./samba 2120 | networks: 2121 | - frontend 2122 | tty: true 2123 | samba48: 2124 | build: ./samba 2125 | networks: 2126 | - frontend 2127 | tty: true 2128 | samba480: 2129 | build: ./samba 2130 | networks: 2131 | - frontend 2132 | tty: true 2133 | samba481: 2134 | build: ./samba 2135 | networks: 2136 | - frontend 2137 | tty: true 2138 | samba482: 2139 | build: ./samba 2140 | networks: 2141 | - frontend 2142 | tty: true 2143 | samba483: 2144 | build: ./samba 2145 | networks: 2146 | - frontend 2147 | tty: true 2148 | samba484: 2149 | build: ./samba 2150 | networks: 2151 | - frontend 2152 | tty: true 2153 | samba485: 2154 | build: ./samba 2155 | networks: 2156 | - frontend 2157 | tty: true 2158 | samba486: 2159 | build: ./samba 2160 | networks: 2161 | - frontend 2162 | tty: true 2163 | samba487: 2164 | build: ./samba 2165 | networks: 2166 | - frontend 2167 | tty: true 2168 | samba488: 2169 | build: ./samba 2170 | networks: 2171 | - frontend 2172 | tty: true 2173 | samba489: 2174 | build: ./samba 2175 | networks: 2176 | - frontend 2177 | tty: true 2178 | samba49: 2179 | build: ./samba 2180 | networks: 2181 | - frontend 2182 | tty: true 2183 | samba490: 2184 | build: ./samba 2185 | networks: 2186 | - frontend 2187 | tty: true 2188 | samba491: 2189 | build: ./samba 2190 | networks: 2191 | - frontend 2192 | tty: true 2193 | samba492: 2194 | build: ./samba 2195 | networks: 2196 | - frontend 2197 | tty: true 2198 | samba493: 2199 | build: ./samba 2200 | networks: 2201 | - frontend 2202 | tty: true 2203 | samba494: 2204 | build: ./samba 2205 | networks: 2206 | - frontend 2207 | tty: true 2208 | samba495: 2209 | build: ./samba 2210 | networks: 2211 | - frontend 2212 | tty: true 2213 | samba496: 2214 | build: ./samba 2215 | networks: 2216 | - frontend 2217 | tty: true 2218 | samba497: 2219 | build: ./samba 2220 | networks: 2221 | - frontend 2222 | tty: true 2223 | samba498: 2224 | build: ./samba 2225 | networks: 2226 | - frontend 2227 | tty: true 2228 | samba499: 2229 | build: ./samba 2230 | networks: 2231 | - frontend 2232 | tty: true 2233 | samba5: 2234 | build: ./samba 2235 | networks: 2236 | - frontend 2237 | tty: true 2238 | samba50: 2239 | build: ./samba 2240 | networks: 2241 | - frontend 2242 | tty: true 2243 | samba500: 2244 | build: ./samba 2245 | networks: 2246 | - frontend 2247 | tty: true 2248 | samba51: 2249 | build: ./samba 2250 | networks: 2251 | - frontend 2252 | tty: true 2253 | samba52: 2254 | build: ./samba 2255 | networks: 2256 | - frontend 2257 | tty: true 2258 | samba53: 2259 | build: ./samba 2260 | networks: 2261 | - frontend 2262 | tty: true 2263 | samba54: 2264 | build: ./samba 2265 | networks: 2266 | - frontend 2267 | tty: true 2268 | samba55: 2269 | build: ./samba 2270 | networks: 2271 | - frontend 2272 | tty: true 2273 | samba56: 2274 | build: ./samba 2275 | networks: 2276 | - frontend 2277 | tty: true 2278 | samba57: 2279 | build: ./samba 2280 | networks: 2281 | - frontend 2282 | tty: true 2283 | samba58: 2284 | build: ./samba 2285 | networks: 2286 | - frontend 2287 | tty: true 2288 | samba59: 2289 | build: ./samba 2290 | networks: 2291 | - frontend 2292 | tty: true 2293 | samba6: 2294 | build: ./samba 2295 | networks: 2296 | - frontend 2297 | tty: true 2298 | samba60: 2299 | build: ./samba 2300 | networks: 2301 | - frontend 2302 | tty: true 2303 | samba61: 2304 | build: ./samba 2305 | networks: 2306 | - frontend 2307 | tty: true 2308 | samba62: 2309 | build: ./samba 2310 | networks: 2311 | - frontend 2312 | tty: true 2313 | samba63: 2314 | build: ./samba 2315 | networks: 2316 | - frontend 2317 | tty: true 2318 | samba64: 2319 | build: ./samba 2320 | networks: 2321 | - frontend 2322 | tty: true 2323 | samba65: 2324 | build: ./samba 2325 | networks: 2326 | - frontend 2327 | tty: true 2328 | samba66: 2329 | build: ./samba 2330 | networks: 2331 | - frontend 2332 | tty: true 2333 | samba67: 2334 | build: ./samba 2335 | networks: 2336 | - frontend 2337 | tty: true 2338 | samba68: 2339 | build: ./samba 2340 | networks: 2341 | - frontend 2342 | tty: true 2343 | samba69: 2344 | build: ./samba 2345 | networks: 2346 | - frontend 2347 | tty: true 2348 | samba7: 2349 | build: ./samba 2350 | networks: 2351 | - frontend 2352 | tty: true 2353 | samba70: 2354 | build: ./samba 2355 | networks: 2356 | - frontend 2357 | tty: true 2358 | samba71: 2359 | build: ./samba 2360 | networks: 2361 | - frontend 2362 | tty: true 2363 | samba72: 2364 | build: ./samba 2365 | networks: 2366 | - frontend 2367 | tty: true 2368 | samba73: 2369 | build: ./samba 2370 | networks: 2371 | - frontend 2372 | tty: true 2373 | samba74: 2374 | build: ./samba 2375 | networks: 2376 | - frontend 2377 | tty: true 2378 | samba75: 2379 | build: ./samba 2380 | networks: 2381 | - frontend 2382 | tty: true 2383 | samba76: 2384 | build: ./samba 2385 | networks: 2386 | - frontend 2387 | tty: true 2388 | samba77: 2389 | build: ./samba 2390 | networks: 2391 | - frontend 2392 | tty: true 2393 | samba78: 2394 | build: ./samba 2395 | networks: 2396 | - frontend 2397 | tty: true 2398 | samba79: 2399 | build: ./samba 2400 | networks: 2401 | - frontend 2402 | tty: true 2403 | samba8: 2404 | build: ./samba 2405 | networks: 2406 | - frontend 2407 | tty: true 2408 | samba80: 2409 | build: ./samba 2410 | networks: 2411 | - frontend 2412 | tty: true 2413 | samba81: 2414 | build: ./samba 2415 | networks: 2416 | - frontend 2417 | tty: true 2418 | samba82: 2419 | build: ./samba 2420 | networks: 2421 | - frontend 2422 | tty: true 2423 | samba83: 2424 | build: ./samba 2425 | networks: 2426 | - frontend 2427 | tty: true 2428 | samba84: 2429 | build: ./samba 2430 | networks: 2431 | - frontend 2432 | tty: true 2433 | samba85: 2434 | build: ./samba 2435 | networks: 2436 | - frontend 2437 | tty: true 2438 | samba86: 2439 | build: ./samba 2440 | networks: 2441 | - frontend 2442 | tty: true 2443 | samba87: 2444 | build: ./samba 2445 | networks: 2446 | - frontend 2447 | tty: true 2448 | samba88: 2449 | build: ./samba 2450 | networks: 2451 | - frontend 2452 | tty: true 2453 | samba89: 2454 | build: ./samba 2455 | networks: 2456 | - frontend 2457 | tty: true 2458 | samba9: 2459 | build: ./samba 2460 | networks: 2461 | - frontend 2462 | tty: true 2463 | samba90: 2464 | build: ./samba 2465 | networks: 2466 | - frontend 2467 | tty: true 2468 | samba91: 2469 | build: ./samba 2470 | networks: 2471 | - frontend 2472 | tty: true 2473 | samba92: 2474 | build: ./samba 2475 | networks: 2476 | - frontend 2477 | tty: true 2478 | samba93: 2479 | build: ./samba 2480 | networks: 2481 | - frontend 2482 | tty: true 2483 | samba94: 2484 | build: ./samba 2485 | networks: 2486 | - frontend 2487 | tty: true 2488 | samba95: 2489 | build: ./samba 2490 | networks: 2491 | - frontend 2492 | tty: true 2493 | samba96: 2494 | build: ./samba 2495 | networks: 2496 | - frontend 2497 | tty: true 2498 | samba97: 2499 | build: ./samba 2500 | networks: 2501 | - frontend 2502 | tty: true 2503 | samba98: 2504 | build: ./samba 2505 | networks: 2506 | - frontend 2507 | tty: true 2508 | samba99: 2509 | build: ./samba 2510 | networks: 2511 | - frontend 2512 | tty: true 2513 | version: '2' 2514 | -------------------------------------------------------------------------------- /System/test/500_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/500_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/500_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:038e86ebb16f35df7c9ed44d2a432c22a47fbf20e080dec602ae0aa96b5011cb 3 | size 5739414 4 | -------------------------------------------------------------------------------- /System/test/50_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba1: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | samba2: 16 | build: ./samba 17 | networks: 18 | - frontend 19 | tty: true 20 | samba3: 21 | build: ./samba 22 | networks: 23 | - frontend 24 | tty: true 25 | samba4: 26 | build: ./samba 27 | networks: 28 | - frontend 29 | tty: true 30 | samba5: 31 | build: ./samba 32 | networks: 33 | - frontend 34 | tty: true 35 | samba6: 36 | build: ./samba 37 | networks: 38 | - frontend 39 | tty: true 40 | samba7: 41 | build: ./samba 42 | networks: 43 | - frontend 44 | tty: true 45 | samba8: 46 | build: ./samba 47 | networks: 48 | - frontend 49 | tty: true 50 | samba9: 51 | build: ./samba 52 | networks: 53 | - frontend 54 | tty: true 55 | samba10: 56 | build: ./samba 57 | networks: 58 | - frontend 59 | tty: true 60 | samba11: 61 | build: ./samba 62 | networks: 63 | - frontend 64 | tty: true 65 | samba12: 66 | build: ./samba 67 | networks: 68 | - frontend 69 | tty: true 70 | samba13: 71 | build: ./samba 72 | networks: 73 | - frontend 74 | tty: true 75 | samba14: 76 | build: ./samba 77 | networks: 78 | - frontend 79 | tty: true 80 | samba15: 81 | build: ./samba 82 | networks: 83 | - frontend 84 | tty: true 85 | samba16: 86 | build: ./samba 87 | networks: 88 | - frontend 89 | tty: true 90 | samba17: 91 | build: ./samba 92 | networks: 93 | - frontend 94 | tty: true 95 | samba18: 96 | build: ./samba 97 | networks: 98 | - frontend 99 | tty: true 100 | samba19: 101 | build: ./samba 102 | networks: 103 | - frontend 104 | tty: true 105 | samba20: 106 | build: ./samba 107 | networks: 108 | - frontend 109 | tty: true 110 | samba21: 111 | build: ./samba 112 | networks: 113 | - frontend 114 | tty: true 115 | samba22: 116 | build: ./samba 117 | networks: 118 | - frontend 119 | tty: true 120 | samba23: 121 | build: ./samba 122 | networks: 123 | - frontend 124 | tty: true 125 | samba24: 126 | build: ./samba 127 | networks: 128 | - frontend 129 | tty: true 130 | samba25: 131 | build: ./samba 132 | networks: 133 | - frontend 134 | tty: true 135 | samba26: 136 | build: ./samba 137 | networks: 138 | - frontend 139 | tty: true 140 | samba27: 141 | build: ./samba 142 | networks: 143 | - frontend 144 | tty: true 145 | samba28: 146 | build: ./samba 147 | networks: 148 | - frontend 149 | tty: true 150 | samba29: 151 | build: ./samba 152 | networks: 153 | - frontend 154 | tty: true 155 | samba30: 156 | build: ./samba 157 | networks: 158 | - frontend 159 | tty: true 160 | samba31: 161 | build: ./samba 162 | networks: 163 | - frontend 164 | tty: true 165 | samba32: 166 | build: ./samba 167 | networks: 168 | - frontend 169 | tty: true 170 | samba33: 171 | build: ./samba 172 | networks: 173 | - frontend 174 | tty: true 175 | samba34: 176 | build: ./samba 177 | networks: 178 | - frontend 179 | tty: true 180 | samba35: 181 | build: ./samba 182 | networks: 183 | - frontend 184 | tty: true 185 | samba36: 186 | build: ./samba 187 | networks: 188 | - frontend 189 | tty: true 190 | samba37: 191 | build: ./samba 192 | networks: 193 | - frontend 194 | tty: true 195 | samba38: 196 | build: ./samba 197 | networks: 198 | - frontend 199 | tty: true 200 | samba39: 201 | build: ./samba 202 | networks: 203 | - frontend 204 | tty: true 205 | samba40: 206 | build: ./samba 207 | networks: 208 | - frontend 209 | tty: true 210 | samba41: 211 | build: ./samba 212 | networks: 213 | - frontend 214 | tty: true 215 | samba42: 216 | build: ./samba 217 | networks: 218 | - frontend 219 | tty: true 220 | samba43: 221 | build: ./samba 222 | networks: 223 | - frontend 224 | tty: true 225 | samba44: 226 | build: ./samba 227 | networks: 228 | - frontend 229 | tty: true 230 | samba45: 231 | build: ./samba 232 | networks: 233 | - frontend 234 | tty: true 235 | samba46: 236 | build: ./samba 237 | networks: 238 | - frontend 239 | tty: true 240 | samba47: 241 | build: ./samba 242 | networks: 243 | - frontend 244 | tty: true 245 | samba48: 246 | build: ./samba 247 | networks: 248 | - frontend 249 | tty: true 250 | samba49: 251 | build: ./samba 252 | networks: 253 | - frontend 254 | tty: true 255 | samba50: 256 | build: ./samba 257 | networks: 258 | - frontend 259 | tty: true 260 | networks: 261 | frontend: 262 | driver: bridge 263 | backend: 264 | driver: bridge 265 | -------------------------------------------------------------------------------- /System/test/50_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/50_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/50_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14a91c6f69c07e39f1e4f874151383baab7a0f4428506bdbac942fbaadcb81db 3 | size 56259 4 | -------------------------------------------------------------------------------- /System/test/50_example/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/test/50_example/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/test/5_example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | phpmailer: 4 | build: ./phpmailer 5 | networks: 6 | - frontend 7 | ports: 8 | - 80 9 | 10 | samba1: 11 | build: ./samba 12 | networks: 13 | - frontend 14 | tty: true 15 | samba2: 16 | build: ./samba 17 | networks: 18 | - frontend 19 | tty: true 20 | samba3: 21 | build: ./samba 22 | networks: 23 | - frontend 24 | tty: true 25 | samba4: 26 | build: ./samba 27 | networks: 28 | - frontend 29 | tty: true 30 | samba5: 31 | build: ./samba 32 | networks: 33 | - frontend 34 | tty: true 35 | 36 | networks: 37 | frontend: 38 | driver: bridge 39 | backend: 40 | driver: bridge 41 | -------------------------------------------------------------------------------- /System/test/5_example/example_phpmailer-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efe7bbd84247ff8fcfb534449355437c8a0e99ea9fe11bf32ef3b0ecdd2c1cde 3 | size 977486 4 | -------------------------------------------------------------------------------- /System/test/5_example/example_samba-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:072cf077da4fd3ab3398f90a237a65edef5a1b9f9b655e473c2eeb243ed13388 3 | size 1470628 4 | -------------------------------------------------------------------------------- /System/test/5_example/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4ee2dbb3b6c22b3da4357ebbb531423548351cd8a38a68ad116b20b1ecf661f0 3 | size 984 4 | -------------------------------------------------------------------------------- /System/test/5_example/topology_graph.dot: -------------------------------------------------------------------------------- 1 | // Topology Graph 2 | graph { 3 | outside 4 | "docker host" 5 | "5example_phpmailer" 6 | "5example_samba1" 7 | "5example_samba2" 8 | "5example_samba3" 9 | "5example_samba4" 10 | "5example_samba5" 11 | outside -- "5example_phpmailer" [contstraint=false] 12 | "docker host" -- "5example_phpmailer" [contstraint=false] 13 | "docker host" -- "5example_samba1" [contstraint=false] 14 | "docker host" -- "5example_samba2" [contstraint=false] 15 | "docker host" -- "5example_samba3" [contstraint=false] 16 | "docker host" -- "5example_samba4" [contstraint=false] 17 | "docker host" -- "5example_samba5" [contstraint=false] 18 | "5example_phpmailer" -- "5example_samba1" [contstraint=false] 19 | "5example_phpmailer" -- "5example_samba2" [contstraint=false] 20 | "5example_phpmailer" -- "5example_samba3" [contstraint=false] 21 | "5example_phpmailer" -- "5example_samba4" [contstraint=false] 22 | "5example_phpmailer" -- "5example_samba5" [contstraint=false] 23 | "5example_samba1" -- "5example_samba2" [contstraint=false] 24 | "5example_samba1" -- "5example_samba3" [contstraint=false] 25 | "5example_samba1" -- "5example_samba4" [contstraint=false] 26 | "5example_samba1" -- "5example_samba5" [contstraint=false] 27 | "5example_samba2" -- "5example_samba3" [contstraint=false] 28 | "5example_samba2" -- "5example_samba4" [contstraint=false] 29 | "5example_samba2" -- "5example_samba5" [contstraint=false] 30 | "5example_samba3" -- "5example_samba4" [contstraint=false] 31 | "5example_samba3" -- "5example_samba5" [contstraint=false] 32 | "5example_samba4" -- "5example_samba5" [contstraint=false] 33 | } 34 | -------------------------------------------------------------------------------- /System/test/5_example/topology_graph.dot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tum-i4/attack-graph-generator/1a92c340ab74696449a1368e6fadc7d0802446e8/System/test/5_example/topology_graph.dot.pdf -------------------------------------------------------------------------------- /System/test/atsea/atsea_app-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d1a96b6aa64a68a074d2080aadf3024ee12fc18892f7e69da79e69e0b8ec0997 3 | size 78665 4 | -------------------------------------------------------------------------------- /System/test/atsea/atsea_db-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:181fc3480064a7efa5a43195e424bc6e1e9bfa5d0b0ef478769413ea89163f35 3 | size 1382289 4 | -------------------------------------------------------------------------------- /System/test/atsea/atsea_payment_gateway-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8534ddec59e62c324afa394cec956df3020c5f6e490860b0d7922336548aa72a 3 | size 7511 4 | -------------------------------------------------------------------------------- /System/test/atsea/atsea_reverse_proxy-vulnerabilities.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b7e8b19c237ec2e51e6807395c6211215a5a9a15efb9d8dd071c77ca0b56560 3 | size 25973 4 | -------------------------------------------------------------------------------- /System/test/atsea/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | 3 | services: 4 | reverse_proxy: 5 | build: ./reverse_proxy 6 | user: nginx 7 | 8 | database: 9 | build: 10 | context: ./database 11 | image: atsea_db 12 | user: postgres 13 | environment: 14 | POSTGRES_USER: gordonuser 15 | POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password 16 | POSTGRES_DB: atsea 17 | ports: 18 | - "5432:5432" 19 | networks: 20 | - back-tier 21 | secrets: 22 | - postgres_password 23 | 24 | appserver: 25 | build: 26 | context: app 27 | dockerfile: Dockerfile 28 | image: atsea_app 29 | user: gordon 30 | ports: 31 | - "8080:8080" 32 | - "5005:5005" 33 | networks: 34 | - front-tier 35 | - back-tier 36 | secrets: 37 | - postgres_password 38 | 39 | payment_gateway: 40 | build: 41 | context: payment_gateway 42 | networks: 43 | - payment 44 | secrets: 45 | - payment_token 46 | 47 | networks: 48 | front-tier: 49 | back-tier: 50 | payment: 51 | driver: overlay 52 | 53 | secrets: 54 | postgres_password: 55 | file: ./devsecrets/postgres_password 56 | payment_token: 57 | file: ./devsecrets/payment_token 58 | -------------------------------------------------------------------------------- /System/test/atsea/topology.json: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14ea4fa3478fc95d6f448489320b748b5d481fcde1dc8a6e8e392b7c597ce29d 3 | size 316 4 | -------------------------------------------------------------------------------- /System/test/docker_compose_generator.py: -------------------------------------------------------------------------------- 1 | """Module for generating big docker compose files.""" 2 | 3 | import os 4 | import yaml 5 | 6 | def generate_compose_file(times_samba): 7 | """Function that generates the docker-compose.yml with number of samba containers.""" 8 | 9 | data = {"version" : "2", 10 | "networks" : {"frontend" : {"driver" : "bridge"}, 11 | "backend" : {"driver" : "bridge"}}, 12 | "services" : {"phpmailer" : {"build" : "./phpmailer", 13 | "networks" : ["frontend"], 14 | "ports" : [80]}}} 15 | 16 | for i in range(1, times_samba + 1): 17 | name_container = "samba"+str(i) 18 | dict_container = {"build" : "./samba", 19 | "networks" : ["frontend"], 20 | "tty" : True} 21 | data["services"][name_container] = dict_container 22 | 23 | 24 | with open(os.path.join(os.getcwd(), 'docker-compose.yml'), 'w') as outfile: 25 | yaml.dump(data, outfile, default_flow_style=False) 26 | 27 | generate_compose_file(1000) 28 | -------------------------------------------------------------------------------- /System/test/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Main module responsible for testing the software.""" 3 | 4 | import sys 5 | import os 6 | import unittest 7 | import json 8 | import time 9 | 10 | sys.path.append(os.path.dirname(os.getcwd())) 11 | 12 | from components import reader 13 | from components import writer 14 | from components import topology_parser as top_par 15 | 16 | from components.attack_graph_parser import breadth_first_search 17 | from components.attack_graph_parser import generate_attack_graph 18 | 19 | def scalability_test_helper(example_folder): 20 | """Main function that tests the scalability for different examples.""" 21 | 22 | number_runs_per_test = 5 23 | 24 | duration_topology = 0 25 | duration_bdf = 0 26 | duration_vuls_preprocessing = 0 27 | duration_total_time = 0 28 | 29 | for i in range(1, number_runs_per_test+1): 30 | 31 | print("\n\nIteration: "+str(i)) 32 | total_time_start = time.time() 33 | 34 | # Preparing the data for testing 35 | parent_path = os.path.dirname(os.getcwd()) 36 | 37 | # Opening the configuration file. 38 | config = reader.read_config_file(old_root_path=parent_path) 39 | topology, duration_topology_new = top_par.parse_topology(example_folder, 40 | os.getcwd()) 41 | 42 | duration_topology += duration_topology_new 43 | 44 | vuls_orig = reader.read_vulnerabilities(example_folder, 45 | ["example_samba", 46 | "example_phpmailer"]) 47 | 48 | vulnerabilities = {} 49 | for container_orig in vuls_orig.keys(): 50 | for container_topology in topology.keys(): 51 | if container_orig in container_topology: 52 | vulnerabilities[container_topology] = vuls_orig[container_orig] 53 | 54 | att_vec_path = os.path.join(parent_path, config["attack-vector-folder-path"]) 55 | 56 | # Returns a tuple of the form: 57 | # (attack_graph_nodes, attack_graph_edges, duration_bdf, duration_vul_preprocessing) 58 | attack_graph_tuple = generate_attack_graph(att_vec_path, 59 | config["preconditions-rules"], 60 | config["postconditions-rules"], 61 | topology, 62 | vulnerabilities, 63 | example_folder) 64 | 65 | # Unpacking the variables 66 | duration_bdf += attack_graph_tuple[2] 67 | duration_vuls_preprocessing += attack_graph_tuple[3] 68 | 69 | no_topology_nodes = len(topology.keys()) 70 | no_topology_edges = 0 71 | for container in topology.keys(): 72 | no_topology_edges += len(topology[container]) 73 | 74 | # We divide them by two because each edge is counted twice. 75 | no_topology_edges = int(no_topology_edges / 2) 76 | no_attack_graph_nodes = len(attack_graph_tuple[0]) 77 | no_attack_graph_edges = len(attack_graph_tuple[1]) 78 | 79 | duration_total_time += (time.time() - total_time_start) 80 | 81 | # Calculate the averages of the times 82 | duration_topology = duration_topology/5 83 | duration_vuls_preprocessing = duration_vuls_preprocessing/5 84 | duration_bdf = duration_bdf/5 85 | duration_total_time = duration_topology + duration_vuls_preprocessing + duration_bdf 86 | 87 | # Printing time summary of the attack graph generation. 88 | writer.print_summary(config["mode"], 89 | config["generate_graphs"], 90 | no_topology_nodes=no_topology_nodes, 91 | no_topology_edges=no_topology_edges, 92 | no_attack_graph_nodes=no_attack_graph_nodes, 93 | no_attack_graph_edges=no_attack_graph_edges, 94 | duration_topology=duration_topology, 95 | duration_vuls_preprocessing=duration_vuls_preprocessing, 96 | duration_bdf=duration_bdf, 97 | duration_total_time=duration_total_time) 98 | 99 | print("Total time elapsed: "+str(duration_total_time)+"\n\n\n") 100 | 101 | class MyTest(unittest.TestCase): 102 | """This class contains the unit tests.""" 103 | 104 | def test_bfs_priviledged_exists(self): 105 | """Testing the creation of attack graph with a priviledged container. 106 | Here the priviledged container is container2. Container3 is isolated and it can 107 | only be reached through the docker host.""" 108 | 109 | print("Test: Testing an image with a 'priviledged' flag...") 110 | 111 | topology = {"outside" : ["container1"], 112 | "container1": ["container2", "outside", "docker host"], 113 | "container2": ["container1", "docker host"], 114 | "container3": ["docker host"], 115 | "docker host": ["container1", "container2", "container3"]} 116 | 117 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 118 | "postcond" : {"CVE-2015-0000" : 3}}, 119 | "container2" : {"precond" : {"CVE-2015-0001" : 3}, 120 | "postcond" : {"CVE-2015-0001" : 4}}, 121 | "container3": {"precond" : {"CVE-2015-0002" : 3}, 122 | "postcond" : {"CVE-2015-0002" : 4}}} 123 | 124 | privileged_access = {"container1" : False, "container2" : True, "container3" : False} 125 | 126 | nodes, edges, _ = breadth_first_search(topology, 127 | exploitable_vuls, 128 | privileged_access) 129 | 130 | # Checking that container3 has been attacked and the edges that lead to it. 131 | self.assertTrue('container2(ADMIN)|docker host(ADMIN)' in edges) 132 | self.assertTrue('docker host(ADMIN)|container3(ADMIN)' in edges) 133 | self.assertTrue('container3(ADMIN)' in nodes) 134 | 135 | def test_bfs_priviledged_dont_exist(self): 136 | """Testing the creation of attack graph without a priviledged container. 137 | There is no privileged container. Container3 is isolated and it can 138 | only be reached through the docker host.""" 139 | 140 | print("Test: Testing an image without a 'privileged' flag...") 141 | 142 | topology = {"outside" : ["container1"], 143 | "container1": ["container2", "outside", "docker host"], 144 | "container2": ["container1", "docker host"], 145 | "container3": ["docker host"], 146 | "docker host": ["container1", "container2", "container3"]} 147 | 148 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 149 | "postcond" : {"CVE-2015-0000" : 3}}, 150 | "container2" : {"precond" : {"CVE-2015-0001" : 3}, 151 | "postcond" : {"CVE-2015-0001" : 4}}, 152 | "container3": {"precond" : {"CVE-2015-0002" : 3}, 153 | "postcond" : {"CVE-2015-0002" : 4}}} 154 | 155 | privileged_access = {"container1" : False, "container2" : False, "container3" : False} 156 | 157 | nodes, _, _ = breadth_first_search(topology, 158 | exploitable_vuls, 159 | privileged_access) 160 | 161 | # Checking that container3 has not been attacked 162 | self.assertFalse('container3(NONE)' in nodes) 163 | self.assertFalse('container3(VOS USER)' in nodes) 164 | self.assertFalse('container3(VOS ADMIN)' in nodes) 165 | self.assertFalse('container3(USER)' in nodes) 166 | self.assertFalse('container3(ADMIN)' in nodes) 167 | 168 | self.assertFalse('docker host(ADMIN)' in nodes) 169 | 170 | def test_empty_graph(self): 171 | """Testing an empty graph. Empty graph by our definition has 172 | no nodes.""" 173 | 174 | print("Test: Testing an empty attack graph(attacker has no access)...") 175 | 176 | topology = {"outside" : [], 177 | "container1": ["container2", "docker host"], 178 | "container2": ["container1", "docker host"], 179 | "container3": ["docker host"], 180 | "docker host": ["container1", "container2", "container3"]} 181 | 182 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 183 | "postcond" : {"CVE-2015-0000" : 3}}, 184 | "container2" : {"precond" : {"CVE-2015-0001" : 3}, 185 | "postcond" : {"CVE-2015-0001" : 4}}, 186 | "container3": {"precond" : {"CVE-2015-0002" : 3}, 187 | "postcond" : {"CVE-2015-0002" : 4}}} 188 | 189 | privileged_access = {"container1" : False, "container2" : False, "container3" : False} 190 | 191 | nodes, edges, _ = breadth_first_search(topology, 192 | exploitable_vuls, 193 | privileged_access) 194 | 195 | # Checking that outside(ADMIN) is the only node. 196 | self.assertTrue('outside(ADMIN)' not in nodes) 197 | 198 | # The attack graph should have 0 nodes. 199 | self.assertEqual(len(nodes), 0) 200 | 201 | # The attack graph should have 0 edges. 202 | self.assertEqual(len(edges), 0) 203 | 204 | def test_clique_attacker(self): 205 | """Tests an attack graph that has an attacker in a clique 206 | i.e. connected to every container.""" 207 | 208 | print("Test: Testing an all-connected attacker...") 209 | 210 | topology = {"outside" : ["container1", "container2", "container3"], 211 | "container1": ["outside", "container2", "docker host"], 212 | "container2": ["outside", "container1", "docker host"], 213 | "container3": ["outside", "docker host"], 214 | "docker host": ["container1", "container2", "container3"]} 215 | 216 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 217 | "postcond" : {"CVE-2015-0000" : 3}}, 218 | "container2" : {"precond" : {"CVE-2015-0001" : 3}, 219 | "postcond" : {"CVE-2015-0001" : 4}}, 220 | "container3": {"precond" : {"CVE-2015-0002" : 3}, 221 | "postcond" : {"CVE-2015-0002" : 4}}} 222 | 223 | privileged_access = {"container1" : False, "container2" : False, "container3" : False} 224 | 225 | nodes, edges, _ = breadth_first_search(topology, 226 | exploitable_vuls, 227 | privileged_access) 228 | 229 | # Checking the nodes 230 | self.assertEqual(len(nodes), 4) 231 | self.assertTrue('outside(ADMIN)' in nodes) 232 | self.assertTrue('container1(USER)' in nodes) 233 | self.assertTrue('container2(ADMIN)' in nodes) 234 | self.assertTrue('container3(ADMIN)' in nodes) 235 | 236 | # Checking the edges 237 | self.assertEqual(len(edges), 3) 238 | self.assertTrue('outside(ADMIN)|container1(USER)' in edges) 239 | self.assertTrue('outside(ADMIN)|container2(ADMIN)' in edges) 240 | self.assertTrue('outside(ADMIN)|container3(ADMIN)' in edges) 241 | 242 | def test_more_than_one_vuls(self): 243 | """Tests an attack graph that has has more than two ways to attack 244 | same node from the same node. In this example container2 has two vulnerabilities 245 | that can potentially be exploited""" 246 | 247 | print("Test: Testing more than one vuls attack from the same node...") 248 | 249 | topology = {"outside" : ["container1"], 250 | "container1": ["outside", "container2", "docker host"], 251 | "container2": ["outside", "container1", "docker host"], 252 | "docker host": ["container1", "container2"]} 253 | 254 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 255 | "postcond" : {"CVE-2015-0000" : 3}}, 256 | "container2" : {"precond" : {"CVE-2015-0001" : 3, 257 | "CVE-2016-0001" : 3}, 258 | "postcond" : {"CVE-2015-0001" : 4, 259 | "CVE-2016-0001" : 4}}} 260 | 261 | privileged_access = {"container1" : False, "container2" : False} 262 | 263 | nodes, edges, _ = breadth_first_search(topology, 264 | exploitable_vuls, 265 | privileged_access) 266 | 267 | # Checking the nodes 268 | self.assertEqual(len(nodes), 3) 269 | self.assertTrue('outside(ADMIN)' in nodes) 270 | self.assertTrue('container1(USER)' in nodes) 271 | self.assertTrue('container2(ADMIN)' in nodes) 272 | 273 | # Checking the edges 274 | self.assertEqual(len(edges), 2) 275 | self.assertTrue('outside(ADMIN)|container1(USER)' in edges) 276 | self.assertTrue('container1(USER)|container2(ADMIN)' in edges) 277 | 278 | # Checking the edge from container1 to container2 279 | edge = edges['container1(USER)|container2(ADMIN)'] 280 | self.assertEqual('CVE-2015-0001', edge[0]) 281 | self.assertEqual('CVE-2016-0001', edge[1]) 282 | 283 | def test_long_attack_graph(self): 284 | """Tests an attack graph that has 4 nodes and it is in a 285 | long chain manner with escalating privileges. 286 | The attacker has to optain outside->container1->container2->container3->container4""" 287 | 288 | print("Test: Testing a long attack graph...") 289 | 290 | topology = {"outside" : ["container1"], 291 | "container1": ["outside", "container2", "docker host"], 292 | "container2": ["container1", "container3", "docker host"], 293 | "container3": ["container2", "container4", "docker host"], 294 | "container4": ["container3", "docker host"], 295 | "docker host": ["container1", "container2", "container3", "container4"]} 296 | 297 | exploitable_vuls = {"container1": {"precond" : {"CVE-2015-0000" : 0}, 298 | "postcond" : {"CVE-2015-0000" : 1}}, 299 | "container2" : {"precond" : {"CVE-2015-0001" : 1}, 300 | "postcond" : {"CVE-2015-0001" : 2}}, 301 | "container3" : {"precond" : {"CVE-2015-0002" : 2}, 302 | "postcond" : {"CVE-2015-0002" : 3}}, 303 | "container4" : {"precond" : {"CVE-2015-0003" : 3}, 304 | "postcond" : {"CVE-2015-0003" : 4}}} 305 | 306 | privileged_access = {"container1" : False, 307 | "container2" : False, 308 | "container3" : False, 309 | "container4" : False} 310 | 311 | nodes, edges, _ = breadth_first_search(topology, 312 | exploitable_vuls, 313 | privileged_access) 314 | 315 | # Checking the nodes 316 | self.assertEqual(len(nodes), 5) 317 | self.assertTrue('outside(ADMIN)' in nodes) 318 | self.assertTrue('container1(VOS USER)' in nodes) 319 | self.assertTrue('container2(VOS ADMIN)' in nodes) 320 | self.assertTrue('container3(USER)' in nodes) 321 | self.assertTrue('container4(ADMIN)' in nodes) 322 | 323 | # Checking the edges 324 | self.assertEqual(len(edges), 4) 325 | self.assertTrue('outside(ADMIN)|container1(VOS USER)' in edges) 326 | self.assertTrue('container1(VOS USER)|container2(VOS ADMIN)' in edges) 327 | self.assertTrue('container2(VOS ADMIN)|container3(USER)' in edges) 328 | self.assertTrue('container3(USER)|container4(ADMIN)' in edges) 329 | 330 | def test_big_real_example(self): 331 | """Testing the example from atsea shop app. It has 4 containers in total. However 332 | only two of them have vulnerabilities.""" 333 | 334 | print("Test: Testing a real example...") 335 | 336 | # Preparing the data for testing 337 | example_folder = os.path.join(os.getcwd(), "atsea") 338 | parent_path = os.path.dirname(os.getcwd()) 339 | 340 | # Opening the configuration file. 341 | config = reader.read_config_file(old_root_path=parent_path) 342 | 343 | topology_path = os.path.join(os.getcwd(), "atsea", "topology.json") 344 | with open(topology_path) as topology_file: 345 | topology = json.load(topology_file) 346 | 347 | vulnerabilities = reader.read_vulnerabilities(example_folder, topology.keys()) 348 | 349 | # Running the attack graph generator 350 | att_vec_path = os.path.join(parent_path, config["attack-vector-folder-path"]) 351 | nodes, edges, _, _ = generate_attack_graph(att_vec_path, 352 | config["preconditions-rules"], 353 | config["postconditions-rules"], 354 | topology, 355 | vulnerabilities, 356 | example_folder) 357 | 358 | # Checking the nodes 359 | self.assertEqual(len(nodes), 5) 360 | self.assertTrue('outside(ADMIN)' in nodes) 361 | self.assertTrue('atsea_app(ADMIN)' in nodes) 362 | self.assertTrue('atsea_app(USER)' in nodes) 363 | self.assertTrue('atsea_db(ADMIN)' in nodes) 364 | self.assertTrue('atsea_db(USER)' in nodes) 365 | 366 | # Checking the edges 367 | self.assertEqual(len(edges), 4) 368 | self.assertTrue('outside(ADMIN)|atsea_app(ADMIN)' in edges) 369 | self.assertTrue('outside(ADMIN)|atsea_app(USER)' in edges) 370 | self.assertTrue('outside(ADMIN)|atsea_db(ADMIN)' in edges) 371 | self.assertTrue('outside(ADMIN)|atsea_db(USER)' in edges) 372 | 373 | def test_scalability_1(self): 374 | """Doing scalability testing of samba and phpmailer example. It has 375 | 1 phpmailer container and 1 samba container.""" 376 | 377 | print("Test: Scalability test of samba and phpmailer example...") 378 | 379 | # Preparing the data for testing 380 | example_folder = os.path.join(os.getcwd(), "1_example") 381 | #scalability_test_helper(example_folder) 382 | 383 | def test_scalability_5(self): 384 | """Doing scalability testing of samba and phpmailer example. It has 385 | 1 phpmailer container and 5 samba containers.""" 386 | 387 | print("Test: Scalability test of 5 samba and phpmailer example...") 388 | 389 | # Preparing the data for testing 390 | example_folder = os.path.join(os.getcwd(), "5_example") 391 | #scalability_test_helper(example_folder) 392 | 393 | 394 | def test_scalability_20(self): 395 | """Doing scalability testing of samba and phpmailer example. It has 396 | 1 phpmailer container and 20 samba containers.""" 397 | 398 | print("Test: Scalability test of 20 samba and phpmailer example...") 399 | 400 | # Preparing the data for testing 401 | example_folder = os.path.join(os.getcwd(), "20_example") 402 | #scalability_test_helper(example_folder) 403 | 404 | def test_scalability_50(self): 405 | """Doing scalability testing of samba and phpmailer example. It has 406 | 1 phpmailer container and 50 samba containers.""" 407 | 408 | print("Test: Scalability test of 50 samba and phpmailer example...") 409 | 410 | # Preparing the data for testing 411 | example_folder = os.path.join(os.getcwd(), "50_example") 412 | #scalability_test_helper(example_folder) 413 | 414 | def test_scalability_100(self): 415 | """Doing scalability testing of samba and phpmailer example. It has 416 | 1 phpmailer container and 100 samba containers.""" 417 | 418 | print("Test: Scalability test of 100 samba and phpmailer example...") 419 | 420 | # Preparing the data for testing 421 | example_folder = os.path.join(os.getcwd(), "100_example") 422 | #scalability_test_helper(example_folder) 423 | 424 | def test_scalability_500(self): 425 | """Doing scalability testing of samba and phpmailer example. It has 426 | 1 phpmailer container and 500 samba containers.""" 427 | 428 | print("Test: Scalability test of 500 samba and phpmailer example...") 429 | 430 | # Preparing the data for testing 431 | example_folder = os.path.join(os.getcwd(), "500_example") 432 | #scalability_test_helper(example_folder) 433 | 434 | def test_scalability_1000(self): 435 | """Doing scalability testing of samba and phpmailer example. It has 436 | 1 phpmailer container and 1000 samba containers.""" 437 | 438 | print("Test: Scalability test of 1000 samba and phpmailer example...") 439 | 440 | # Preparing the data for testing 441 | example_folder = os.path.join(os.getcwd(), "1000_example") 442 | scalability_test_helper(example_folder) 443 | 444 | if __name__ == "__main__": 445 | print("Testing the attack graph generator...") 446 | 447 | unittest.main() 448 | --------------------------------------------------------------------------------