async def clear_tasks_for_callback_func(data, cid, user): try: callback = await db_objects.get(Callback, id=cid) operation = await db_objects.get(Operation, id=callback.operation) except Exception as e: print(e) return {'status': 'error', 'error': 'failed to get callback or operation'} tasks_removed = [] if "all" == data['task']: tasks = await db_objects.execute(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp)) elif len(data['task']) > 0: tasks = await db_objects.execute(Task.select().where(Task.id == data['task'])) else: # if you don't actually specify a task, remove the the last task that was entered tasks = await db_objects.execute(Task.select().where( (Task.status == "submitted") & (Task.callback == callback) ).order_by(-Task.timestamp).limit(1)) for t in tasks: if operation.name in user['operations']: try: t_removed = t.to_json() # don't actually delete it, just mark it as completed with a response of "CLEARED TASK" t.status = "processed" await db_objects.update(t) # now create the response so it's easy to track what happened with it response = "CLEARED TASK by " + user['username'] await db_objects.create(Response, task=t, response=response) tasks_removed.append(t_removed) except Exception as e: print(e) return {'status': 'error', 'error': 'failed to delete task: ' + t.command.cmd} return {'status': 'success', 'tasks_removed': tasks_removed}
async def clear_tasks_for_callback_func(data, cid, user): try: callback = await db_objects.get(Callback, id=cid) operation = await db_objects.get(Operation, id=callback.operation) except Exception as e: print(e) return { 'status': 'error', 'error': 'failed to get callback or operation' } if "task" not in data: return {'status': 'error', 'error': 'must specify the task to clear'} tasks_removed = [] if "all" == data['task']: tasks = await db_objects.execute(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp)) else: tasks = await db_objects.execute( Task.select().where(Task.id == data['task'])) for t in tasks: if user['username'] == t.operator.username or user[ 'admin'] or operation.name in user['admin_operations']: try: t_removed = t.to_json() await db_objects.delete(t) tasks_removed.append(t_removed) except Exception as e: print(e) return { 'status': 'error', 'error': 'failed to delete task: ' + t.command.cmd } return {'status': 'success', 'tasks_removed': tasks_removed}
async def clear_tasks_for_callback_func(data, cid, user): try: callback = await db_objects.get(Callback, id=cid) operation = await db_objects.get(Operation, id=callback.operation) except Exception as e: print(e) return { 'status': 'error', 'error': 'failed to get callback or operation' } tasks_removed = [] if "all" == data['task']: tasks = await db_objects.execute(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp)) elif len(data['task']) > 0: # if the user specifies a task, make sure that it's not being processed tasks = await db_objects.execute( Task.select().where((Task.id == data['task']) & (Task.status == "submitted"))) else: # if you don't actually specify a task, remove the the last task that was entered tasks = await db_objects.execute(Task.select().where( (Task.status == "submitted") & (Task.callback == callback)).order_by(-Task.timestamp).limit(1)) for t in tasks: if operation.name in user['operations']: try: t_removed = t.to_json() # don't actually delete it, just mark it as completed with a response of "CLEARED TASK" t.status = "processed" await db_objects.update(t) # we need to adjust all of the things associated with this task now since it didn't actually happen # find/remove ATTACKTask, TaskArtifact, FileMeta attack_tasks = await db_objects.execute( ATTACKTask.select().where(ATTACKTask.task == t)) for at in attack_tasks: await db_objects.delete(at, recursive=True) task_artifacts = await db_objects.execute( TaskArtifact.select().where(TaskArtifact.task == t)) for ta in task_artifacts: await db_objects.delete(ta, recursive=True) file_metas = await db_objects.execute( FileMeta.select().where(FileMeta.task == t)) for fm in file_metas: os.remove(fm.path) await db_objects.delete(fm, recursive=True) # now create the response so it's easy to track what happened with it response = "CLEARED TASK by " + user['username'] await db_objects.create(Response, task=t, response=response) tasks_removed.append(t_removed) except Exception as e: print(e) return { 'status': 'error', 'error': 'failed to delete task: ' + t.command.cmd } return {'status': 'success', 'tasks_removed': tasks_removed}
async def get_all_tasks_for_callback(request, cid): try: callback = await db_objects.get(Callback, id=cid) except Exception as e: return json({'status': 'error', 'error': 'Callback does not exist'}) try: tasks = Task.select() cb_task_data = await db_objects.execute( Task.select().where(Task.callback == callback)) return json([c.to_json() for c in cb_task_data]) except Exception as e: return json({'status': 'error', 'error': 'No Tasks', 'msg': str(e)})
async def list_all_screencaptures_per_operation(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") if user['current_operation'] != "": query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() screencaptures = await db_objects.prefetch( query.where( FileMeta.path.regexp(".*{}/downloads/.*/screenshots/".format( operation.name))), Task.select(), Command.select(), Callback.select()) screencapture_paths = [] for s in screencaptures: screencapture_paths.append(s.to_json()) return json({'status': 'success', 'files': screencapture_paths}) else: return json({ "status": 'error', 'error': 'must be part of a current operation to see an operation\'s screencaptures' })
async def ws_responses(request, ws): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newresponse";') responses = Response.select() tasks = Task.select() responses_with_tasks = await db_objects.prefetch(responses, tasks) for resp in responses_with_tasks: await ws.send(js.dumps(resp.to_json())) await ws.send("") # now pull off any new responses we got queued up while processing old responses while True: try: msg = conn.notifies.get_nowait() id = (msg.payload) rsp = await db_objects.get(Response, id=id) await ws.send(js.dumps(rsp.to_json())) # print(msg.payload) except asyncio.QueueEmpty as e: await asyncio.sleep(2) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: # print("closed /ws/task_updates") pool.close()
async def get_all_tasks(request): callbacks = Callback.select() operators = Operator.select() tasks = Task.select() # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) full_task_data = await db_objects.prefetch(tasks, callbacks, operators) return json([c.to_json() for c in full_task_data])
async def get_all_tasks_by_callback_in_current_operation(request, user): try: operation = await db_objects.get(Operation, name=user['current_operation']) except Exception as e: return json({'status': 'error', 'error': 'Not part of an operation'}) output = [] callbacks = await db_objects.execute(Callback.select().where( Callback.operation == operation).order_by(Callback.id)) for callback in callbacks: c = callback.to_json( ) # hold this callback, task, and response info to push to our output stack c['tasks'] = [] tasks = await db_objects.execute( Task.select().where(Task.callback == callback).order_by(Task.id)) for t in tasks: t_data = t.to_json() t_data['responses'] = [] responses = await db_objects.execute(Response.select().where( Response.task == t).order_by(Response.id)) for r in responses: t_data['responses'].append(r.to_json()) c['tasks'].append(t_data) output.append(c) return json({'status': 'success', 'output': output})
async def search_tasks(request, user): try: data = request.json if 'search' not in data: return json({ 'status': 'error', 'error': 'failed to find search term in request' }) operation = await db_objects.get(Operation, name=user['current_operation']) except Exception as e: return json({'status': 'error', 'error': 'Cannot get that response'}) tasks = await db_objects.execute( Task.select().where((Task.params.contains(data['search'])) | (Task.original_params.contains(data['search']))). join(Callback).where(Callback.operation == operation).order_by(Task.id) ) output = [] for t in tasks: responses = await db_objects.execute( Response.select().where(Response.task == t)) output.append({ **t.to_json(), "responses": [r.to_json() for r in responses] }) return json({'status': 'success', 'output': output})
async def list_all_screencaptures_per_callback(request, user, id): try: query = await db_model.callback_query() callback = await db_objects.get(query, id=id) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to find callback'}) screencapture_paths = [] if callback.operation.name in user['operations']: query = await db_model.filemeta_query() screencaptures = await db_objects.prefetch( query.where( FileMeta.path.regexp(".*{}/downloads/.*/screenshots/".format( callback.operation.name))), Task.select(), Command.select(), Callback.select()) for s in screencaptures: if s.task.callback == callback: screencapture_paths.append(s.to_json()) return json({ 'status': 'success', 'callback': callback.id, 'files': screencapture_paths }) else: return json({ 'status': 'error', 'error': 'must be part of that callback\'s operation to see its screenshots' })
async def get_next_task(request, cid): # gets the next task by time for the callback to do try: callback = await db_objects.get(Callback, id=cid) except Exception as e: return json({'status': 'error', 'error': 'callback does not exist'}) try: callback.last_checkin = datetime.datetime.now() callback.active = True # always set this to true regardless of what it was before because it's clearly active await db_objects.update(callback) # update the last checkin time tasks = await db_objects.get(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp)) except Exception as e: print(e) return json({ 'command': 'none' }) # return empty if there are no tasks that meet the criteria tasks.status = "processing" await db_objects.update(tasks) return json({ "command": tasks.command, "params": tasks.params, "id": tasks.id })
async def ws_tasks(request, ws): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newtask";') # before we start getting new things, update with all of the old data callbacks = Callback.select() operators = Operator.select() tasks = Task.select() tasks_with_all_info = await db_objects.prefetch(tasks, callbacks, operators) # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) for task in tasks_with_all_info: await ws.send(js.dumps(task.to_json())) await ws.send("") # now pull off any new tasks we got queued up while processing the old data while True: try: msg = conn.notifies.get_nowait() id = (msg.payload) tsk = await db_objects.get(Task, id=id) await ws.send(js.dumps(tsk.to_json())) except asyncio.QueueEmpty as e: await asyncio.sleep(2) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: # print("closed /ws/tasks") pool.close()
async def search_comments_by_callback_in_current_operation(request, user): try: operator = await db_objects.get(Operator, username=user['username']) operation = await db_objects.get(Operation, name=user['current_operation']) data = request.json if 'search' not in data: return json({'status': 'error', 'error': 'search is required'}) except Exception as e: return json({ 'status': 'error', 'error': 'failed to find operator or operation: ' + str(e) }) tasks = await db_objects.execute(Task.select().where( Task.comment.contains(data['search'])).join(Callback).where( Callback.operation == operation).order_by(Task.id)) callbacks = {} for t in tasks: responses = await db_objects.execute( Response.select().where(Response.task == t)) if t.callback.id not in callbacks: callbacks[t.callback.id] = t.callback.to_json() callbacks[t.callback.id]['tasks'] = [] callbacks[t.callback.id]['tasks'].append({ **t.to_json(), "responses": [r.to_json() for r in responses] }) return json({'status': 'success', 'callbacks': list(callbacks.values())})
async def get_next_task(request, cid): # gets the next task by time for the callback to do try: callback = await db_objects.get(Callback, id=cid) except Exception as e: print("Callback did not exist, tasking to exit") return json({ 'command': "exit", "params": "" }) # if the callback doesn't exist for some reason, task it to exit try: callback.last_checkin = datetime.datetime.utcnow() callback.active = True # always set this to true regardless of what it was before because it's clearly active await db_objects.update(callback) # update the last checkin time operation = await db_objects.get(Operation, name=callback.operation.name) if not operation.complete: tasks = await db_objects.get(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status == "submitted")).order_by(Task.timestamp)) else: # if the operation is done, kill anything that still tries to get tasking return json({"command": "exit", "params": ""}) except Exception as e: print(e) return json({ 'command': 'none' }) # return empty if there are no tasks that meet the criteria tasks.status = "processing" await db_objects.update(tasks) return json({ "command": tasks.command.cmd, "params": tasks.params, "id": tasks.id })
async def get_all_tasks_by_callback_in_current_operation(request, user): try: operation = await db_objects.get(Operation, name=user['current_operation']) except Exception as e: return json({'status': 'error', 'error': 'Not part of an operation'}) output = [] callbacks = await db_objects.execute(Callback.select().where( Callback.operation == operation).order_by(Callback.id)) for callback in callbacks: c = callback.to_json( ) # hold this callback, task, and response info to push to our output stack c['tasks'] = [] tasks = await db_objects.execute( Task.select().where(Task.callback == callback).order_by(Task.id)) for t in tasks: t_data = t.to_json() t_data['responses'] = [] t_data['attackids'] = [ ] # display the att&ck id numbers associated with this task if there are any responses = await db_objects.execute(Response.select().where( Response.task == t).order_by(Response.id)) for r in responses: t_data['responses'].append(r.to_json()) attackids = await db_objects.execute(ATTACKId.select().where(( ATTACKId.task == t) | (ATTACKId.cmd == t.command)).order_by( ATTACKId.id)) for a in attackids: t_data['attackids'].append() # make it a set so we don't have duplicates from the command and some other method t_data['attackids'] = set(t_data['attackids']) c['tasks'].append(t_data) output.append(c) return json({'status': 'success', 'output': output})
async def get_all_files_meta(request, user): try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if f.operation.name in user['operations']])
async def get_all_files_meta(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message="Cannot access via Cookies. Use CLI or access via JS in browser") try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json([f.to_json() for f in files if f.operation.name in user['operations']])
async def regex_against_tasks(request, user): data = request.json try: operation = await db_objects.get(Operation, name=user['current_operation']) except Exception as e: return json({ 'status': 'error', 'error': "Failed to find current operation" }) if 'regex' not in data: return json({'status': 'error', 'error': 'regex is a required field'}) if 'apply' not in data: return json({'status': 'error', 'error': 'apply is a required field'}) if 'attack' not in data: return json({'status': 'error', 'error': 'an attack T# is required'}) try: attack = await db_objects.get(ATTACK, t_num=data['attack']) except Exception as e: return json({ 'status': 'error', 'error': 'Failed to find that T#. Make sure you specify "attack": "T1124" for example' }) matching_tasks = await db_objects.execute( Task.select().join(Callback).where( Callback.operation == operation).switch().where( (Task.params.regexp(data['regex'])) | (Task.original_params.regexp(data['regex']))).order_by( Task.id)) if data['apply']: # actually apply the specified att&ck id to the matched tasks for t in matching_tasks: # don't create duplicates attacktask, create = await db_objects.get_or_create(ATTACKTask, attack=attack, task=t) return json({'status': 'success'}) else: # simply return which tasks would have matched # for each matching task, also return which other ATT&CK IDs are associated tasks = [] for t in matching_tasks: sub_attacks = [] matching_attacks = await db_objects.execute( ATTACKTask.select().where(ATTACKTask.task == t)) for ma in matching_attacks: sub_attacks.append({ 't_num': ma.attack.t_num, 'name': ma.attack.name }) tasks.append({**t.to_json(), "attack": sub_attacks}) return json({'status': 'success', 'matches': tasks})
async def get_all_tasks(request, user): if user['admin']: callbacks = Callback.select() operators = Operator.select() tasks = Task.select() # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) full_task_data = await db_objects.prefetch(tasks, callbacks, operators) return json([c.to_json() for c in full_task_data]) else: return json({ 'status': 'error', 'error': 'must be admin to see all tasks' })
async def get_all_tasks(request, user): callbacks = Callback.select() operators = Operator.select() tasks = Task.select() full_task_data = await db_objects.prefetch(tasks, callbacks, operators) if user['admin']: # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) return json([c.to_json() for c in full_task_data]) elif user['current_operation'] != "": operation = await db_objects.get(Operation, name=user['current_operation']) return json([c.to_json() for c in full_task_data if c.callback.operation == operation]) else: return json({'status': 'error', 'error': 'must be admin to see all tasks or part of a current operation'})
async def get_all_not_completed_tasks_for_callback_func(cid, user): try: callback = await db_objects.get(Callback, id=cid) operation = await db_objects.get(Operation, id=callback.operation) except Exception as e: print(e) return {'status': 'error', 'error': 'failed to get callback or operation'} if operation.name in user['operations']: # Get all tasks that have a status of submitted or processing tasks = await db_objects.execute(Task.select().join(Callback).where( (Task.callback == callback) & (Task.status != "processed")).order_by(Task.timestamp)) return {'status': 'success', 'tasks': [x.to_json() for x in tasks]} else: return {'status': 'error', 'error': 'You must be part of the operation to view this information'}
async def get_all_responses(request, user): try: responses = [] operation = await db_objects.get(Operation, name=user['current_operation']) callbacks = await db_objects.execute(Callback.select().where(Callback.operation == operation)) for c in callbacks: tasks = await db_objects.execute(Task.select().where(Task.callback == c)) for t in tasks: task_responses = await db_objects.execute(Response.select().where(Response.task == t)) responses += [r.to_json() for r in task_responses] except Exception as e: return json({'status': 'error', 'error': 'Cannot get responses'}) return json(responses)
async def get_all_files_meta(request, user): if user["auth"] not in ["access_token", "apitoken"]: abort( status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser", ) try: query = await db_model.filemeta_query() files = await db_objects.prefetch(query, Task.select(), Command.select(), Callback.select()) except Exception as e: return json({"status": "error", "error": "failed to get files"}) return json( [f.to_json() for f in files if f.operation.name in user["operations"]])
async def get_next_task(request, cid): # gets the next task by time for the callback to do try: callback = await db_objects.get(Callback, id=cid) except Exception as e: print("Callback did not exist, returning blank message") return json({}, status=404) try: callback.last_checkin = datetime.datetime.utcnow() callback.active = True # always set this to true regardless of what it was before because it's clearly active await db_objects.update(callback) # update the last checkin time operation = await db_objects.get(Operation, name=callback.operation.name) if not operation.complete: tasks = await db_objects.get(Task.select().join( Callback).where((Task.callback == callback) & (Task.status == "submitted")).order_by( Task.timestamp).limit(1)) else: # operation is complete, just return blank return json({}, status=404) except Exception as e: print(e) return json({ 'command': 'none' }) # return empty if there are no tasks that meet the criteria tasks.status = "processing" await db_objects.update(tasks) if callback.encryption_type != "" and callback.encryption_type is not None: # encrypt the message before returning it string_message = js.dumps({ "command": tasks.command.cmd, "params": tasks.params, "id": tasks.id }) if callback.encryption_type == "AES256": raw_encrypted = await crypt.encrypt_AES256( data=string_message.encode(), key=base64.b64decode(callback.encryption_key)) return raw(base64.b64encode(raw_encrypted), status=200) else: return json({ "command": tasks.command.cmd, "params": tasks.params, "id": tasks.id })
async def get_all_tasks_for_callback(request, cid, user): try: callback = await db_objects.get(Callback, id=cid) operation = await db_objects.get(Operation, id=callback.operation) except Exception as e: return json({'status': 'error', 'error': 'Callback does not exist'}) if operation.name in user['operations']: try: cb_task_data = await db_objects.execute(Task.select().where(Task.callback == callback).order_by(Task.id)) return json([c.to_json() for c in cb_task_data]) except Exception as e: return json({'status': 'error', 'error': 'No Tasks', 'msg': str(e)}) else: return json({'status': 'error', 'error': 'You must be part of the right operation to see this information'})
async def callbacks_get_all_tasking(request, user, id): # Get all of the tasks and responses so far for the specified agent try: operation = await db_objects.get(Operation, name=user['current_operation']) callback = await db_objects.get(Callback, id=id, operation=operation) cb_json = callback.to_json() cb_json['tasks'] = [] tasks = await db_objects.execute(Task.select().where(Task.callback == callback).order_by(Task.id)) for t in tasks: responses = await db_objects.execute(Response.select().where(Response.task == t).order_by(Response.id)) rs = [] for r in responses: rs.append(r.to_json()) cb_json['tasks'].append({**t.to_json(), "responses": rs}) return json({'status': 'success', **cb_json}) except Exception as e: print(e) return json({'status': 'error', 'error': str(e)})
async def get_current_operations_files_meta(request, user): if user['current_operation'] != "": try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() files = await db_objects.prefetch( query.where(FileMeta.operation == operation), Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if not "screenshots" in f.path]) else: return json({ "status": 'error', 'error': 'must be part of an active operation' })
async def get_comments_by_operator_in_current_operation(request, user): try: operation = await db_objects.get(Operation, name=user['current_operation']) operator_operation = await db_objects.execute(OperatorOperation.select().where(OperatorOperation.operation == operation)) except Exception as e: return json({'status': 'error', 'error': 'failed to find operator or operation: ' + str(e)}) operators_list = [] for mapping in operator_operation: operator = mapping.operator tasks = await db_objects.execute(Task.select().where( (Task.comment_operator == operator) & (Task.comment != "")).join(Callback).where(Callback.operation == operation).order_by(Task.id)) callbacks = {} for t in tasks: responses = await db_objects.execute(Response.select().where(Response.task == t)) if t.callback.id not in callbacks: callbacks[t.callback.id] = t.callback.to_json() callbacks[t.callback.id]['tasks'] = [] callbacks[t.callback.id]['tasks'].append({**t.to_json(), "responses": [r.to_json() for r in responses]}) if len(callbacks.keys()) > 0: operators_list.append({**operator.to_json(), 'callbacks': list(callbacks.values())}) return json({'status': 'success', 'operators': operators_list})
async def get_current_operations_files_meta(request, user): if user['auth'] not in ['access_token', 'apitoken']: abort(status_code=403, message= "Cannot access via Cookies. Use CLI or access via JS in browser") if user['current_operation'] != "": try: query = await db_model.operation_query() operation = await db_objects.get(query, name=user['current_operation']) query = await db_model.filemeta_query() files = await db_objects.prefetch( query.where(FileMeta.operation == operation), Task.select(), Command.select(), Callback.select()) except Exception as e: return json({'status': 'error', 'error': 'failed to get files'}) return json( [f.to_json() for f in files if not "screenshots" in f.path]) else: return json({ "status": 'error', 'error': 'must be part of an active operation' })
async def database_clears(request, user): try: operator = await db_objects.get(Operator, username=user['username']) operation = await db_objects.get(Operation, name=user['current_operation']) if operation.name not in user['admin_operations']: return json({'status': 'error', 'error': "you must be the admin of the operation to clear the database"}) except Exception as e: return json({'status': 'error', 'error': "failed to get the operation and operation: " + str(e)}) data = request.json if 'object' not in data: return json({'status': 'error', 'error': '"object" is a required parameter'}) deleted_obj_info = {'dbnumber': 0} if data['object'] == "payloads": payloads = await db_objects.execute(Payload.select().where(Payload.operation == operation)) for p in payloads: try: os.remove(p.location) # delete it from disk first except Exception as e: print(e) await db_objects.delete(p, recursive=True) # then delete it and everything it relies on from the db deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "callbacks": callbacks = await db_objects.execute(Callback.select().where(Callback.operation == operation)) for c in callbacks: await db_objects.delete(c, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "screencaptures": screencaptures = await db_objects.execute(FileMeta.select().where( (FileMeta.operation == operation) & (FileMeta.path.contains("/screenshots/")) )) for s in screencaptures: try: os.remove(s.path) except Exception as e: print(e) await db_objects.delete(s, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "downloads": downloads = await db_objects.execute(FileMeta.select().where( (FileMeta.operation == operation) & (FileMeta.path.contains("/downloads/")) )) for d in downloads: try: os.remove(d.path) except Exception as e: print(e) await db_objects.delete(d, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 shutil.rmtree("./app/files/{}/downloads".format(operation.name)) # remove the downloads folder from disk elif data['object'] == "uploads": uploads = await db_objects.execute(FileMeta.select().where( (FileMeta.operation == operation) & (FileMeta.path.contains("/{}/".format(operation.name))) & ~(FileMeta.path.contains("/downloads")) )) for u in uploads: try: os.remove(u.path) except Exception as e: print(e) await db_objects.delete(u, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "keylogs": keylogs = await db_objects.execute(Keylog.select().where(Keylog.operation == operation)) for k in keylogs: await db_objects.delete(k, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "credentials": credentials = await db_objects.execute(Credential.select().where(Credential.operation == operation)) for c in credentials: await db_objects.delete(c, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "tasks": callbacks = Callback.select().where(Callback.operation == operation) tasks = await db_objects.prefetch(Task.select(), callbacks) for t in tasks: await db_objects.delete(t, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 elif data['object'] == "responses": callbacks = Callback.select().where(Callback.operation == operation) tasks = Task.select() responses = await db_objects.prefetch(Response.select(), tasks, callbacks) for r in responses: await db_objects.delete(r, recursive=True) deleted_obj_info['dbnumber'] = deleted_obj_info['dbnumber'] + 1 return json({"status": "success", 'stats': deleted_obj_info})