Files
SecGen/lib/objects/system.rb
2016-06-12 00:21:12 +01:00

101 lines
3.9 KiB
Ruby

class System
attr_accessor :name
attr_accessor :attributes # (basebox selection)
attr_accessor :module_selectors # (filters)
attr_accessor :module_selections # (after resolution)
# Initalizes System object
# @param [Object] name of the system
# @param [Object] attributes such as base box selection
# @param [Object] module_selectors these are modules that define filters for selecting the actual modules to use
def initialize(name, attributes, module_selectors)
self.name = name
self.attributes = attributes
self.module_selectors = module_selectors
self.module_selections = []
end
# selects from the available modules, based on the selection filters that have been specified
# @param [Object] available_modules all available modules (vulnerabilities, services, bases)
# @param [Object] recursion_count (retry count -- used for resolving conflicts by bruteforce randomisation)
# @return [Object] the list of selected modules
def resolve_module_selection(available_modules, recursion_count)
selected_modules = []
num_actioned_module_conflicts = 0
# for each module specified in the scenario
module_selectors.each do |module_filter|
# select based on selected type, access, cve...
search_list = available_modules.clone
# shuffle order of available vulnerabilities
search_list.shuffle!
# remove any not the type of module we are adding (vulnerabilty/service)
search_list.delete_if{|x| "#{x.module_type}_selecter" != module_filter.module_type}
# remove non-options due to conflicts
search_list.delete_if{|module_for_possible_exclusion|
found_conflict = false
selected_modules.each do |prev_selected|
if module_for_possible_exclusion.conflicts_with(prev_selected) ||
prev_selected.conflicts_with(module_for_possible_exclusion)
Print.verbose "Excluding incompatible module: #{module_for_possible_exclusion.module_path}"
num_actioned_module_conflicts += 1
found_conflict = true
end
end
found_conflict
}
# for each filter to apply for this module
module_filter.attributes.keys.each do |filter_attribute_key|
search_for = module_filter.attributes[filter_attribute_key]
if search_for != nil && search_for !=''
search_list.delete_if{|module_for_possible_exclusion|
found_match = false
if module_for_possible_exclusion.attributes["#{filter_attribute_key}"] != nil
module_for_possible_exclusion.attributes["#{filter_attribute_key}"].each do |value|
# Print.verbose "comparing #{value} and #{search_for}"
if Regexp.new(search_for).match(value)
found_match = true
end
end
else
found_match = true
end
!found_match
}
Print.verbose "Filtered to modules matching: #{filter_attribute_key} ~= #{search_for} (->#{search_list.size})"
else
true
end
end
if search_list.length == 0
Print.err 'Could not find a matching module. Please check the scenario specification'
# bruteforce conflict resolution (could be more intelligent)
if recursion_count < 10 && num_actioned_module_conflicts > 0
Print.err "During scenario generation #{num_actioned_module_conflicts} module conflict(s) occured..."
Print.err 'Re-attempting to resolve scenario...'
return resolve_module_selection(available_modules, recursion_count + 1)
else
exit
end
end
# use from the top of the randomised list
selected = search_list[0]
Print.std "Selected module: #{selected.attributes['name'][0]} (#{selected.module_path})"
to_add = selected.clone
to_add.select_inputs
# resolve randomness of inputs
selected_modules.push to_add
end
selected_modules
end
end