def run_playbook(uplink: UplinkConnection, playbook: str, target: str, args: str): print(f'### Manually executing playbook: {playbook} against {target}') manual_target = { 'target_host': target, 'details': { 'run_method': 'manual' } } for i in range(0, len(args)): manual_target[f'arg{i}'] = args[i] try: playbook_module = importlib.import_module( f'radar.playbooks.{playbook}') results = playbook_module.run(manual_target) print(results) except ModuleNotFoundError as mnfe: print(f'!!! Missing referenced Playbook: {mnfe}') except AttributeError as ae: print(f'!!! Malformed Playbook, missing required attribute: {ae}') except TypeError as te: print( f'!!! Malformed Playbook, the run method must take in the target as a dict: {te}' ) except KeyboardInterrupt: print("!!! Command cancelled by key interrupt") uplink.send_data(const.DEFAULT_TARGET_COLLECTION, manual_target)
def modify_auth(uplink: UplinkConnection, api_key: str, superuser=False, authorizing=True): uplink.change_key_authorization(api_key, superuser=superuser, authorizing=authorizing)
def dispatch(command: str, args=None): uplink_connection = UplinkConnection() if command == 'info': get_info(uplink_connection) elif command == 'distribute': distributed_command = args.command distribute_command(uplink_connection, distributed_command) elif command == 'playbook': run_playbook(uplink_connection, args.playbook, args.target, args.playbook_args) elif command == 'collection-list': list_collections(uplink_connection) elif command == 'database-list': list_database_structure(uplink_connection) elif command == 'get-data': collection = args.collection database = args.database read_database_contents(uplink_connection, collection, database=database) elif command == 'mission-list': list_missions(uplink_connection) elif command == 'mission-join': join_mission(uplink_connection, args.mission) elif command == 'check-auth': check_auth(uplink_connection) elif command == 'grant-auth': modify_auth(uplink_connection, args.api_key, superuser=args.superuser) elif command == 'remove-auth': modify_auth(uplink_connection, args.api_key, authorizing=False) elif command == 'document-commands': output_filename = args.output_filename document_commands(uplink_connection, output_filename)
def main(raw_command: str): print('============ EXECUTING COMMAND ============', file=sys.stderr) system_command = SystemCommand(raw_command) completed = system_command.run() if not completed: print("!!! Command didn't finish executing", file=sys.stderr) exit(1) print(system_command.command_output, end='') print('========== PARSING COMMAND OUTPUT =========', file=sys.stderr) parser_manager = CommandParserManager() command_json = system_command.to_json() metadata, targets = parser_manager.parse( system_command) # Conditionally parse command print('============ RUNNING PLAYBOOKS ============', file=sys.stderr) playbook_manager = PlaybookManager() playbook_manager.automate(targets) # Conditionally run Playbooks print('========= ESTABLISHING RADAR UPLINK =======', file=sys.stderr) uplink = UplinkConnection() print('=============== SYNCING DATA ==============', file=sys.stderr) print("> command data... ", end='', file=sys.stderr) uplink.send_data(const.DEFAULT_COMMAND_COLLECTION, command_json) print("done", file=sys.stderr) print("> metadata... ", end='', file=sys.stderr) uplink.send_data(const.DEFAULT_METADATA_COLLECTION, metadata) print("done", file=sys.stderr) print("> target data... ", end='', file=sys.stderr) if len(targets) != 0: uplink.send_data(const.DEFAULT_TARGET_COLLECTION, targets) print("done", file=sys.stderr) else: print("n/a", file=sys.stderr) print('============<({[ COMPLETED ]})>============', file=sys.stderr)
def document_commands(uplink: UplinkConnection, output_filename: str): out_file = open(output_filename, "w") command_list = uplink.get_data(const.DEFAULT_COMMAND_COLLECTION) for command_data in command_list: start_time_float = command_data.get("execution_time_start") start_time = time.strftime('%Y-%m-%d %H:%M:%S %z', time.localtime(start_time_float)) end_time_float = command_data.get("execution_time_end") end_time = time.strftime('%Y-%m-%d %H:%M:%S %z', time.localtime(end_time_float)) host = command_data.get("executed_on_host") command = command_data.get("command") output = command_data.get("command_output") out_file.write(f"RADAR COMMAND EXECUTION $> {command}\n") out_file.write(f"Executed on Host: {host}\n") out_file.write(f"Command Started at: {start_time}\n") out_file.write(f"Command Finished at: {end_time}\n") out_file.write("OUTPUT:\n") out_file.write("```\n") for line in output.split("\n")[:-1]: out_file.write(f'{line.strip()}\n') out_file.write("```\n") out_file.write("\n\n\n")
def distribute_command(uplink: UplinkConnection, distrib_command: str): syntax_pattern = '^(?P<targets>.+) ([iI][nN][tT][oO]) (?P<command>.*{}.*)$' parsed_command = re.search(syntax_pattern, distrib_command) if not parsed_command.group('targets'): print("!!! Missing targets that go into distributed command") exit(1) if not parsed_command.group('command'): print("!!! Missing distributed command with placeholder") exit(1) unprocessed_target_list = parsed_command.group('targets').split(',') target_list = [] for target in unprocessed_target_list: target = target.strip() if len(target) > 0: target_list.append(target) command = parsed_command.group('command').strip() if len(target_list) == 0 or command == '': print('!!! Either targets or command is missing content and is blank') exit(1) # IP Input patterns ipaddr_rex = '^([0-9]{1,3}\.){3}[0-9]{1,3}$' iprange_rex = '^([0-9]{1,3}\.){3}[0-9]{1,3} *\- *([0-9]{1,3}\.){3}[0-9]{1,3}$' ipcidr_rex = '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$' # tokenize each target in target_list print("### Verifying targets") for target in target_list: if re.match(ipaddr_rex, target): print(f" {target} is an IP address") elif re.match(iprange_rex, target): print(f" {target} is an IP range") elif re.match(ipcidr_rex, target): print(f" {target} is an CIDR network") else: print( f" {target} is a hostname, URL, or other non-IP address target" ) valid = input("Does this look correct? [Y/n]: ").strip().lower() if len(valid) > 0 and valid[0] != 'y': print('!!! You said targets are invalid... stopping now') exit(2) # Generate every single valid target all_targets = [] for target in target_list: try: if re.match(ipaddr_rex, target): host_ip = netaddr.IPAddress(target) all_targets.append(str(host_ip)) elif re.match(iprange_rex, target): range_start_end = [ip.strip() for ip in target.split('-')] iprange = netaddr.IPRange(range_start_end[0], range_start_end[1]) for host_ip in iprange: all_targets.append(str(host_ip)) elif re.match(ipcidr_rex, target): cidr = netaddr.IPNetwork(target) for host_ip in cidr.iter_hosts(): all_targets.append(str(host_ip)) else: all_targets.append(target) except Exception as err: print(f"!!! Invalid target '{target}': {err}") if len(all_targets) == 0: print("!!! No valid targets... aborting") exit(1) print(f"$$$ A total of {len(all_targets)} targets are valid") command_list = [command.replace('{}', target) for target in all_targets] print(f"~~~ Example distirbuted command: '{command_list[0]}'") valid = input("Does this look correct? [Y/n]: ").strip().lower() if len(valid) > 0 and valid[0] != 'y': print('!!! You said the command is wrong... stopping now') exit(2) print(f"$$$ Sending {len(command_list)} commands to be distributed") result = uplink.send_distributed_commands(command_list) if not result: print('!!! Failed to send the commands to the Uplink')
def get_info(uplink: UplinkConnection): info = uplink.get_info() print(info)
def check_auth(uplink: UplinkConnection): uplink.get_key_authorization()
def join_mission(uplink: UplinkConnection, mission: str): uplink.set_mission(mission)
def list_missions(uplink: UplinkConnection): mission_list = uplink.get_mission_list() print("Available Missions w/ data") for mission in mission_list: print(f'> {mission}')
def read_database_contents(uplink: UplinkConnection, collection: str, database=None): contents = uplink.get_data(collection, database=database) print(json.dumps(contents, indent=4, sort_keys=True))
def list_collections(uplink: UplinkConnection): collection_list = uplink.list_collections() for collection in collection_list: print(collection)
def list_database_structure(uplink: UplinkConnection): structure = uplink.get_database_structure() for database_name, collection_list in structure.items(): print(database_name) for collection in collection_list: print(f'> {collection}')