mirror of
https://github.com/cliffe/SecGen.git
synced 2026-02-21 11:18:06 +00:00
Initial changes to directory structure
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
projects/**
|
||||
projects
|
||||
unusedcode
|
||||
.DS_Store
|
||||
.idea
|
||||
|
||||
79
.idea/SecGen.iml
generated
Normal file
79
.idea/SecGen.iml
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="RUBY_MODULE" version="4">
|
||||
<component name="ModuleRunConfigurationManager">
|
||||
<configuration default="false" name="systemreader" type="RubyRunConfigurationType" factoryName="Ruby" temporary="true">
|
||||
<module name="SecGen" />
|
||||
<RUBY_RUN_CONFIG NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
||||
<RUBY_RUN_CONFIG NAME="WORK DIR" VALUE="$MODULE_DIR$" />
|
||||
<RUBY_RUN_CONFIG NAME="SHOULD_USE_SDK" VALUE="false" />
|
||||
<RUBY_RUN_CONFIG NAME="ALTERN_SDK_NAME" VALUE="" />
|
||||
<RUBY_RUN_CONFIG NAME="myPassParentEnvs" VALUE="true" />
|
||||
<envs />
|
||||
<EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="true" />
|
||||
<EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
|
||||
<EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
|
||||
<COVERAGE_PATTERN ENABLED="true">
|
||||
<PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
|
||||
</COVERAGE_PATTERN>
|
||||
</EXTENSION>
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_PATH" VALUE="$MODULE_DIR$/lib/systemreader.rb" />
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_ARGS" VALUE="" />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="false" name="secgen" type="RubyRunConfigurationType" factoryName="Ruby" temporary="true">
|
||||
<module name="SecGen" />
|
||||
<RUBY_RUN_CONFIG NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
||||
<RUBY_RUN_CONFIG NAME="WORK DIR" VALUE="$MODULE_DIR$" />
|
||||
<RUBY_RUN_CONFIG NAME="SHOULD_USE_SDK" VALUE="false" />
|
||||
<RUBY_RUN_CONFIG NAME="ALTERN_SDK_NAME" VALUE="" />
|
||||
<RUBY_RUN_CONFIG NAME="myPassParentEnvs" VALUE="true" />
|
||||
<envs />
|
||||
<EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="true" />
|
||||
<EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
|
||||
<EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
|
||||
<COVERAGE_PATTERN ENABLED="true">
|
||||
<PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
|
||||
</COVERAGE_PATTERN>
|
||||
</EXTENSION>
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_PATH" VALUE="$MODULE_DIR$/secgen.rb" />
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_ARGS" VALUE="-r" />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="false" name="vulnerability_processor_tests" type="RubyRunConfigurationType" factoryName="Ruby" temporary="true">
|
||||
<module name="SecGen" />
|
||||
<RUBY_RUN_CONFIG NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
|
||||
<RUBY_RUN_CONFIG NAME="WORK DIR" VALUE="$MODULE_DIR$/tests/helpers" />
|
||||
<RUBY_RUN_CONFIG NAME="SHOULD_USE_SDK" VALUE="false" />
|
||||
<RUBY_RUN_CONFIG NAME="ALTERN_SDK_NAME" VALUE="" />
|
||||
<RUBY_RUN_CONFIG NAME="myPassParentEnvs" VALUE="true" />
|
||||
<envs />
|
||||
<EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="true" />
|
||||
<EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
|
||||
<EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
|
||||
<COVERAGE_PATTERN ENABLED="true">
|
||||
<PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
|
||||
</COVERAGE_PATTERN>
|
||||
</EXTENSION>
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_PATH" VALUE="$MODULE_DIR$/tests/helpers/vulnerability_processor_tests.rb" />
|
||||
<RUBY_RUN_CONFIG NAME="SCRIPT_ARGS" VALUE="" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/projects" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/projects/Project1" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="stub [puppet module]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.10.4, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.0.0, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="minitest (v5.8.4, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.6.7.1, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="rake (v10.5.0, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="xml-simple (v1.1.5, ruby-2.0.0-p645) [gem]" level="application" />
|
||||
</component>
|
||||
<component name="PuppetLibraryUpdateService" isEnabled="true" />
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
11
Gemfile
11
Gemfile
@@ -1,3 +1,10 @@
|
||||
source "https://rubygems.org"
|
||||
source 'https://rubygems.org'
|
||||
#production gems go here
|
||||
gem 'nokogiri'
|
||||
gem 'xml-simple'
|
||||
|
||||
gem "nokogiri"
|
||||
#development only gems go here
|
||||
group :test, :development do
|
||||
gem 'minitest'
|
||||
gem 'rake'
|
||||
end
|
||||
1
config/config
Normal file
1
config/config
Normal file
@@ -0,0 +1 @@
|
||||
Configuration will go here
|
||||
@@ -2,9 +2,7 @@
|
||||
<!-- an example remote storage system, with a remotely exploitable vulnerability that can then be escalated to root -->
|
||||
<system id="storageserver" os="linux" basebox="puppettest" url="" >
|
||||
<vulnerabilities>
|
||||
<vulnerability privilege="user" access="remote" type="ftp" cve=""></vulnerability>
|
||||
<vulnerability privilege="user" access="remote" type="" cve=""></vulnerability>
|
||||
<vulnerability privilege="root" access="local" type="" cve=""></vulnerability>
|
||||
</vulnerabilities>
|
||||
<!-- secure services will be provided, if matching insecure ones have not been selected -->
|
||||
<!--<services>-->
|
||||
@@ -18,13 +16,14 @@
|
||||
</system>
|
||||
|
||||
<!-- an example remote web server, with a remotely exploitable root vulnerability -->
|
||||
<system id="webserver" os="linux" basebox="puppettest" url="" >
|
||||
<!-- This never worked.-->
|
||||
<!--<system id="webserver" os="linux" basebox="puppettest" url="" >
|
||||
<vulnerabilities>
|
||||
<vulnerability privilege="root" access="remote" type="www" cve=""></vulnerability>
|
||||
</vulnerabilities>
|
||||
<networks>
|
||||
<network name="homeonly"></network>
|
||||
<misc name="homeonly"></misc>
|
||||
</networks>
|
||||
</system>
|
||||
</system> -->
|
||||
|
||||
</systems>
|
||||
2
Vagrantfile → lib/Vagrantfile
vendored
2
Vagrantfile → lib/Vagrantfile
vendored
@@ -25,7 +25,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# using a specific IP.
|
||||
# config.vm.network "private_network", ip: "192.168.33.10"
|
||||
|
||||
# Create a public network, which generally matched to bridged network.
|
||||
# Create a public misc, which generally matched to bridged misc.
|
||||
# Bridged networks make the machine appear as another physical device on
|
||||
# your network.
|
||||
# config.vm.network "public_network"
|
||||
18
lib/constants.rb
Normal file
18
lib/constants.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
#FILE CONSTANTS
|
||||
ROOT_DIR = File.expand_path('../../../SecGen',__FILE__)
|
||||
SCENARIO_XML = "#{ROOT_DIR}/config/scenario.xml"
|
||||
NETWORKS_XML = "#{ROOT_DIR}/xml/networks.xml"
|
||||
VULN_XML = "#{ROOT_DIR}/xml/vulns.xml"
|
||||
SERVICES_XML = "#{ROOT_DIR}/xml/services.xml"
|
||||
BASE_XML = "#{ROOT_DIR}/xml/bases.xml"
|
||||
MOUNT_DIR = "#{ROOT_DIR}/mount/"
|
||||
|
||||
#PATH CONSTANTS
|
||||
MODULES_PATH = "#{ROOT_DIR}/modules/"
|
||||
VULNERABILITIES_PATH = "#{ROOT_DIR}/modules/vulnerabilities/"
|
||||
|
||||
#ERROR CONSTANTS
|
||||
VULN_NOT_FOUND = "Matching vulnerability was not found please check the xml scenario.xml"
|
||||
|
||||
#RUNTIME_CONSTANTS
|
||||
AVAILABLE_CVE_NUMBERS = []
|
||||
@@ -1,5 +1,5 @@
|
||||
require 'erb'
|
||||
require_relative 'system.rb'
|
||||
require_relative 'constants'
|
||||
|
||||
|
||||
VAGRANT_TEMPLATE_FILE = "#{ROOT_DIR}/lib/templates/vagrantbase.erb"
|
||||
@@ -36,9 +36,9 @@ class FileCreator
|
||||
File.open("#{PROJECTS_DIR}/Project#{build_number}/Vagrantfile", 'w') { |file| file.write(vagrant_template.result(controller.get_binding)) }
|
||||
|
||||
|
||||
report_template = ERB.new(File.read(REPORT_TEMPLATE_FILE), 0, '<>')
|
||||
puts "#{PROJECTS_DIR}/Project#{build_number}/Report file has been created"
|
||||
File.open("#{PROJECTS_DIR}/Project#{build_number}/Report", 'w'){ |file| file.write(report_template.result(controller.get_binding)) }
|
||||
#report_template = ERB.new(File.read(REPORT_TEMPLATE_FILE), 0, '<>')
|
||||
#puts "#{PROJECTS_DIR}/Project#{build_number}/Report file has been created"
|
||||
#File.open("#{PROJECTS_DIR}/Project#{build_number}/Report", 'w'){ |file| file.write(report_template.result(controller.get_binding)) }
|
||||
|
||||
return build_number
|
||||
end
|
||||
78
lib/helpers/vulnerability_processor.rb
Normal file
78
lib/helpers/vulnerability_processor.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
require_relative '../../lib/constants' #CW - Could this only be included in secgen.rb and have the constants initialized at runtime?
|
||||
require_relative '../../lib/objects/vulnerability'
|
||||
require 'nokogiri'
|
||||
require 'xmlsimple'
|
||||
|
||||
class VulnerabilityProcessor
|
||||
# returns a hash of compatible vulnerabilities based on what is provided in scenario.xml (scenario_vulns)
|
||||
# based on the attributes optionally specified in scenario.xml (scenario_vulns)
|
||||
def process(scenario_vulns)
|
||||
|
||||
return_vulns = {}
|
||||
|
||||
all_vulnerabilities = get_vulnerabilities_array
|
||||
|
||||
scenario_vulns.each do |vulnerability_query|
|
||||
# select based on selected type, access, cve...
|
||||
search_list = all_vulnerabilities.clone
|
||||
# shuffle order of available vulnerabilities
|
||||
search_list.shuffle!
|
||||
# remove all the vulns that don't match the current selection (type, etc)
|
||||
if vulnerability_query.type.length > 0
|
||||
puts "Searching for vulnerability matching type: " + vulnerability_query.type
|
||||
search_list.delete_if{|x| x.type != vulnerability_query.type}
|
||||
end
|
||||
if vulnerability_query.access.length > 0
|
||||
puts "Searching for vulnerability matching access: " + vulnerability_query.access
|
||||
search_list.delete_if{|x| x.access != vulnerability_query.access}
|
||||
end
|
||||
if vulnerability_query.cve.length > 0
|
||||
puts "Searching for vulnerability matching CVE: " + vulnerability_query.cve
|
||||
search_list.delete_if{|x| x.cve != vulnerability_query.cve}
|
||||
end
|
||||
|
||||
if search_list.length == 0
|
||||
puts VULN_NOT_FOUND
|
||||
puts "(note: you can only have one of each type of vulnerability per system)"
|
||||
exit
|
||||
else
|
||||
# use from the top of the top of the randomised list
|
||||
return_vulns[vulnerability_query.id] = search_list[0]
|
||||
if search_list[0].type.length > 0
|
||||
puts "Selected vulnerability : " + search_list[0].type
|
||||
end
|
||||
|
||||
# enforce only one of any vulnerability type (remove from available)
|
||||
search_list.delete_if{|x| x.type == vulnerability_query.type}
|
||||
end
|
||||
end
|
||||
|
||||
return return_vulns.values
|
||||
|
||||
|
||||
end
|
||||
|
||||
def get_vulnerabilities_array
|
||||
vulnerabilities = []
|
||||
Dir.glob("#{ROOT_DIR}/modules/vulnerabilities/**/**/secgen_metadata.xml").each do |file|
|
||||
vulnerability_hash = XmlSimple.xml_in(file, {})
|
||||
vulnerability = convert_vulnerability_hash_to_vulnerability_object(vulnerability_hash)
|
||||
vulnerabilities.push(vulnerability)
|
||||
end
|
||||
|
||||
return vulnerabilities
|
||||
end
|
||||
|
||||
def convert_vulnerability_hash_to_vulnerability_object(vulnerability_hash)
|
||||
return Vulnerability.new(
|
||||
vulnerability_hash['type'],
|
||||
vulnerability_hash['privilege'],
|
||||
vulnerability_hash['access'],
|
||||
vulnerability_hash['puppets'],
|
||||
vulnerability_hash['details'],
|
||||
vulnerability_hash['ports'],
|
||||
vulnerability_hash['cve'],
|
||||
vulnerability_hash['files'],
|
||||
vulnerability_hash['scripts'])
|
||||
end
|
||||
end
|
||||
25
lib/objects/vulnerability.rb
Normal file
25
lib/objects/vulnerability.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
class Vulnerability
|
||||
attr_accessor :type, :privilege, :access ,:puppets, :details, :ports, :cve, :files, :scripts
|
||||
|
||||
def eql? other
|
||||
# checks if type matches vulns.xml from scenario.xml
|
||||
other.kind_of?(self.class) && @type == other.type
|
||||
end
|
||||
|
||||
def initialize(type="", privilege="", access="", puppets=[], details="", ports=[], cve="", files=[], scripts=[])
|
||||
@type = type
|
||||
@privilege = privilege
|
||||
@access = access
|
||||
@puppets = puppets
|
||||
@details = details
|
||||
@ports = ports
|
||||
@cve = cve
|
||||
@files = files
|
||||
@scripts = scripts
|
||||
end
|
||||
|
||||
def id
|
||||
return @type + @privilege + @access
|
||||
end
|
||||
|
||||
end
|
||||
1
lib/puppet_shared/puppet_shared
Normal file
1
lib/puppet_shared/puppet_shared
Normal file
@@ -0,0 +1 @@
|
||||
The new mount
|
||||
@@ -1,13 +1,6 @@
|
||||
require 'nokogiri'
|
||||
# assign constants
|
||||
ROOT_DIR = File.dirname(__FILE__)
|
||||
require_relative 'constants'
|
||||
|
||||
BOXES_XML = "#{ROOT_DIR}/lib/xml/boxes.xml"
|
||||
NETWORKS_XML = "#{ROOT_DIR}/lib/xml/networks.xml"
|
||||
VULN_XML = "#{ROOT_DIR}/lib/xml/vulns.xml"
|
||||
SERVICES_XML = "#{ROOT_DIR}/lib/xml/services.xml"
|
||||
BASE_XML = "#{ROOT_DIR}/lib/xml/bases.xml"
|
||||
MOUNT_DIR = "#{ROOT_DIR}/mount/"
|
||||
|
||||
class System
|
||||
# can access from outside of class
|
||||
@@ -53,7 +46,7 @@ class Network
|
||||
end
|
||||
|
||||
def eql? other
|
||||
# checks if name matches networks.xml from boxes.xml
|
||||
# checks if name matches networks.xml from scenario.xml
|
||||
other.kind_of?(self.class) && @name == other.name
|
||||
end
|
||||
|
||||
@@ -88,7 +81,7 @@ end
|
||||
|
||||
class ServiceManager
|
||||
# secure services are randomly selected from the definitions in services.xml (secure_services)
|
||||
# based on the attributes optionally specified in boxes.xml (want_services)
|
||||
# based on the attributes optionally specified in scenario.xml (want_services)
|
||||
# However, if the service type has already had a vulnerability assigned (selected_vulns), it is ignored here
|
||||
def self.process(want_services, secure_services, selected_vulns=[])
|
||||
return_services = {}
|
||||
@@ -116,7 +109,7 @@ class ServiceManager
|
||||
end
|
||||
|
||||
if search_list.length == 0
|
||||
STDERR.puts "Matching service was not found please check the xml boxes.xml"
|
||||
STDERR.puts "Matching service was not found please check the xml scenario.xml"
|
||||
STDERR.puts "(note: you can only have one of each type of service per system)"
|
||||
exit
|
||||
else
|
||||
@@ -135,13 +128,13 @@ class ServiceManager
|
||||
end
|
||||
|
||||
class NetworkManager
|
||||
# the user will either specify a blank network type or a knownnetwork type
|
||||
# the user will either specify a blank misc type or a knownnetwork type
|
||||
def self.process(networks,valid_network)
|
||||
new_networks = {}
|
||||
# intersection of valid networks / user defined networks
|
||||
legal_networks = valid_network & networks
|
||||
networks.each do |network|
|
||||
# checks to see string is blank if so valid network into a new hash map of vulnerabilities
|
||||
# checks to see string is blank if so valid misc into a new hash map of vulnerabilities
|
||||
if network.name == ""
|
||||
random = valid_network.sample
|
||||
new_networks[random.id] = random
|
||||
@@ -151,14 +144,14 @@ class NetworkManager
|
||||
legal_networks.shuffle.each do |valid|
|
||||
if network.name == valid.name
|
||||
network.range = valid.range unless not network.range.empty?
|
||||
# valid network into a new hash map of networks
|
||||
# valid misc into a new hash map of networks
|
||||
new_networks[network.id] = network
|
||||
has_found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not has_found
|
||||
p "Network was not found please check the xml boxes.xml"
|
||||
p "Network was not found please check the xml scenario.xml"
|
||||
exit
|
||||
end
|
||||
end
|
||||
@@ -181,83 +174,8 @@ class BaseManager
|
||||
end
|
||||
end
|
||||
|
||||
class Vulnerability
|
||||
attr_accessor :type, :privilege, :access ,:puppets, :details, :ports, :cve
|
||||
|
||||
def eql? other
|
||||
# checks if type matches vulns.xml from boxes.xml
|
||||
other.kind_of?(self.class) && @type == other.type
|
||||
end
|
||||
|
||||
def hash
|
||||
@type.hash
|
||||
end
|
||||
|
||||
def initialize(type="", privilege="", access="", puppets=[], details="", ports=[], cve="")
|
||||
@type = type
|
||||
@privilege = privilege
|
||||
@access = access
|
||||
@puppets = puppets
|
||||
@details = details
|
||||
@ports = ports
|
||||
@cve = cve
|
||||
end
|
||||
|
||||
def id
|
||||
return @type + @privilege + @access
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class VulnerabilityManager
|
||||
# vulnerabilities are randomly selected from the definitions in vulns.xml (all_vulns)
|
||||
# based on the attributes optionally specified in boxes.xml (want_vulns)
|
||||
def self.process(want_vulns, all_vulns)
|
||||
return_vulns = {}
|
||||
|
||||
legal_vulns = all_vulns.clone
|
||||
want_vulns.each do |vulnerability_query|
|
||||
# select based on selected type, access, cve...
|
||||
|
||||
# copy vulns array
|
||||
search_list = legal_vulns.clone
|
||||
# shuffle order of available vulnerabilities
|
||||
search_list.shuffle!
|
||||
# remove all the vulns that don't match the current selection (type, etc)
|
||||
if vulnerability_query.type.length > 0
|
||||
puts "Searching for vulnerability matching type: " + vulnerability_query.type
|
||||
search_list.delete_if{|x| x.type != vulnerability_query.type}
|
||||
end
|
||||
if vulnerability_query.access.length > 0
|
||||
puts "Searching for vulnerability matching access: " + vulnerability_query.access
|
||||
search_list.delete_if{|x| x.access != vulnerability_query.access}
|
||||
end
|
||||
if vulnerability_query.cve.length > 0
|
||||
puts "Searching for vulnerability matching CVE: " + vulnerability_query.cve
|
||||
search_list.delete_if{|x| x.cve != vulnerability_query.cve}
|
||||
end
|
||||
|
||||
if search_list.length == 0
|
||||
STDERR.puts "Matching vulnerability was not found please check the xml boxes.xml"
|
||||
STDERR.puts "(note: you can only have one of each type of vulnerability per system)"
|
||||
exit
|
||||
else
|
||||
# use from the top of the top of the randomised list
|
||||
return_vulns[vulnerability_query.id] = search_list[0]
|
||||
if search_list[0].type.length > 0
|
||||
puts "Selected vulnerability : " + search_list[0].type
|
||||
end
|
||||
|
||||
# enforce only one of any vulnerability type (remove from available)
|
||||
legal_vulns.delete_if{|x| x.type == vulnerability_query.type}
|
||||
end
|
||||
end
|
||||
return return_vulns.values
|
||||
end
|
||||
end
|
||||
|
||||
class Conf
|
||||
# this class uses nokogiri to grab all of the information from network.xml, bases.xml, and vulns.xml
|
||||
# this class uses nokogiri to grab all of the information from misc.xml, bases.xml, and vulns.xml
|
||||
# then adds them to their specific class to do checking for legal in Manager.process
|
||||
def self.networks
|
||||
if defined? @@networks
|
||||
@@ -1,12 +1,14 @@
|
||||
require_relative 'system.rb'
|
||||
|
||||
require_relative 'objects/vulnerability'
|
||||
require_relative 'helpers/vulnerability_processor'
|
||||
class SystemReader
|
||||
# initializes systems xml from BOXES_XML const
|
||||
def initialize(systems_xml)
|
||||
@systems_xml = systems_xml
|
||||
@vulnerability_processor = VulnerabilityProcessor.new
|
||||
end
|
||||
|
||||
# uses nokogiri to extract all system information from boxes.xml will add it to the system class after
|
||||
# uses nokogiri to extract all system information from scenario.xml will add it to the system class after
|
||||
# checking if the vulnerabilities / networks exist from system.rb
|
||||
def systems
|
||||
systems = []
|
||||
@@ -46,7 +48,7 @@ class SystemReader
|
||||
puts "Processing system: " + id
|
||||
# vulns / networks are passed through to their manager and the program will create valid vulnerabilities / networks
|
||||
# depending on what the user has specified these two will return valid vulns to be used in vagrant file creation.
|
||||
new_vulns = VulnerabilityManager.process(vulns, Conf.vulnerabilities)
|
||||
new_vulns = @vulnerability_processor.process(vulns)
|
||||
#puts new_vulns.inspect
|
||||
|
||||
new_networks = NetworkManager.process(networks, Conf.networks)
|
||||
1
modules/modules
Normal file
1
modules/modules
Normal file
@@ -0,0 +1 @@
|
||||
Vulnerabilities, Services, Users, Bases and Networks will go in here
|
||||
@@ -0,0 +1 @@
|
||||
include vsftpdbackdoor::install
|
||||
@@ -1,4 +1,4 @@
|
||||
#copies and unpacks vsftpd saves it to usr/local/sbin and executes it for startup
|
||||
#copies and unpacks vsftpd_234_backdoor saves it to usr/local/sbin and executes it for startup
|
||||
class vsftpdbackdoor::install {
|
||||
exec { 'unzip-vsftpd':
|
||||
command => 'tar xzf vsftpd-2.3.4.tar.gz && mv vsftpd-2.3.4 /home/vagrant/vsftpd-2.3.4',
|
||||
@@ -0,0 +1,19 @@
|
||||
<vulnerability
|
||||
type="ftp"
|
||||
cve=""
|
||||
privilege="user"
|
||||
access="remote"
|
||||
details="ftpbackdoor smiley face backdoor exploit"
|
||||
platform="unix">
|
||||
<puppets>
|
||||
<puppet>install.pp</puppet>
|
||||
<puppet>ftpbackdoor.pp</puppet>
|
||||
</puppets>
|
||||
<files>
|
||||
<file>vsftpd-2.3.4.tar.gz</file>
|
||||
</files>
|
||||
<scripts>
|
||||
<script>copyvsftpd.sh</script>
|
||||
<script>startvsftpd.sh</script>
|
||||
</scripts>
|
||||
</vulnerability>
|
||||
@@ -11,7 +11,7 @@ class distcc::config {
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0777',
|
||||
content => template('distcc/distcc.erb')
|
||||
content => template('../data/distcc.erb')
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<vulnerability
|
||||
type="distcc"
|
||||
cve="CVE-2004-2687"
|
||||
privilege="user"
|
||||
access="remote"
|
||||
details="distcc can be exploited by exploit/unix/misc/distcc_exec"
|
||||
platform="unix">
|
||||
<puppets>
|
||||
<puppet>distcc.pp</puppet>
|
||||
</puppets>
|
||||
<files>
|
||||
<file>distcc.erb</file>
|
||||
</files>
|
||||
<scripts>
|
||||
</scripts>
|
||||
</vulnerability>
|
||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
class { 'vsftpd':
|
||||
anonymous_enable => 'YES',
|
||||
write_enable => 'YES',
|
||||
ftpd_banner => 'Marmotte FTP Server',
|
||||
chroot_local_user => 'YES',
|
||||
}
|
||||
|
||||
include vsftpd
|
||||
@@ -5,10 +5,13 @@
|
||||
path => "/bin/",
|
||||
}
|
||||
# finds every file and modifies with date may 2006
|
||||
exec { "find":
|
||||
command => "find / -exec touch -d '17 May 2006 14:16' {} \\;",
|
||||
path => "/usr/bin/",
|
||||
}
|
||||
# todo: CW - find a way to do this quicker, as it takes the most of the time when spinning up a vm, also commented out for testing purposes
|
||||
# exec { "find":
|
||||
# command => "find / -exec touch -d '17 May 2006 14:16' {} \\;",
|
||||
# path => "/usr/bin/",
|
||||
# timeout => 5000
|
||||
# }
|
||||
|
||||
# disables eth1 which runs the public network for each vulnerable machine
|
||||
# vagrant runs over 10.0 for eth0 .. eth1 for public .. and eth2 for private.
|
||||
|
||||
@@ -17,12 +20,14 @@
|
||||
path => "/sbin/",
|
||||
}
|
||||
# changes default vagrant password, would kind of be pointless if they could just ssh to vagrant/vagrant :P
|
||||
# this never worked.
|
||||
# user {
|
||||
# 'vagrant':
|
||||
# ensure => present,
|
||||
# password => 'superdupersecurepassword',
|
||||
# }
|
||||
|
||||
user { 'vagrant':
|
||||
password => 'superdupersecurepassword',
|
||||
}
|
||||
|
||||
# or you can remove the user entierly, up to you 'but if you are playing around with vagrant might cause problems'
|
||||
# or you can remove the user entierly, up to you 'but i you are playing around with vagrant might cause problems'
|
||||
#use this option only when you are rolling out to users.
|
||||
|
||||
# user { 'vagrant':
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
# Security Simulator
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
# This program allows you to use a large amount of virtual machines and install vulnerable software to create a learning environment.
|
||||
#
|
||||
# By: Lewis Ardern (Leeds Metropolitan University)
|
||||
|
||||
require 'getoptlong'
|
||||
require 'fileutils'
|
||||
require_relative 'system.rb'
|
||||
require_relative 'filecreator.rb'
|
||||
require_relative 'systemreader.rb'
|
||||
require_relative 'vagrant.rb'
|
||||
require_relative 'lib/constants'
|
||||
require_relative 'lib/filecreator.rb'
|
||||
require_relative 'lib/systemreader.rb'
|
||||
require_relative 'lib/vagrant.rb'
|
||||
|
||||
puts 'SecGen - Creates virtualised security scenarios'
|
||||
puts 'Licensed GPLv3 2014-16'
|
||||
@@ -34,8 +24,8 @@ end
|
||||
def build_config
|
||||
puts 'Reading configuration file for virtual machines you want to create'
|
||||
|
||||
# uses nokogoiri to grab all the system information from boxes.xml
|
||||
systems = SystemReader.new(BOXES_XML).systems
|
||||
# uses nokogoiri to grab all the system information from scenario.xml
|
||||
systems = SystemReader.new(SCENARIO_XML).systems
|
||||
|
||||
puts 'Creating vagrant file'
|
||||
# create's vagrant file / report a starts the vagrant installation'
|
||||
@@ -1,6 +1,6 @@
|
||||
require "test/unit"
|
||||
require 'nokogiri'
|
||||
require_relative "../../system.rb"
|
||||
require_relative "../system.rb"
|
||||
#http://ruby-doc.org/stdlib-2.0.0/libdoc/test/unit/rdoc/Test/Unit/Assertions.html
|
||||
|
||||
class TestXMLIsEqual < Test::Unit::TestCase
|
||||
@@ -17,7 +17,7 @@ class TestXMLIsEqual < Test::Unit::TestCase
|
||||
vulns = system.css('vulnerabilities vulnerability').collect do |v|
|
||||
Vulnerability.new(v[:type],v[:privilege],v[:access],v[:puppet],v[:details])
|
||||
end
|
||||
networks = system.css('networks network').collect { |n| n['name'] }
|
||||
networks = system.css('networks misc').collect { |n| n['name'] }
|
||||
|
||||
@systems << System.new(id, os, base, vulns, networks)
|
||||
end
|
||||
91
tests/helpers/vulnerability_processor_tests.rb
Normal file
91
tests/helpers/vulnerability_processor_tests.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
require 'minitest/autorun'
|
||||
require '../../lib/helpers/vulnerability_processor'
|
||||
require '../../lib/objects/vulnerability'
|
||||
class VulnerabilityProcessorTests < MiniTest::Test
|
||||
|
||||
def setup
|
||||
@sut = VulnerabilityProcessor.new
|
||||
#Array of Vulnerabilities
|
||||
@want_xml = Array.new
|
||||
@all_vuln_xml = Array.new
|
||||
end
|
||||
|
||||
def test_when_given_one_vulnerability_should_return_one_vulnerability
|
||||
#arrange
|
||||
vulnerability = Vulnerability.new
|
||||
vulnerability.type = 'ftp'
|
||||
vulnerability.access = 'remote'
|
||||
|
||||
@want_xml.push(vulnerability)
|
||||
|
||||
#act
|
||||
result = @sut.process(@want_xml)
|
||||
|
||||
#assert
|
||||
|
||||
assert(result.is_a?(Array), msg = 'The returned value is not an array')
|
||||
assert_equal(result.count, 1, msg= 'The returned count is less than 1')
|
||||
assert(result[0].is_a?(Vulnerability), msg = 'The first value is not a type of Vulnerability')
|
||||
assert_equal(result[0].type, 'ftp', msg= 'The type is not ftp')
|
||||
assert_equal(result[0].access, 'remote', msg= 'The access is not remote')
|
||||
end
|
||||
|
||||
def test_when_given_vulnerability_with_cve_should_return_full_vulnerability
|
||||
#arrange
|
||||
vulnerability = Vulnerability.new
|
||||
vulnerability.cve = 'CVE-2004-2687'
|
||||
@want_xml.push(vulnerability)
|
||||
|
||||
#act
|
||||
result = @sut.process(@want_xml)
|
||||
|
||||
#assert
|
||||
|
||||
assert(result.is_a?(Array), msg = 'The returned value is not an array')
|
||||
assert_equal(result.count, 1, msg= 'The returned count is less than 1')
|
||||
assert(result[0].is_a?(Vulnerability), msg = 'The first value is not a type of vulnerability')
|
||||
assert_equal(result[0].type, 'distcc', msg= 'The type is not distcc')
|
||||
assert_equal(result[0].access, 'remote', msg= 'The access is not remote')
|
||||
end
|
||||
|
||||
def test_when_given_multiple_vulnerabilities_should_return_multiple_vulnerabilities
|
||||
#arrange
|
||||
vulnerability = Vulnerability.new
|
||||
vulnerability.type = 'ftp'
|
||||
vulnerability.access = 'remote'
|
||||
@want_xml.push(vulnerability)
|
||||
vulnerability = Vulnerability.new
|
||||
vulnerability.cve = 'CVE-2004-2687'
|
||||
@want_xml.push(vulnerability)
|
||||
#act
|
||||
result = @sut.process(@want_xml)
|
||||
|
||||
#assert
|
||||
|
||||
assert(result.is_a?(Array), msg = 'The returned value is not an array')
|
||||
assert_equal(result.count, 2, msg= 'The returned count is less than 1')
|
||||
assert(result[0].is_a?(Vulnerability), msg = 'The first value is not a type of hash')
|
||||
|
||||
end
|
||||
|
||||
def test_when_given_multiple_vulnerabilities_of_same_type_should_return_single_vulnerability
|
||||
#arrange
|
||||
vulnerability = Vulnerability.new
|
||||
vulnerability.type = 'ftp'
|
||||
vulnerability.access = 'remote'
|
||||
@want_xml.push(vulnerability)
|
||||
@want_xml.push(vulnerability)
|
||||
|
||||
#act
|
||||
result = @sut.process(@want_xml)
|
||||
|
||||
#assert
|
||||
|
||||
assert(result.is_a?(Array), msg = 'The returned value is not an array')
|
||||
assert_equal(result.count, 1, msg= 'The returned count is less than 1')
|
||||
assert(result[0].is_a?(Vulnerability), msg = 'The first value is not a type of hash')
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -5,5 +5,5 @@
|
||||
</base>
|
||||
<base name="puppettest" os="linux" distro="unknown" url="http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210.box" vagrantbase="puppettest" >
|
||||
</base>
|
||||
</base>
|
||||
</bases>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
<network name="homeonly" range="172.16.0.0"></network>
|
||||
<network name="homeonly1" range="172.17.0.0"></network>
|
||||
<network name="homeonly2" range="172.18.0.0"></network>
|
||||
</network>
|
||||
</networks>
|
||||
@@ -52,16 +52,7 @@
|
||||
<puppet>writeableshadow</puppet>
|
||||
</puppets>
|
||||
</vulnerability>
|
||||
<vulnerability
|
||||
type="distcc"
|
||||
cve="CVE-2004-2687"
|
||||
privilege="user"
|
||||
access="remote"
|
||||
details="distcc can be exploited by exploit/unix/misc/distcc_exec">
|
||||
<puppets>
|
||||
<puppet>distcc</puppet>
|
||||
</puppets>
|
||||
</vulnerability>
|
||||
|
||||
<vulnerability
|
||||
type="ftp"
|
||||
cve=""
|
||||
Reference in New Issue
Block a user