def __init__(self, scenario_name): self.file_manager = FileManager() #Variables self.scenario_name = scenario_name self.scenario_id = get_unique_id(length=8) now = datetime.now() self.creation_date = now.strftime("%d/%m/%Y %H:%M:%S") self.last_accessed = self.creation_date[:] self.exploit_info = ExploitInfo("", "", "") self.vulnerability_info = VulnerabilityInfo("", "", "", "") self.machines = dict()
def __init__(self): self.file_manager = FileManager() self.url = ConfigManager().mongoURL() self.db_name = "soft_prac" self.scenarios_col_name = 'scenarios' self.exploits_col_name = 'exploits' self.vulnerabilities_col_name = 'vulnerabilities' self.client = pymongo.MongoClient(self.url) self.db = self.client[self.db_name] self.scenarios_col = self.db[self.scenarios_col_name] self.exploits_col = self.db[self.exploits_col_name] self.vulnerabilities_col = self.db[self.vulnerabilities_col_name] self.addScenariosToDB() self.addExploitsToDB() self.addVulnerabilitiesToDB()
def __init__(self, db_manager=DatabaseManager()): self.file_manager = FileManager() self.db_manager = db_manager self.exploits_dict = self._initializeFromDatabase()
class Scenario(object): def __init__(self, scenario_name): self.file_manager = FileManager() #Variables self.scenario_name = scenario_name self.scenario_id = get_unique_id(length=8) now = datetime.now() self.creation_date = now.strftime("%d/%m/%Y %H:%M:%S") self.last_accessed = self.creation_date[:] self.exploit_info = ExploitInfo("", "", "") self.vulnerability_info = VulnerabilityInfo("", "", "", "") self.machines = dict() def setExploitInfo(self, exploit_info): """ Sets the exploit info for this scenario :param exploit_info: Object which carries the exploit info """ self.exploit_info = exploit_info def setVulnerabilityInfo(self, vulnerability_info): """ Sets the vulnerability info for this scenario :param vulnerability_info: Object which carries the vulnerability info """ self.vulnerability_info = vulnerability_info def addVM(self, vm): """ Adds a new virtual machine to this scenario :param vm: Object which carries the virtual machine data """ self.machines[vm.name] = vm def dictionary(self): """ Generates a dictionary for the Scenario object :return: A dictionary with Scenario data """ scenario_dict = dict() scenario_dict["scenario_name"] = self.scenario_name scenario_dict["scenario_id"] = self.scenario_id scenario_dict["creation_date"] = self.creation_date scenario_dict["last_accessed"] = self.last_accessed scenario_dict["exploit_info"] = self.exploit_info.dictionary( ) if self.exploit_info else dict() scenario_dict[ "vulnerability_info"] = self.vulnerability_info.dictionary( ) if self.vulnerability_info else dict() scenario_dict["machines"] = dict() for name in self.machines: scenario_dict["machines"][name] = self.machines[name].dictionary() return scenario_dict def generateScenario(self, scenario_name): """ Generates a scenario JSON file :param scenario_name: String with the scenario name :return: JSON file containing all the scenario data """ json_dict = self.dictionary() json_name = self.scenario_name + ".json" with open( self.file_manager.getScenariosPath() / scenario_name / "JSON" / json_name, 'w') as outfile: json.dump(json_dict, outfile) json_string = json.dumps(json_dict, indent=2) print(json_string) return json_string
import os import subprocess import re import psutil from CeleryApp import celery from math import ceil from Managers.FileManager import FileManager from Managers.DatabaseManager import DatabaseManager from Managers.SaltManager import SaltManager from Entities.Response import Response from Managers.ConsoleManager import ConsoleManager file_manager = FileManager() db_manager = DatabaseManager() salt_manager = SaltManager() console_manager = ConsoleManager() class VagrantManager(): def getSystemInfo(self): """ Gets the system info. :return: Response object containing request info """ cpu_count_logical = psutil.cpu_count(logical=True) cpu_count = psutil.cpu_count(logical=False) memory = psutil.virtual_memory() mem = getattr(memory, 'total') memory_bytes = int(mem) gigabytes = float(1024**3) total_ram = ceil(memory_bytes / gigabytes)
def __init__(self): self.file_manager = FileManager() self.vagrant_file = VagrantFile() self.scenario_manager = ScenarioManager()
class VagrantManager(object): def __init__(self): self.file_manager = FileManager() self.vagrant_file = VagrantFile() self.scenario_manager = ScenarioManager() def createVagrantFiles(self, scenario_name): """ Creates a vagrant file per machine in a scenario :param scenario_json: String with the scenario name :return: True if vagrant files were successfully created """ self.file_manager.createMachineFolders(scenario_name) scenario_json = self.scenario_manager.getScenario(scenario_name) for machine_name in scenario_json["machines"]: machine = scenario_json["machines"][machine_name] machine_path = self.file_manager.getScenariosPath( ) / scenario_name / "Machines" / machine_name print( self.vagrant_file.vagrantFilePerMachine(machine, machine_path)) result = {"result": True} return result def runVagrantUp(self, scenario_name): """ Executes the vagrant up command for each machine in the scenario :param scenario_name: String with the scenario name :return: True if the vagrant up commands were successfully executed """ self.createVagrantFiles(scenario_name) scenario_json = self.scenario_manager.getScenario(scenario_name) for machine_name in scenario_json["machines"]: machine_path = self.file_manager.getScenariosPath( ) / scenario_name / "Machines" / machine_name if not os.path.exists(machine_path): # Proceed if path exists return os.chdir(machine_path) process = subprocess.Popen(['vagrant', 'up'], stdout=subprocess.PIPE, universal_newlines=True) while True: output = process.stdout.readline() if output == '' and process.poll() is not None: break if output: print(output.strip()) result = {"result": True} return result def sendCommand(self, scenario_name, machine_name, command, default_timeout=5, show_output=True): #First we need to move to the directory of the given machine machine_path = self.file_manager.getScenariosPath( ) / scenario_name / "Machines" / machine_name #using "vagrant ssh -c 'command' <machine>" will only try to execute that command and return, CHANGE THIS connect_command = "vagrant ssh -c '{}' {}".format( command, machine_name) sshProcess = subprocess.Popen(connect_command, cwd=machine_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True, shell=True, bufsize=0) #wait for the execution to finish, process running on different shell sshProcess.wait() sshProcess.stdin.close() return_code = sshProcess.returncode if show_output: for line in sshProcess.stdout: if line == "END\n": break print(line, end="") for line in sshProcess.stdout: if line == "END\n": break print(line, end="") return return_code def restartVM(self, machine_name): pass def haltVM(self, machine_name): pass def testNetworkPing(self, scenario_name, machine_name, destination_machine_name, count=1): if self.scenario_manager.scenarioExists(scenario_name): scenario_data = self.scenario_manager.getScenario(scenario_name) try: machines = scenario_data['machines'] machine_to_ping = machines[destination_machine_name] machine_to_ping_network_settings = machine_to_ping[ 'network_settings'] destination_ip = machine_to_ping_network_settings['ip_address'] ping_command = "ping -c {} {}".format(count, destination_ip) return_code = self.sendCommand(scenario_name, machine_name, ping_command) if return_code == 0: print("Ping Succesful") return True elif return_code == 1: print("No answer from %s" % destination_machine_name) return False else: print("Another error as ocurred") return False except KeyError: print("Machines not defined for this Scenario") return False else: print("Scenario %s not found" % scenario_name) return False def getAvailableBoxes(self): """ Gets the available boxes in the Vagrant context :return: A list of string with the available boxes """ # Variables boxes = {} boxNum = 0 boxlist = subprocess.check_output("vagrant box list", shell=True) boxlist = str(boxlist) boxlist = re.sub(r"(^[b']|'|\s(.*?)\\n)", " ", boxlist) boxlist = boxlist.split(" ") boxlist = filter(None, boxlist) print("Loading available Vanilla VMs") for boxName in boxlist: boxNum = boxNum + 1 boxes[boxNum] = boxName print("[ " + str(boxNum) + " ]" + boxName) return boxes
class ScenarioManager(): def __init__(self, db_manager=DatabaseManager()): self.file_manager = FileManager() self.db_manager = db_manager self.scenarios_dict = self._initializeFromDatabase() def _initializeFromDirectory(self): """ Initializes the scenario's runtime objects using data from the host folders. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = os.listdir(self.file_manager.getScenariosPath()) for scenario_name in scenarios: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) scenarios_dict[scenario_name] = scenario return scenarios_dict def _initializeFromDatabase(self): """ Pre-populates the database with scenarios. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = self.db_manager.getScenarios() for raw_scenario in scenarios: del raw_scenario["_id"] scenario_name = raw_scenario["scenario_name"] scenario = Scenario(scenario_name).objectFromDictionary( raw_scenario) scenarios_dict[scenario_name] = scenario return scenarios_dict def newEmpty(self, scenario_name): """ Creates a new scenario which includes the folders and the scenario JSON file :param scenario_name: String with the scenario name :return: Response object containing the status of the request """ #Folder creation moved to FileManager response = Response() if scenario_name not in self.scenarios_dict: #self.file_manager.createScenarioFolders(scenario_name) scenario = Scenario(scenario_name) self.scenarios_dict[scenario_name] = scenario #self._saveScenarioAsJSON(scenario) self.db_manager.insertScenario(scenario.dictionary().copy()) response.setResponse(True) response.setBody(scenario.dictionary()) else: response.setResponse(False) response.setReason('Scenario already exist') response.setBody(dict()) return response.dictionary() def getAll(self): """ Gets the available scenarios :return: Response object containing the status of the request """ # Variables scenarios_dict = { "scenarios": [ self.scenarios_dict[s].scenario_name for s in self.scenarios_dict ] } response = Response() response.setResponse(True) response.setBody(scenarios_dict) return response.dictionary() def getOne(self, scenario_name): """ Gets the scenario as a JSON file :param scenario_name: String with the scenario name :return: Response object containing the status of the request """ response = Response() if scenario_name in self.scenarios_dict: response.setResponse(True) response.setBody(self.scenarios_dict[scenario_name].dictionary()) else: response.setResponse(False) response.setReason('Scenario doesn\'t exist') response.setBody(dict()) return response.dictionary() def editOne(self, scenario_json): """ Edits a current scenario with a JSON file :param scenario_json: JSON file with the new scenario :return: Response object containing the status of the request """ response = Response() print(scenario_json) scenario_name = scenario_json["scenario_name"] if scenario_name in self.scenarios_dict: if "machines" in scenario_json: for machine in scenario_json["machines"]: if scenario_json["machines"][machine]["uuid"] == "": new_uuid = uuid.uuid4() new_uuid = str(new_uuid).replace('-', '') print("Unique id: ", new_uuid) scenario_json['machines'][machine]['uuid'] = new_uuid scenario_json = Scenario(scenario_name).objectFromDictionary( scenario_json) self.scenarios_dict[scenario_name] = scenario_json #self._saveScenarioAsJSON(new_scenario) self.db_manager.editScenario(scenario_json.dictionary().copy()) response.setResponse(True) response.setBody(self.scenarios_dict[scenario_name].dictionary()) else: response.setReason('Scenario doesn\'t exist') response.setResponse(False) response.setBody(dict()) return response.dictionary() def deleteOne(self, scenario_name): """ Deletes one scenario from the database. :param scenario_name: Scenario's name string :return: Response object containing the status of the request """ response = Response() if scenario_name in self.scenarios_dict: deleted_scenario = self.scenarios_dict.pop(scenario_name) #self.file_manager.deleteScenariosFolder(scenario_name) self.db_manager.deleteScenario(scenario_name) response.setResponse(True) response.setBody(deleted_scenario.dictionary()) else: response.setResponse(False) response.setReason('Scenario doesn\'t exist') response.setBody(dict()) return response.dictionary() def scenarioExists(self, scenario_name): """ Check if a scenario exists. :param scenario_name: String with the scenario name :return: False if the scenario JSON file does not exist and the path to the JSON file if it exist """ scenario_dir_path = self.file_manager.getScenariosPath( ) / scenario_name / "JSON" if not os.path.isdir(scenario_dir_path): print("Scenario %s directory not found" % scenario_name) return False else: scenario_json_path = scenario_dir_path / ''.join( [scenario_name, ".json"]) if not os.path.exists(scenario_json_path): print("Scenario %s json not found" % scenario_name) return None else: return scenario_json_path def _saveScenarioAsJSON(self, scenario): """ Saves a scenario as a JSON file :param scenario: Scenario's name string :return: None """ scenario_json_path = self.file_manager.getScenarioJSONPath( scenario.scenario_name) / ''.join( [scenario.scenario_name, ".json"]) if scenario_json_path: with open(scenario_json_path, 'w+') as outfile: outfile.write(json.dumps(scenario.dictionary(), indent=2)) outfile.close() return
def __init__(self, db_manager=DatabaseManager()): self.file_manager = FileManager() self.db_manager = db_manager self.vulnerabilities_dict = self._initializeFromDatabase()
def __init__(self): self.file_manager = FileManager()
class ScenarioManager(object): def __init__(self): self.file_manager = FileManager() def createScenario(self, scenario_name): """ Creates a new scenario which includes the folders and the scenario JSON file :param scenario_name: String with the scenario name :return: True if the new scenario was successfully created """ #Folder creation moved to FileManager self.file_manager.createScenarioFolders(scenario_name) scenario = Scenario(scenario_name) scenario.generateScenario(scenario_name) result = {"result": True} return result def getScenarios(self): """ Gets the available scenarios :return: A list of strings with the available scenarios """ # Variables scenarios = os.listdir(self.file_manager.getScenariosPath()) scenarios_dict = {"scenarios": scenarios} return scenarios_dict def scenarioExists(self, scenario_name): """ Check if a scenario exists :param scenario_name: String with the scenario name :return: False if the scenario JSON file does not exist and the path to the JSON file if it exist """ scenario_dir_path = self.file_manager.getScenariosPath( ) / scenario_name / "JSON" if not os.path.isdir(scenario_dir_path): print("Scenario %s directory not found" % scenario_name) return False else: scenario_json_path = scenario_dir_path / ''.join( [scenario_name, ".json"]) if not os.path.exists(scenario_json_path): print("Scenario %s json not found" % scenario_name) return None else: return scenario_json_path def getScenario(self, scenario_name): """ Gets the scenario as a JSON file :param scenario_name: String with the scenario name :return: JSON file with the scenario info """ scenario_json_path = self.scenarioExists(scenario_name) if scenario_json_path: try: with open(scenario_json_path) as json_file: scenario_json = json.load(json_file) return scenario_json except: print("Something went wrong while retrieving Scenario JSON") def editScenario(self, scenario_json): """ Edits a current scenario with a JSON file :param scenario_name: String with the scenario name :param scenario_json: JSON file with the new scenario :return: True if the scenario has been successfully edited, otherwise False """ scenario_name = scenario_json["scenario_name"] scenario_json_path = self.scenarioExists(scenario_name) if scenario_json_path: with open(scenario_json_path, 'w+') as outfile: outfile.write(json.dumps(scenario_json, indent=2)) outfile.close() #THIS IS A PLACEHOLDER #It will try to create the folders every time the scenario is edited #new_scenario_dict = json.loads(new_scenario) return True else: return False
class DatabaseManager(): def __init__(self): self.file_manager = FileManager() self.url = ConfigManager().mongoURL() self.db_name = "soft_prac" self.scenarios_col_name = 'scenarios' self.exploits_col_name = 'exploits' self.vulnerabilities_col_name = 'vulnerabilities' self.client = pymongo.MongoClient(self.url) self.db = self.client[self.db_name] self.scenarios_col = self.db[self.scenarios_col_name] self.exploits_col = self.db[self.exploits_col_name] self.vulnerabilities_col = self.db[self.vulnerabilities_col_name] self.addScenariosToDB() self.addExploitsToDB() self.addVulnerabilitiesToDB() def _initializeScenariosFromDirectory(self): """ Initializes the scenario's runtime objects using data from the host folders. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = os.listdir(self.file_manager.getScenariosPath()) for scenario_name in scenarios: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) scenarios_dict[scenario_name] = scenario return scenarios_dict def addScenariosToDB(self): """ Pre-populates the database with scenarios. :return: None """ scenarios_to_add = ['Scenario_1', 'Scenario_3'] currentScenarios = self.getScenarios() scenarios_list = [ scenario['scenario_name'] for scenario in currentScenarios ] scenarios_set = set(scenarios_list) for scenario_name in scenarios_to_add: if scenario_name not in scenarios_set: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) self.insertScenario(scenario.dictionary().copy()) return def addExploitsToDB(self): """ Pre-populates the database with exploits. :return: None """ exploits_to_add = [ 'Django_3_0_Cross-Site_Request_Forgery_Token_Bypass' ] currentExploits = self.getExploits() exploits_list = [exploit['name'] for exploit in currentExploits] exploits_set = set(exploits_list) for exploit_name in exploits_to_add: if exploit_name not in exploits_set: json_name = ''.join([exploit_name, ".json"]) with open( self.file_manager.getExploitJSONPath(exploit_name) / json_name) as outfile: exploit_dict = json.load(outfile) exploit = Exploit().objectFromDictionary(exploit_dict) self.insertExploit(exploit.dictionary().copy()) return def addVulnerabilitiesToDB(self): """ Pre-populates the database with vulnerabilities. :return: None """ vulnerabilities_to_add = ['rConfig_3_9_searchColumn_SQL_Injection'] currentVulnerabilities = self.getVulnerabilities() vulnerabilities_list = [ vulnerability['name'] for vulnerability in currentVulnerabilities ] vulnerabilities_set = set(vulnerabilities_list) for vulnerability_name in vulnerabilities_to_add: if vulnerability_name not in vulnerabilities_set: json_name = ''.join([vulnerability_name, ".json"]) with open( self.file_manager.getVulnerabilityJSONPath( vulnerability_name) / json_name) as outfile: vulnerability_dict = json.load(outfile) vulnerability = Vulnerability().objectFromDictionary( vulnerability_dict) self.insertVulnerability(vulnerability.dictionary().copy()) return #CRUD: CREATE, READ, UPDATE and DELETE #Scenarios def insertScenario(self, scenario_json): """ Inserts a scenario into the database. :param scenario_json: Scenario's JSON file to be inserted :return: Inserted document's id """ doc = self.scenarios_col.insert_one(scenario_json) return doc.inserted_id def getScenarioNames(self): """ Gets the scenario's names. :return: A list containing the scenarios names """ return [doc['scenario_name'] for doc in self.scenarios_col.find()] def getScenarios(self): """ Gets the scenarios from the databases. :return: A list containing scenarios in the database """ return [doc for doc in self.scenarios_col.find()] def getScenario(self, scenario_name): """ Gets a specific scenario from the database. :param scenario_name: Scenario's name string :return: A list containing the scenario retrieved from the database """ query = {'scenario_name': scenario_name} return [doc for doc in self.scenarios_col.find(query)] def editScenario(self, scenario_json): """ Edits a scenario in the database. :param scenario_json: JSON file containing scenario's data :return: Modified document's id """ query = {'scenario_name': scenario_json['scenario_name']} new_doc = {"$set": scenario_json} doc = self.scenarios_col.update_one(query, new_doc) return doc.modified_count def deleteScenario(self, scenario_name): """ Deletes a scenario from the database. :param scenario_name: Scenario's name string :return: Deleted document's id """ query = {'scenario_name': scenario_name} doc = self.scenarios_col.delete_one(query) return doc.deleted_count #Exploits def insertExploit(self, exploit_json): """ Inserts a scenario in the database. :param exploit_json: JSON file containing the exploit's data :return: Inserted document's id """ doc = self.exploits_col.insert_one(exploit_json) return doc.inserted_id def getExploitNames(self): """ Gets the exploits names from the database. :return: A list containing the exploits' names """ return [doc['name'] for doc in self.exploits_col.find()] def getExploits(self): """ Gets the exploits stored in the database. :return: A list containing the stored exploits' data """ return [doc for doc in self.exploits_col.find()] def getExploit(self, exploit_name): """ Gets an exploit from the database. :param exploit_name: Exploit's name string :return: A list containing the exploit data """ query = {'name': exploit_name} return [doc for doc in self.exploits_col.find(query)] def editExploit(self, exploit_json): """ Edits an exploit in the database. :param exploit_json: JSON file containing the exploit's data :return: Modified document's id """ query = {'name': exploit_json['name']} new_doc = {"$set": exploit_json} doc = self.exploits_col.update_one(query, new_doc) return doc.modified_count def deleteExploit(self, exploit_name): """ Deletes a exploit from the database. :param exploit_name: Exploit's name string :return: Deleted document's id """ query = {'name': exploit_name} doc = self.exploits_col.delete_one(query) return doc.deleted_count #Vulnerabilities def insertVulnerability(self, vulnerability_json): """ Inserts a vulnerability in the database. :param vulnerability_json: JSON file containing the vulnerability's data :return: Inserted document's id """ doc = self.vulnerabilities_col.insert_one(vulnerability_json) return doc.inserted_id def getVulnerabilityNames(self): """ Gets the vulnerabilities names from the database. :return: A list containing the vulnerability's names """ return [doc['name'] for doc in self.vulnerabilities_col.find()] def getVulnerabilities(self): """ Gets the vulnerabilities stored in the database. :return: A list containing the stored vulnerabilities' data """ return [doc for doc in self.vulnerabilities_col.find()] def getVulnerability(self, vulnerability_name): """ Gets a vulnerability from the database. :param vulnerability_name: Vulnerability's name string :return: A list containing the vulnerability's data """ query = {'name': vulnerability_name} return [doc for doc in self.vulnerabilities_col.find(query)] def editVulnerability(self, vulnerability_json): """ Edits a vulnerability in the database. :param vulnerability_json: JSON file containing the vulnerability's data :return: Modified document's id """ query = {'name': vulnerability_json['name']} new_doc = {"$set": vulnerability_json} doc = self.vulnerabilities_col.update_one(query, new_doc) return doc.modified_count def deleteVulnerability(self, vulnerability_name): """ Deletes a vulnerability from the database. :param vulnerability_name: Vulnerability's name string :return: Deleted document's id """ query = {'name': vulnerability_name} doc = self.vulnerabilities_col.delete_one(query) return doc.deleted_count