(WiP) Created proftpd_133c_backdoor testing script - Needs testing!

This commit is contained in:
ts
2019-02-02 01:27:50 +00:00
parent 1c4a9aebf1
commit 1fffa4b05c
6 changed files with 158 additions and 3 deletions

View File

@@ -0,0 +1,91 @@
# Post Provision Testing
#
# This file will be copied into each project folder at creation time.
# It will be required from each of the modules/secgen_tests/module_name.rb test scripts
#
# Test classes must: require_relative '../../../../../lib/post_provision_test'
require_relative "../../../lib/helpers/print.rb"
require 'json'
require 'base64'
require 'socket'
require 'timeout'
class PostProvisionTest
attr_accessor :project_path
attr_accessor :system_ip
attr_accessor :module_name
attr_accessor :module_path
attr_accessor :json_inputs
def initialize
# self.project_path =
end
def run
Print.info "Running tests for #{self.module_name}"
test_module
end
def test_module
# Override me with testing details
end
def get_system_ip(module_file_path)
# Get Vagrantfile
end
def get_json_inputs
json_inputs_path = "#{File.expand_path('../', self.module_path)}/secgen_functions/files/json_inputs/*"
Print.info "json_inputs_path: #{json_inputs_path}"
json_inputs_files = Dir.glob(json_inputs_path)
Print.info "json_input_files (pre delete): #{json_inputs_files}"
json_inputs_files.delete_if { |path| !path.include?(self.module_name) }
Print.info "json_input_files (post delete): #{json_inputs_files}"
JSON.parse(Base64.strict_decode64(File.read(json_inputs_files.first)))
end
# Pass __FILE__ in from subclasses
def get_module_path(file_path)
"#{File.expand_path('..', File.dirname(file_path))}"
end
# Note: returns proftpd_testing
def get_system_name
get_system_path.match(/.*?([^\/]*)$/i).captures[0]
end
# Note: returns /home/thomashaw/git/SecGen/projects/SecGen20190202_010552/puppet/proftpd_testing
def get_system_path
"#{File.expand_path('../../', self.module_path)}"
end
# Note: returns /home/thomashaw/git/SecGen/projects/SecGen20190202_010552/
def get_project_path
"#{File.expand_path('../../../../', self.module_path)}"
end
##############################
## Useful testing functions ##
##############################
def is_port_open?(ip, port)
begin
Timeout::timeout(1) do
begin
s = TCPSocket.new(ip, port)
s.close
return true
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
return false
end
end
rescue Timeout::Error
# ignored
end
false
end
end

View File

@@ -172,6 +172,10 @@ class ProjectFilesCreator
abort
end
# Copy the test superclass into the project/lib directory
Print.std "Copying post-provision testing class"
FileUtils.mkdir("#{@out_dir}/lib")
FileUtils.cp("#{ROOT_DIR}/lib/objects/post_provision_test.rb", "#{@out_dir}/lib/post_provision_test.rb")
Print.std "VM(s) can be built using 'vagrant up' in #{@out_dir}"

View File

@@ -161,7 +161,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
b64_json_inputs = Base64.strict_encode64(json_inputs)
# save the inputs in a randomly named file in the
# project out directory of the secgen_functions module
json_inputs_filename = "#{module_name}_#{SecureRandom.hex(15).to_s}"
json_inputs_filename = "#{selected_module.module_path_end}_#{SecureRandom.hex(15).to_s}"
dir = "#{@out_dir}/puppet/#{system.name}/modules/secgen_functions/files/json_inputs"
FileUtils.mkdir_p(dir) unless File.exists?(dir)
Print.verbose "Writing #{selected_module.module_path_name} input to: #{dir}/#{json_inputs_filename}"

View File

@@ -0,0 +1,30 @@
require_relative '../../../../../lib/post_provision_test'
class Proftpd133cBackdoorTest < PostProvisionTest
attr_accessor :ftp_port
def initialize
super
self.module_name = 'proftpd_133c_backdoor'
self.module_path = get_module_path(__FILE__)
self.json_inputs = get_json_inputs
self.ftp_port = get_json_inputs['port'].to_i
# Print.info self.json_inputs
# Print.info "get_system_name: #{get_system_name}"
# Print.info "get_system_path: #{get_system_path}"
# Print.info "get_project_path: #{get_project_path}"
end
def test_module
# TODO: Need to determine how to handle the output... see other Open3.capture3 module and stdout print pass/fail perhaps?
# TODO: Raise an exception? Return false? Print the PASSED / FAILED only?
if is_port_open? "172.16.0.5", "21"
Print.info "PASSED: Port #{ftp_port} is open on #{get_system_name}!"
else
Print.err "FAILED: Port #{ftp_port} is closed on #{get_system_name}!"
end
end
end
Proftpd133cBackdoorTest.new.run

View File

@@ -4,8 +4,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
<system>
<system_name>empty_stretch</system_name>
<base platform="linux" distro="Debian 9" type="server"/>
<system_name>proftpd_testing</system_name>
<base platform="linux" distro="Debian 7.8" type="server"/>
<vulnerability module_path=".*proftpd_133c_backdoor"/>
<input into_datastore="IP_addresses">
<value>172.16.0.5</value>

View File

@@ -118,6 +118,8 @@ def build_vms(scenario, project_dir, options)
while retry_count and !successful_creation
vagrant_output = GemExec.exe('vagrant', project_dir, "#{command} #{system}")
if vagrant_output[:status] == 0
shutdown_cycle(project_dir)
post_provision_tests(project_dir)
Print.info 'VMs created.'
successful_creation = true
if options[:shutdown] or OVirtFunctions::provider_ovirt?(options)
@@ -329,6 +331,32 @@ def get_vm_names(scenario)
vm_names
end
def shutdown_cycle(project_dir)
Print.info 'Shutting down VMs.'
sleep(30)
GemExec.exe('vagrant', project_dir, 'halt')
sleep 5
GemExec.exe('vagrant',project_dir,'up')
sleep 30
end
def post_provision_tests(project_dir)
# Get project files
Print.err "project_dir: #{project_dir}"
# Get system names
test_script_paths = Dir.glob("#{project_dir}/puppet/*/modules/*/secgen_test/*.rb")
test_script_paths.each {|test_file_path|
output = `bundle exec ruby #{test_file_path}`
Print.info output
if output.include? "FAILED"
raise "Post provision failure!"
end
}
Print.info 'Running post-provision tests...'
end
# end of method declarations
# start of program execution