def print_logs(): queue = ScenarioEnvironment().logging_queue logger = _init_logger() while True: try: record = queue.get() if record is None: break logger.handle(record) except: pass
def format_command(command): env = ScenarioEnvironment() replaces = { 'victim': env.victim_hostname, } for k, replace in replaces.items(): command = command.replace("${%s}" % k, replace) return command
def __init__(self): self.storage = { "time": {"exploit": []}, "container": [], } self.name = None self.logger = log.get_logger("collector", ScenarioEnvironment().logging_queue) self.container_ready = None
def _init_logger(): formatter = logging.Formatter( fmt='%(levelname)s - %(container)s - %(message)s') fh = logging.FileHandler( os.path.join(ScenarioEnvironment().out_dir, 'runs.log')) fh.setFormatter(formatter) handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(handler) logger.addHandler(fh) return logger
def optimize_attack_time(image: ChainImage): env = ScenarioEnvironment() logger = log.get_logger("postprocessing", env.logging_queue) scap = os.path.join(env.out_dir, f'{env.recording_name}.scap') pcap = os.path.join(env.out_dir, f'{env.recording_name}.pcap') ip = Collector().attacker_ip logger.info(f"Starting postprocessing for attacker {ip}") matcher = PostprocessingMatcher(pcap, scap, ip) for command in image.commands: optimized_time, source = matcher.get_exact_attack_time( command.after_packet) Collector().set_exploit_time(command.name, optimized_time, source) logger.info(f"Finished postprocessing")
def __init__(self, exploit_time: Union[int, float], warmup_time: Union[int, float], recording_time: Union[int, float]): if not isinstance(warmup_time, (int, float)): raise TypeError("Warmup time needs to be an integer or float") if not isinstance(recording_time, (int, float)): raise TypeError("Recording time needs to be an integer or float") if not isinstance(exploit_time, (int, float)): raise TypeError( "Exploit start time needs to be an integer or float") if exploit_time > recording_time: raise ValueError( "The start time of the exploit must be before the end of the recording!" ) self.name = ScenarioEnvironment().recording_name self.exploit_time = exploit_time self.is_exploit = exploit_time is not 0 self.warmup_time = warmup_time self.recording_time = recording_time
Collector().set_exploit_time(command.name, optimized_time, source) logger.info(f"Finished postprocessing") if __name__ == '__main__': portscan = ExecCommand("sh /app/nmap.sh ${victim}", name="port-scan") bruteforce = ExecCommand("sh /app/hydra.sh ${victim}", name="brute-force", after_packet=TCPPacketPartsMatcher( ["GET /", "User-Agent: curl"], forbidden_parts=["Authorization"])) privilege_escalation = ExecCommand( "python3 /app/attacker.py ${victim}:5984", name="privilege-escalation", after_packet=TCPPacketPartsMatcher( ["GET /_all_dbs", "User-Agent: curl", "Authorization"])) remote_code = ExecCommand("python3 /app/reverse-shell.py ${victim}:5984", name="remote-code", after_packet=TCPPacketPartsMatcher( ["GET /_users/_all_docs", "Authorization"])) exploit_full = ChainImage( "exploit_couchdb", commands=[portscan, bruteforce, privilege_escalation, remote_code]) ScenarioEnvironment().out_dir = "../../couchdb_example/runs" ScenarioEnvironment().recording_name = "young_franklin_9218" Collector().add_container("x", "attacker", "192.168.224.3") optimize_attack_time(exploit_full)
def __init__(self, filename="runs.json"): self.file = open(os.path.join(ScenarioEnvironment().out_dir, filename), "a+")
def stop(): # lock.acquire() queue = ScenarioEnvironment().logging_queue queue.put_nowait(None)
def __init__(self, image: ChainImage): self.queue = ScenarioEnvironment().logging_queue self.network = ScenarioEnvironment().network self.image = image
def get_ip_address(container): container.reload() return container.attrs['NetworkSettings']['Networks'][ ScenarioEnvironment().network.name]['IPAddress']
def _sysdig(self, buffer_size): sysdig_out_path = os.path.join(ScenarioEnvironment().out_dir, f'{self.env.recording_name}.scap') self.logger.info('Saving to Sysdig to {} with buffer size {}'.format(sysdig_out_path, buffer_size)) return pexpect.spawn( 'sysdig -w {} -s {} container.name={} --unbuffered'.format(sysdig_out_path, buffer_size, self.env.victim_hostname))
def __init__(self, image: ChainImage): super().__init__(image) self.port_mapping = "all" self.container = None self.env = ScenarioEnvironment() self.logger = log.get_logger(f"[VICTIM] {self.env.victim_hostname}", self.queue)