def test_random_array(): obj = ba_random() l = [1, 2, 3, 4, 5] for i in range(400): val = obj.array_random(l) assert val in l assert val == 1 or val == 2 or val == 3 or val == 4 or val == 5
def test_will_do(): obj = ba_random() truecount = 0 falsecount = 0 for i in range(400): val = obj.will_do() assert val == True or val == False if val == True: truecount += 1 elif val == False: falsecount += 1 assert truecount > 0 assert falsecount > 0
def __load_provides(self, provides_string, restriction_list): choose_list = [] for module in module_util.get_module_list(): current_module = module_util.import_module(module) if current_module.has_provides( provides_string) and current_module.get_class_name( ) not in restriction_list: # If the module we selected is already loaded (but not processed), use it if current_module.get_class_name( ) in self.__name_map and self.__name_map[ current_module.get_class_name()] != None: self.__provides_map[ provides_string] = current_module.get_class_name() return self.__name_map[current_module.get_class_name()] else: choose_list.append(module) if choose_list == 0: return None selected_module_name = ba_random().array_random(choose_list) selected_module = module_util.import_module(selected_module_name) if selected_module == None: return None # Set the provides mapping self.__provides_map[provides_string] = selected_module.get_class_name() self.__insert_module(selected_module.get_class_name(), selected_module) return self.__name_map[selected_module.get_class_name()]
def __load_provides(self, provides_string, restriction_list): choose_list = [] for module in module_util.get_module_list(): current_module = module_util.import_module(module) if current_module.has_provides(provides_string) and current_module.get_class_name() not in restriction_list: # If the module we selected is already loaded (but not processed), use it if current_module.get_class_name() in self.__name_map and self.__name_map[current_module.get_class_name()] != None: self.__provides_map[provides_string] = current_module.get_class_name() return self.__name_map[current_module.get_class_name()] else: choose_list.append(module) if choose_list == 0: return None selected_module_name = ba_random().array_random(choose_list) selected_module = module_util.import_module(selected_module_name) if selected_module == None: return None # Set the provides mapping self.__provides_map[provides_string] = selected_module.get_class_name() self.__insert_module(selected_module.get_class_name(), selected_module) return self.__name_map[selected_module.get_class_name()]
def test_random_string(): obj = ba_random() for i in range(400): val = obj.random_string(2, 10) assert len(val) >= 2 and len(val) <= 10
def test_random_number(): obj = ba_random() for i in range(400): num = obj.random_number(0, 10) assert num >= 0 and num <= 10
def __resolve_vuln(self, module_obj, depth, vuln_object, ver_restrictions=[], dep_restrictions=[]): front = "\t " * depth if self.__debug: print(front + "V: Processing " + module_obj.get_class_name() + "." + vuln_object.name()) print(front + "------------------------------------------\n") dep_list = vuln_object.get_dependencies() if len(dep_list) > 0: for dep in dep_list: if self.__debug: print(front + "V: Dependency: ") for item in dep.get_links(): print(front + " " + str(item)) dep_done = False # List for ORed vulnerabilities of provides strings that have failed failed_ps_list = [] # Loop until a valid module for the dependency is loaded while dep_done == False: selected_dep_ps = None selected_dep_range = None # Check if the dependency has mutiple matchable values (is OR) if dep.is_or(): dep_choice_list = dep.get_links() dep_valid_list = [] # Remove from the running any provides strings that have failed for dep_choice in dep_choice_list: if not dep_choice[0] in failed_ps_list: dep_valid_list.append(dep_choice) # Check if the OR has failed on all counts, if so fail the vuln if len(dep_valid_list) == 0: return False # If so, check to see if any of the provides strings are already loaded, and use them if so for dep_choice in dep_valid_list: if dep_choice[0] in self.__provides_map: selected_dep_ps = dep_choice.provides_string selected_dep_range = dep_choice.version_range # If no existing values were found, then select a random one if selected_dep_ps == None: choice_sel = ba_random().array_random( dep_valid_list) selected_dep_ps = choice_sel.provides_string selected_dep_range = choice_sel.version_range # If not OR, just get the strings else: link = dep.get_links()[0] selected_dep_ps = link.provides_string selected_dep_range = link.version_range if self.__debug: print( front + "V: Looking for a dependency that can provide: " + selected_dep_ps + " - " + str(selected_dep_range)) # If no other module that provides the string, load a module that does if selected_dep_ps not in self.__provides_map: provides_done = False # Modules that were tried to provide the necessary provides_string, but failed to resolve failed_modules = [] # Loop until we load a resolvable module that provides the given provides string while provides_done == False: # Get a module to attempt to use dep_module = self.__load_provides( selected_dep_ps, failed_modules) # Could not get a module that provides the dependency that works if dep_module == None: if dep.is_or(): failed_ps_list.append(selected_dep_ps) provides_done = True else: self.__add_faulting_module( "PS:" + selected_dep_ps, "Could not load module for " + selected_dep_ps) return False else: if self.__debug: print(front + "V: Loaded module " + dep_module.get_class_name() + " to provide " + selected_dep_ps) self.__add_parent(module_obj.get_class_name(), dep_module.get_class_name()) # Add the restriction given by the dependency definition dep_module.add_version_restriction( selected_dep_ps, selected_dep_range) result = self.__resolve_module( dep_module, depth + 1, ver_restrictions + module_obj.get_dependency_restrictions()) if result == True: dep_done = True provides_done = True else: if self.__debug: print(front + "V: Module failed to resolve") if not dep_module in failed_modules: failed_modules.append( dep_module.get_class_name()) self.__remove_child_tree( dep_module.get_class_name()) dep_module._clear_restrictions() else: dep_done = True # A module with that provides string has been loaded and presumably processed. Use it provides_module = self.__name_map[ self.__provides_map[selected_dep_ps]] # Check if dependency is parent to the dependency's parent (circular dependence) if self.__in_parent_path( module_obj.get_class_name(), provides_module.get_class_name()): self.__add_faulting_module( module_obj.get_class_name(), "Circular dependency detected") return False # Check if the dependency module has already been processed if provides_module.get_class_name( ) in self.__processed: # If so, we need to check if we need to reprocess the tree # First create list of dependency restrictions that are for this dependency for dep_restriction in vuln.get_dependency_restrictions( ): if dep_restriction.provides_string( ) == self.__provides_map[selected_dep_ps]: provides_module._add_temp_dependency_restriction( dep_restriction) # Check if with the new restrictions the module doesn't need to be changed if provides_module.still_valid(): # If so, convert the temp restictions into permanent ones provides_module.commit_temp_dependency_restrictions( ) # Clear the temp restrictions provides_module.clear_temp_dependency_restrictions( ) # If the vulnerabilities in the dependency are no longer possible, here's where things get interesting else: # First check if the module has any child modules (already processed dependencies) if self.__has_children( provides_module.get_class_name()): # If so, remove them self.__remove_child_tree( provides_module.get_class_name()) # Check if the module is a dependency for anything else, because the vulnerabilities that it provided are now invalid if not self.__has_parents( provides_module.get_class_name()): # If not, things are a lot simpler # Add the current restrictions to the child module provides_module.commit_temp_dependency_restrictions( ) # Clear the temp restrictions provides_module.clear_temp_dependency_restrictions( ) # Reprocess the child module result = self.__resolve_module( provides_module, depth + 1) if result == False: return False else: # If not, we must figure out how to get both parent modules to give valid restrictions if possible # TODO: Change his algorithm to something better pass # Current Algorithm: Randomly select one of modules to set its current vulnerabilities and restrict them # This still has possibility of leaving out valid combinations, and also not working at all select_list = self.__parent_map[ provides_module.get_class_name()] + [ module_obj.get_class_name() ] selection = ba_random().array_random( select_list) self.__name_map[ selection].negate_selections() self.__restarting = True else: error_message = "Invalid state, '" + selected_dep_ps + "' is set, but the module has not been resolved" self.__add_faulting_module( provides_module.get_class_name(), error_message) if self.__debug: print(error_message) return False return True else: return True
def __resolve_vuln(self, module_obj, depth, vuln_object, ver_restrictions=[], dep_restrictions=[]): front = "\t " * depth if self.__debug: print(front + "V: Processing " + module_obj.get_class_name() + "." + vuln_object.name()) print(front + "------------------------------------------\n") dep_list = vuln_object.get_dependencies() if len(dep_list) > 0: for dep in dep_list: if self.__debug: print(front + "V: Dependency: ") for item in dep.get_links(): print(front + " " + str(item)) dep_done = False # List for ORed vulnerabilities of provides strings that have failed failed_ps_list = [] # Loop until a valid module for the dependency is loaded while dep_done == False: selected_dep_ps = None selected_dep_range = None # Check if the dependency has mutiple matchable values (is OR) if dep.is_or(): dep_choice_list = dep.get_links() dep_valid_list = [] # Remove from the running any provides strings that have failed for dep_choice in dep_choice_list: if not dep_choice[0] in failed_ps_list: dep_valid_list.append(dep_choice) # Check if the OR has failed on all counts, if so fail the vuln if len(dep_valid_list) == 0: return False # If so, check to see if any of the provides strings are already loaded, and use them if so for dep_choice in dep_valid_list: if dep_choice[0] in self.__provides_map: selected_dep_ps = dep_choice.provides_string selected_dep_range = dep_choice.version_range # If no existing values were found, then select a random one if selected_dep_ps == None: choice_sel = ba_random().array_random(dep_valid_list) selected_dep_ps = choice_sel.provides_string selected_dep_range = choice_sel.version_range # If not OR, just get the strings else: link = dep.get_links()[0] selected_dep_ps = link.provides_string selected_dep_range = link.version_range if self.__debug: print(front + "V: Looking for a dependency that can provide: " + selected_dep_ps + " - " + str(selected_dep_range)) # If no other module that provides the string, load a module that does if selected_dep_ps not in self.__provides_map: provides_done = False # Modules that were tried to provide the necessary provides_string, but failed to resolve failed_modules = [] # Loop until we load a resolvable module that provides the given provides string while provides_done == False: # Get a module to attempt to use dep_module = self.__load_provides(selected_dep_ps, failed_modules) # Could not get a module that provides the dependency that works if dep_module == None: if dep.is_or(): failed_ps_list.append(selected_dep_ps) provides_done = True else: self.__add_faulting_module("PS:" + selected_dep_ps, "Could not load module for " + selected_dep_ps) return False else: if self.__debug: print(front + "V: Loaded module " + dep_module.get_class_name() + " to provide " + selected_dep_ps) self.__add_parent(module_obj.get_class_name(), dep_module.get_class_name()) # Add the restriction given by the dependency definition dep_module.add_version_restriction(selected_dep_ps, selected_dep_range) result = self.__resolve_module(dep_module, depth + 1, ver_restrictions + module_obj.get_dependency_restrictions()) if result == True: dep_done = True provides_done = True else: if self.__debug: print(front + "V: Module failed to resolve") if not dep_module in failed_modules: failed_modules.append(dep_module.get_class_name()) self.__remove_child_tree(dep_module.get_class_name()) dep_module._clear_restrictions() else: dep_done = True # A module with that provides string has been loaded and presumably processed. Use it provides_module = self.__name_map[self.__provides_map[selected_dep_ps]] # Check if dependency is parent to the dependency's parent (circular dependence) if self.__in_parent_path(module_obj.get_class_name() ,provides_module.get_class_name()): self.__add_faulting_module(module_obj.get_class_name(), "Circular dependency detected") return False # Check if the dependency module has already been processed if provides_module.get_class_name() in self.__processed: # If so, we need to check if we need to reprocess the tree # First create list of dependency restrictions that are for this dependency for dep_restriction in vuln.get_dependency_restrictions(): if dep_restriction.provides_string() == self.__provides_map[selected_dep_ps]: provides_module._add_temp_dependency_restriction(dep_restriction) # Check if with the new restrictions the module doesn't need to be changed if provides_module.still_valid(): # If so, convert the temp restictions into permanent ones provides_module.commit_temp_dependency_restrictions() # Clear the temp restrictions provides_module.clear_temp_dependency_restrictions() # If the vulnerabilities in the dependency are no longer possible, here's where things get interesting else: # First check if the module has any child modules (already processed dependencies) if self.__has_children(provides_module.get_class_name()): # If so, remove them self.__remove_child_tree(provides_module.get_class_name()) # Check if the module is a dependency for anything else, because the vulnerabilities that it provided are now invalid if not self.__has_parents(provides_module.get_class_name()): # If not, things are a lot simpler # Add the current restrictions to the child module provides_module.commit_temp_dependency_restrictions() # Clear the temp restrictions provides_module.clear_temp_dependency_restrictions() # Reprocess the child module result = self.__resolve_module(provides_module, depth + 1) if result == False: return False else: # If not, we must figure out how to get both parent modules to give valid restrictions if possible # TODO: Change his algorithm to something better pass # Current Algorithm: Randomly select one of modules to set its current vulnerabilities and restrict them # This still has possibility of leaving out valid combinations, and also not working at all select_list = self.__parent_map[provides_module.get_class_name()] + [module_obj.get_class_name()] selection = ba_random().array_random(select_list) self.__name_map[selection].negate_selections() self.__restarting = True else: error_message = "Invalid state, '" + selected_dep_ps +"' is set, but the module has not been resolved" self.__add_faulting_module(provides_module.get_class_name(), error_message) if self.__debug: print(error_message) return False return True else: return True
def __module(self, options): if len(options) == 0: print("Incomplete command") print( "Valid sub-commands: add, remove, info, list, random, force, test" ) else: subcommand = options[0] del options[0] if subcommand == "add": if not len(options) == 1: print("module add: No module name") else: module_name = options[0] if module_util.module_exists(module_name): if not module_name in self.__vars['to_run']['value']: self.__vars['to_run']['value'].append(module_name) print("Module added") else: print("Module is already set to be run") else: print("Module '" + module_name + "' does not exist") elif subcommand == "random": rand_list = [] self.__vars['to_run']['value'] = [] while len(rand_list) == 0: mod_list = module_util.get_module_list() set_level = self.__vars['level']['value'] for module in mod_list: # Skip the test module if module == "test_module": continue mod_obj = module_util.import_module(module) if mod_obj: if set_level == "any": if ba_random().will_do(): rand_list.append(module) else: if mod_obj.has_difficulty( set_level) and ba_random().will_do(): rand_list.append(module) else: print("Could not import module " + module) for module_name in rand_list: self.__vars['to_run']['value'].append(module_name) elif subcommand == "remove": if not len(options) == 1: print("module add: No module set") else: module_name = options[0] if module_util.module_exists(module_name): if module_name in self.__vars['to_run']['value']: self.__vars['to_run']['value'].remove(module_name) print("Module removed") else: print("Module is not set to run") else: print("Module '" + module_name + "' does not exist") elif subcommand == "info": if not len(options) == 1: print("module info: No module name") else: module_name = options[0] if module_util.module_exists(module_name): tmp_module = module_util.import_module(module_name) print(tmp_module.info()) print("Vulnerabilities:") for vuln in tmp_module.full_vulnerability_list(): print(" " + vuln) else: print("Module '" + module_name + "' does not exist") elif subcommand == "list": module_list = module_util.get_module_list() if len(module_list) > 0: for item in module_list: if item == "test_module": continue if item in self.__vars['to_run']['value']: print("\t+ " + item) else: print("\t- " + item) else: print("\nNo modules are set to run!") elif subcommand == "force": if not len(options) == 2: print("Enter a module and vulnerability to force") else: module = options[0] vuln = options[1] if module_util.module_exists(module): if vuln in module_util.import_module( module).full_vulnerability_list(): if not module in self.__vars['force']['value']: self.__vars['force']['value'][module] = [] if not vuln in self.__vars['force']['value'][ module]: self.__vars['force']['value'][module].append( vuln) else: print( "That vulnerability is already being forced" ) else: print("Module '" + module + "' does not have the vulnerability '" + vuln + "'") else: print("Module '" + module + "' does not exist") elif subcommand == "test": if self.__debug_mode == False: print("'module test' can only be used in debug mode") elif not len(options) == 2: print("Enter a module and vulnerability to test") else: module = options[0] vuln = options[1] if module_util.module_exists(module): module_obj = module_util.import_module(module) if vuln in module_obj.full_vulnerability_list(): result = module_obj.test(vuln) if result == False: print("Test failed") else: print("Test succeeded") else: print("Module '" + module + "' does not have the vulnerability '" + vuln + "'") else: print("Module '" + module + "' does not exist") else: print("module: invalid subcommand '" + subcommand + "'")
def __module(self, options): if len(options) == 0: print("Incomplete command") print("Valid sub-commands: add, remove, info, list, random, force, test") else: subcommand = options[0] del options[0] if subcommand == "add": if not len(options) == 1: print("module add: No module name") else: module_name = options[0] if module_util.module_exists(module_name): if not module_name in self.__vars['to_run']['value']: self.__vars['to_run']['value'].append(module_name) print("Module added") else: print("Module is already set to be run") else: print("Module '" + module_name + "' does not exist") elif subcommand == "random": rand_list = [] self.__vars['to_run']['value'] = [] while len(rand_list) == 0: mod_list = module_util.get_module_list() set_level = self.__vars['level']['value'] for module in mod_list: # Skip the test module if module == "test_module": continue mod_obj = module_util.import_module(module) if mod_obj: if set_level == "any": if ba_random().will_do(): rand_list.append(module) else: if mod_obj.has_difficulty(set_level) and ba_random().will_do(): rand_list.append(module) else: print("Could not import module "+ module) for module_name in rand_list: self.__vars['to_run']['value'].append(module_name) elif subcommand == "remove": if not len(options) == 1: print("module add: No module set") else: module_name = options[0] if module_util.module_exists(module_name): if module_name in self.__vars['to_run']['value']: self.__vars['to_run']['value'].remove(module_name) print("Module removed") else: print("Module is not set to run") else: print("Module '" + module_name + "' does not exist") elif subcommand == "info": if not len(options) == 1: print("module info: No module name") else: module_name = options[0] if module_util.module_exists(module_name): tmp_module = module_util.import_module(module_name) print(tmp_module.info()) print("Vulnerabilities:") for vuln in tmp_module.full_vulnerability_list(): print(" " + vuln) else: print("Module '" + module_name + "' does not exist") elif subcommand == "list": module_list = module_util.get_module_list() if len(module_list) > 0: for item in module_list: if item == "test_module": continue if item in self.__vars['to_run']['value']: print("\t+ " + item) else: print("\t- " + item) else: print("\nNo modules are set to run!") elif subcommand == "force": if not len(options) == 2: print("Enter a module and vulnerability to force") else: module = options[0] vuln = options[1] if module_util.module_exists(module): if vuln in module_util.import_module(module).full_vulnerability_list(): if not module in self.__vars['force']['value']: self.__vars['force']['value'][module] = [] if not vuln in self.__vars['force']['value'][module]: self.__vars['force']['value'][module].append(vuln) else: print("That vulnerability is already being forced") else: print("Module '" + module + "' does not have the vulnerability '" + vuln + "'") else: print("Module '" + module + "' does not exist") elif subcommand == "test": if self.__debug_mode == False: print("'module test' can only be used in debug mode") elif not len(options) == 2: print("Enter a module and vulnerability to test") else: module = options[0] vuln = options[1] if module_util.module_exists(module): module_obj = module_util.import_module(module) if vuln in module_obj.full_vulnerability_list(): result = module_obj.test(vuln) if result == False: print("Test failed") else: print("Test succeeded") else: print("Module '" + module + "' does not have the vulnerability '" + vuln + "'") else: print("Module '" + module + "' does not exist") else: print("module: invalid subcommand '" + subcommand + "'")