
Create randomly insecure VMs
SecGen creates vulnerable virtual machines, lab environments, and hacking challenges, so students can learn security penetration testing techniques.
Boxes like Metasploitable2 are always the same, this project uses Vagrant, Puppet, and Ruby to create randomly vulnerable virtual machines that can be used for learning or for hosting CTF events.
The latest version is available at: http://github.com/cliffe/SecGen/
Please complete a short survey to tell us how you are using SecGen.
For a hosted solution visit: https://hacktivity.co.uk/
Computer security students benefit from engaging in hacking challenges. Practical lab work and pre-configured hacking challenges are common practice both in security education and also as a pastime for security-minded individuals. Competitive hacking challenges, such as capture the flag (CTF) competitions have become a mainstay at industry conferences and are the focus of large online communities. Virtual machines (VMs) provide an effective way of sharing targets for hacking, and can be designed in order to test the skills of the attacker. Websites such as Vulnhub host pre-configured hacking challenge VMs and are a valuable resource for those learning and advancing their skills in computer security. However, developing these hacking challenges is time consuming, and once created, essentially static. That is, once the challenge has been "solved" there is no remaining challenge for the student, and if the challenge is created for a competition or assessment, the challenge cannot be reused without risking plagiarism, and collusion.
Security Scenario Generator (SecGen) generates randomised vulnerable systems. VMs are created based on a scenario specification, which describes the constraints and properties of the VMs to be created. For example, a scenario could specify the creation of a system with a remotely exploitable vulnerability that would result in user-level compromise, and a locally exploitable flaw that would result in root-level compromise. This would require the attacker to discover and exploit both randomly selected vulnerabilities in order to obtain root access to the system. Alternatively, the scenario that is defined can be more specific, specifying certain kinds of services (such as FTP or SMB) or even exact vulnerabilities (by CVE).
SecGen is a Ruby application, with an XML configuration language. SecGen reads its configuration, including the available vulnerabilities, services, networks, users, and content, reads the definition of the requested scenario, applies logic for randomising the scenario, and leverages Puppet and Vagrant to provision the required VMs.
SecGen is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
SecGen contains modules, which install various software packages. Each SecGen module may contain or remotely source software, and each module defines its own license in the accompanying secgen_metadata.xml file.
SecGen is developed and tested on Ubuntu Linux. In theory, SecGen should run on Mac or Windows, if you have all the required software installed.
SecGen needs:
There are two ways to install it. Both have been tested from a fresh Ubuntu install.
Install Docker and VirtualBox on the host, then let docker/secgen-docker.sh build a container with everything else. VirtualBox is still needed on the host for its kernel driver. See docker/README.md.
git clone https://github.com/cliffe/SecGen.git
cd SecGen
docker/secgen-docker.sh run -s scenarios/default_scenario.xml
Install VirtualBox from Oracle's repository. The virtualbox package in Ubuntu 24.04 (7.0.16) cannot build its kernel driver for the current HWE kernels, and Linux 7.0 needs VirtualBox 7.2.8 or later:
sudo apt-get update
sudo apt-get install -y wget gpg lsb-release
wget -qO- https://www.virtualbox.org/download/oracle_vbox_2016.asc \
| sudo gpg --yes --dearmor -o /usr/share/keyrings/oracle-virtualbox-2016.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/oracle-virtualbox-2016.gpg] https://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib" \
| sudo tee /etc/apt/sources.list.d/virtualbox.list
sudo apt-get update
sudo apt-get install -y virtualbox-7.2
If KVM is loaded, VirtualBox can't start VMs while KVM holds VT-x (VERR_VMX_IN_VMX_ROOT_MODE). On kernels 6.12 and later you can let them coexist:
echo "options kvm enable_virt_at_load=0" | sudo tee /etc/modprobe.d/kvm-virtualbox.conf
sudo modprobe -r kvm_intel kvm_amd kvm; sudo modprobe kvm_intel || sudo modprobe kvm_amd
SecGen scenarios use host-only network ranges outside VirtualBox's default 192.168.56.0/21, so allow any range:
sudo mkdir -p /etc/vbox
echo '* 0.0.0.0/0 ::/0' | sudo tee /etc/vbox/networks.conf
Install Vagrant from HashiCorp's repository (Ubuntu 26.04 no longer packages it, and older Vagrant releases can't download boxes from Vagrant Cloud any more):
wget -qO- https://apt.releases.hashicorp.com/gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update
sudo apt-get install -y vagrant
Install Ruby and the other required packages:
sudo apt-get install -y git ruby-full ruby-dev build-essential patch pkg-config zlib1g-dev liblzma-dev \
imagemagick exiftool libpq-dev libcurl4-openssl-dev libxml2-dev libxslt1-dev graphviz libgraphviz-dev \
libpcap-dev libsqlite3-dev libgpgme-dev libyaml-dev libffi-dev libssl-dev
Clone SecGen and install the gems. Use bundle install, not bundle update: Gemfile.lock pins versions that work on every supported Ruby, and bundle update replaces them with the newest releases, which may not.
git clone https://github.com/cliffe/SecGen.git
cd SecGen
sudo gem install bundler -v '~> 2.4'
sudo bundle install
Then try the default scenario (it downloads the base box from hacktivity.co.uk the first time):
ruby secgen.rb run
Notes: