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_all_responses(request, user): try: all_responses = await db_objects.execute(Response.select()) except Exception as e: return json({'status': 'error', 'error': 'Cannot get responses'}) return json([c.to_json() for c in all_responses])
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 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 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_responses_for_task(request, user, id): try: operation = await db_objects.get(Operation, name=user['current_operation']) task = await db_objects.get(Task, id=id) except Exception as e: return json({'status': 'error', 'error': 'failed to get operation or task'}) responses = await db_objects.execute(Response.select().where(Response.task == task).order_by(Response.id)) return json([r.to_json() for r in responses])
async def search_responses(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'}) responses = await db_objects.execute(Response.select().where(Response.response.contains(data['search'])).join(Task).join(Callback).where(Callback.operation == operation).order_by(Response.id)) return json({'status': 'success', 'output': [r.to_json() for r in responses]})
async def get_one_task_and_responses(request, tid, user): try: task = await db_objects.get(Task, id=tid) if task.callback.operation.name in user['operations']: responses = await db_objects.execute(Response.select().where(Response.task == task)) return json({'status': "success", "callback": task.callback.to_json(), "task": task.to_json(), "responses": [r.to_json() for r in responses]}) else: return json({'status': 'error', 'error': 'you don\'t have access to that task'}) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to find that task'})
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 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_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 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})