chg: [user session] refactor login + AIL users, use alternative IDs, kill user(s) session

otp
terrtia 2024-05-06 16:21:00 +02:00
parent 31b519cc17
commit 3473273802
No known key found for this signature in database
GPG Key ID: 1E1B1F50D84613D0
26 changed files with 548 additions and 97 deletions

427
bin/lib/ail_users.py Executable file
View File

@ -0,0 +1,427 @@
#!/usr/bin/env python3
# -*-coding:UTF-8 -*
import bcrypt
import os
import pyotp
import re
import secrets
import sys
from flask_login import UserMixin
from uuid import uuid4
sys.path.append(os.environ['AIL_BIN'])
##################################
# Import Project packages
##################################
from lib.ConfigLoader import ConfigLoader
# Config
config_loader = ConfigLoader()
r_serv_db = config_loader.get_db_conn("Kvrocks_DB")
r_cache = config_loader.get_redis_conn("Redis_Cache")
config_loader = None
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,100}$'
regex_password = re.compile(regex_password)
# # TODO: migrate Role_Manager
#### SESSIONS ####
def get_sessions():
r_cache.smembers('ail:sessions')
def exists_session(session):
r_cache.hexists('ail:sessions', session)
def exists_session_user(user_id):
r_cache.hexists('ail:sessions:users', user_id)
def get_session_user(session):
return r_cache.hget('ail:sessions', session)
def get_user_session(user_id):
return r_cache.hget('ail:sessions:users', user_id)
def _generate_session_key(user_id):
return f'{user_id}:{str(uuid4())}'
def _rotate_user_session(user_id):
kill_session_user(user_id)
new_session = _generate_session_key(user_id)
r_cache.hset('ail:sessions', new_session, user_id)
r_cache.hset('ail:sessions:users', user_id, new_session)
return new_session
def kill_session_user(user_id):
session = get_user_session(user_id)
if session:
r_cache.hdel('ail:sessions', session)
r_cache.hdel('ail:sessions:users', user_id)
def kill_sessions():
r_cache.delete('ail:sessions')
r_cache.delete('ail:sessions:users')
#### PASSWORDS ####
def check_password_strength(password):
result = regex_password.match(password)
if result:
return True
else:
return False
def gen_password():
return secrets.token_urlsafe(30)
def hashing_password(password):
password = password.encode()
return bcrypt.hashpw(password, bcrypt.gensalt())
## --PASSWORDS-- ##
#### TOKENS ####
def gen_token():
return secrets.token_urlsafe(41)
def _delete_user_token(user_id):
current_token = get_user_token(user_id)
if current_token:
r_serv_db.hdel('ail:users:tokens', current_token)
def _set_user_token(user_id, token):
r_serv_db.hset('ail:users:tokens', token, user_id)
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'token', token)
def generate_new_token(user_id):
# create user token
_delete_user_token(user_id)
token = gen_token()
_set_user_token(user_id, token)
def get_default_admin_token(): # TODO REMOVE ME ##############################################################################
if r_serv_db.exists('ail:user:metadata:admin@admin.test'):
return r_serv_db.hget('ail:user:metadata:admin@admin.test', 'token')
else:
return ''
## --TOKENS-- ##
#### OTP ####
def _get_totp(secret):
return pyotp.TOTP(secret)
def _verify_totp(totp, code):
return totp.verify(code)
def _get_hotp(secret):
return pyotp.HOTP(secret)
def _verify_hotp(hotp, counter, code):
return hotp.verify(code, counter)
## --OTP-- ##
#### USERS ####
def get_users():
return r_serv_db.hkeys('ail:users:all')
def get_user_role(user_id):
return r_serv_db.hget(f'ail:user:metadata:{user_id}', 'role')
def get_user_passwd_hash(user_id):
return r_serv_db.hget('ail:users:all', user_id)
def get_user_token(user_id):
return r_serv_db.hget(f'ail:user:metadata:{user_id}', 'token')
def get_token_user(token):
return r_serv_db.hget('ail:users:tokens', token)
def exists_token(token):
return r_serv_db.hexists('ail:users:tokens', token)
# def _get_user_otp(user_id):
#
#
# def get_user_hotps(user_id):
#
#
# def _get_user_hotp(user_id):
#
#
# def verify_user_otp(user_id, code):
#
#
# def get_user_hotp_counter(user_id):
# return r_serv_db.hget(f'ail:user:metadata:{user_id}', 'hotp:counter')
#
# def verify_user_hotp(user_id, code):
# counter
########################################################################################################################
########################################################################################################################
# TODO USER LAST LOGIN TIME
# TODO Check if logged
class AILUser(UserMixin):
def __init__(self, user_id):
self.user_id = user_id
session = get_user_session(self.user_id)
if session:
self.id = session
else:
self.id = "__anonymous__"
@classmethod
def get(self_class, id):
return self_class(id)
# @property
# def is_anonymous(self):
# return self.id == "__anonymous__"
# def get_id(self):
# return self.id
def get_user_id(self):
return self.user_id
def exists(self): # TODO CHECK USAGE
return r_serv_db.exists(f'ail:user:metadata:{self.user_id}')
def get_meta(self):
return {'email': self.user_id,}
## SESSION ##
def is_logged(self): #####################################################################################################
pass
def get_session(self):
return self.id
def rotate_session(self):
self.id = _rotate_user_session(self.user_id)
print('rotate session:', self.id)
return self.id
def kill_session(self):
kill_session_user(self.user_id)
self.id = None
## PASSWORD ##
def is_password_change_requested(self):
if r_serv_db.hget(f'ail:user:metadata:{self.user_id}', 'change_passwd') == 1:
return True
else:
return False
def request_password_change(self):
r_serv_db.hset(f'ail:user:metadata:{self.user_id}', 'change_passwd', 1)
def check_password(self, password):
password = password.encode()
hashed_password = r_serv_db.hget('ail:users:all', self.user_id).encode()
if bcrypt.checkpw(password, hashed_password):
return True
else:
return False
def edit_password(self, password_hash, chg_passwd=False): # TODO REPLACE BY PASSWORD
if chg_passwd:
r_serv_db.hset(f'ail:user:metadata:{self.user_id}', 'change_passwd', 1)
else:
r_serv_db.hdel(f'ail:user:metadata:{self.user_id}', 'change_passwd')
# remove default user password file ########################################################################## TODO MOVE ME
if self.user_id == 'admin@admin.test':
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
if os.path.isfile(default_passwd_file):
os.remove(default_passwd_file)
r_serv_db.hset('ail:users:all', self.user_id, password_hash)
# create new token
generate_new_token(self.user_id)
## ROLE ##
def is_in_role(self, role): # TODO Get role via user alternative ID
print('is_in_role')
print(f'ail:users:role:{role}', self.user_id)
if r_serv_db.sismember(f'ail:users:role:{role}', self.user_id):
return True
else:
return False
def get_role(self):
return r_serv_db.hget(f'ail:user:metadata:{self.user_id}', 'role')
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def delete(self): # TODO DESTROY SESSION
kill_session_user(self.user_id)
# def create_user(user_id):
########################################################################################################################
########################################################################################################################
def exists_user(user_id):
return r_serv_db.exists(f'ail:user:metadata:{user_id}')
def get_user_metadata(user_id):
user_metadata = {'email': user_id,
'role': r_serv_db.hget(f'ail:user:metadata:{user_id}', 'role'),
'api_key': r_serv_db.hget(f'ail:user:metadata:{user_id}', 'token')}
return user_metadata
def get_users_metadata(list_users):
users = []
for user in list_users:
users.append(get_user_metadata(user))
return users
def create_user(user_id, password=None, chg_passwd=True, role=None):
# # TODO: check password strength
if password:
new_password = password
else:
new_password = gen_password()
password_hash = hashing_password(new_password)
# EDIT
if exists_user(user_id):
if password or chg_passwd:
edit_user_password(user_id, password_hash, chg_passwd=chg_passwd)
if role:
edit_user_role(user_id, role)
# CREATE USER
else:
# Role
if not role:
role = get_default_role()
if role in get_all_roles():
for role_to_add in get_all_user_role(role):
r_serv_db.sadd(f'ail:users:role:{role_to_add}', user_id)
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'role', role)
r_serv_db.hset('ail:users:all', user_id, password_hash)
if chg_passwd:
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'change_passwd', 'True')
# create user token
generate_new_token(user_id)
def edit_user_password(user_id, password_hash, chg_passwd=False):
if chg_passwd:
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'change_passwd', 'True')
else:
r_serv_db.hdel(f'ail:user:metadata:{user_id}', 'change_passwd')
# remove default user password file
if user_id == 'admin@admin.test':
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
if os.path.isfile(default_passwd_file):
os.remove(default_passwd_file)
r_serv_db.hset('ail:users:all', user_id, password_hash)
# create new token
generate_new_token(user_id)
# # TODO: solve edge_case self delete
def delete_user(user_id):
if exists_user(user_id):
for role_id in get_all_roles():
r_serv_db.srem(f'ail:users:role:{role_id}', user_id)
user_token = get_user_token(user_id)
if user_token:
r_serv_db.hdel('ail:users:tokens', user_token)
r_serv_db.delete(f'ail:user:metadata:{user_id}')
r_serv_db.hdel('ail:users:all', user_id)
# # TODO: raise Exception
else:
print(f'Error: user {user_id} do not exist')
## --USERS-- ##
#### ROLES ####
def get_all_roles():
return r_serv_db.zrange('ail:roles:all', 0, -1)
# create role_list
def _create_roles_list():
if not r_serv_db.exists('ail:roles:all'):
r_serv_db.zadd('ail:roles:all', {'admin': 1})
r_serv_db.zadd('ail:roles:all', {'analyst': 2})
r_serv_db.zadd('ail:roles:all', {'user': 3})
r_serv_db.zadd('ail:roles:all', {'user_no_api': 4})
r_serv_db.zadd('ail:roles:all', {'read_only': 5})
def get_role_level(role):
return int(r_serv_db.zscore('ail:roles:all', role))
def get_user_role_by_range(inf, sup):
return r_serv_db.zrange('ail:roles:all', inf, sup)
def get_all_user_role(user_role):
current_role_val = get_role_level(user_role)
return r_serv_db.zrange('ail:roles:all', current_role_val - 1, -1)
def get_all_user_upper_role(user_role):
current_role_val = get_role_level(user_role)
# remove one rank
if current_role_val > 1:
return r_serv_db.zrange('ail:roles:all', 0, current_role_val -2)
else:
return []
def get_default_role():
return 'read_only'
def is_in_role(user_id, role):
return r_serv_db.sismember(f'ail:users:role:{role}', user_id)
def edit_user_role(user_id, role):
current_role = get_user_role(user_id)
if role != current_role:
request_level = get_role_level(role)
current_role = get_role_level(current_role)
if current_role < request_level:
role_to_remove = get_user_role_by_range(current_role - 1, request_level - 2)
for role_id in role_to_remove:
r_serv_db.srem(f'ail:users:role:{role_id}', user_id)
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'role', role)
else:
role_to_add = get_user_role_by_range(request_level - 1, current_role)
for role_id in role_to_add:
r_serv_db.sadd(f'ail:users:role:{role_id}', user_id)
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'role', role)
def check_user_role_integrity(user_id):
user_role = get_user_role(user_id)
all_user_role = get_all_user_role(user_role)
res = True
for role in all_user_role:
if not r_serv_db.sismember(f'ail:users:role:{role}', user_id):
res = False
upper_role = get_all_user_upper_role(user_role)
for role in upper_role:
if r_serv_db.sismember(f'ail:users:role:{role}', user_id):
res = False
return res
## --ROLES-- ##

View File

@ -78,6 +78,8 @@ phonenumbers>8.12.1
flask>=2.3.3
flask-login
bcrypt>3.1.6
pyotp
segno
# Ail typo squatting
ail_typo_squatting

View File

@ -24,7 +24,7 @@ sys.path.append(os.environ['AIL_BIN'])
# Import Project packages
##################################
from lib.ConfigLoader import ConfigLoader
from lib.Users import User
from lib.ail_users import AILUser, get_session_user
from lib import Tag
from lib import ail_logger
@ -135,8 +135,14 @@ login_manager.init_app(app)
# ========= LOGIN MANAGER ========
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
def load_user(session_id): # TODO USE Alternative ID
print(session)
user_id = get_session_user(session_id)
if user_id:
user = AILUser.get(user_id)
print(user)
return user
return None
# ========= HEADER GENERATION ======== DEPRECATED

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, make_response
from flask_login import login_required, current_user, login_user, logout_user
from flask_login import login_required
sys.path.append('modules')
import Flask_config

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user, login_user, logout_user
from flask_login import login_required
sys.path.append('modules')
import Flask_config

View File

@ -13,7 +13,7 @@ import time
from datetime import datetime
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, send_file, abort
from flask_login import login_required, current_user, login_user, logout_user
from flask_login import login_required, current_user
sys.path.append('modules')
import Flask_config
@ -95,7 +95,7 @@ def crawlers_dashboard_captures_delete():
@login_required
@login_read_only
def manual():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
l_cookiejar = crawlers.api_get_cookiejars_selector(user_id)
crawlers_types = crawlers.get_crawler_all_types()
proxies = [] # TODO HANDLE PROXIES
@ -111,7 +111,7 @@ def manual():
@login_required
@login_analyst
def send_to_spider():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
# POST val
url = request.form.get('url_to_crawl')
@ -645,7 +645,7 @@ def crawler_cookiejar_add():
@login_required
@login_analyst
def crawler_cookiejar_add_post():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
description = request.form.get('description')
level = request.form.get('level')
@ -692,7 +692,7 @@ def crawler_cookiejar_add_post():
@login_required
@login_read_only
def crawler_cookiejar_all():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_cookiejars = crawlers.get_cookiejars_meta_by_iterator(crawlers.get_cookiejars_user(user_id))
global_cookiejars = crawlers.get_cookiejars_meta_by_iterator(crawlers.get_cookiejars_global())
return render_template("all_cookiejar.html", user_cookiejar=user_cookiejars, global_cookiejar=global_cookiejars)
@ -702,7 +702,7 @@ def crawler_cookiejar_all():
@login_required
@login_read_only
def crawler_cookiejar_show():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookiejar_uuid = request.args.get('uuid')
res = crawlers.api_get_cookiejar(cookiejar_uuid, user_id)
@ -718,7 +718,7 @@ def crawler_cookiejar_show():
@login_required
@login_analyst
def crawler_cookiejar_cookie_delete():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookie_uuid = request.args.get('uuid')
res = crawlers.api_delete_cookie(user_id, cookie_uuid)
@ -733,7 +733,7 @@ def crawler_cookiejar_cookie_delete():
@login_required
@login_analyst
def crawler_cookiejar_delete():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookiejar_uuid = request.args.get('uuid')
res = crawlers.api_delete_cookiejar(user_id, cookiejar_uuid)
@ -746,7 +746,7 @@ def crawler_cookiejar_delete():
@login_required
@login_read_only
def crawler_cookiejar_edit():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookiejar_uuid = request.args.get('uuid')
description = request.args.get('description')
@ -758,7 +758,7 @@ def crawler_cookiejar_edit():
@login_required
@login_read_only
def crawler_cookiejar_cookie_edit():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookie_uuid = request.args.get('uuid')
cookie_dict = crawlers.api_get_cookie(user_id, cookie_uuid)
@ -769,7 +769,7 @@ def crawler_cookiejar_cookie_edit():
@login_required
@login_read_only
def crawler_cookiejar_cookie_edit_post():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookie_uuid = request.form.get('cookie_uuid')
name = request.form.get('name')
value = request.form.get('value')
@ -808,7 +808,7 @@ def crawler_cookiejar_cookie_add():
@login_required
@login_read_only
def crawler_cookiejar_cookie_manual_add_post():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookiejar_uuid = request.form.get('cookiejar_uuid')
name = request.form.get('name')
value = request.form.get('value')
@ -838,7 +838,7 @@ def crawler_cookiejar_cookie_manual_add_post():
@login_required
@login_read_only
def crawler_cookiejar_cookie_json_add_post():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
cookiejar_uuid = request.form.get('cookiejar_uuid')
if 'file' in request.files:

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user, login_user, logout_user
from flask_login import login_required, current_user
sys.path.append('modules')
import Flask_config
@ -65,7 +65,7 @@ def get_default_yara_rule_content():
@login_required
@login_read_only
def trackers_dashboard():
user_id = current_user.get_id() # TODO
user_id = current_user.get_user_id()
trackers = Tracker.get_trackers_dashboard()
stats = Tracker.get_trackers_stats(user_id)
return render_template("trackers_dashboard.html", trackers=trackers, stats=stats, bootstrap_label=bootstrap_label)
@ -74,7 +74,7 @@ def trackers_dashboard():
@login_required
@login_read_only
def tracked_menu():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id)
global_trackers = Tracker.get_global_trackers_meta()
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label)
@ -84,7 +84,7 @@ def tracked_menu():
@login_read_only
def tracked_menu_word():
tracker_type = 'word'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type='word')
global_trackers = Tracker.get_global_trackers_meta(tracker_type='word')
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
@ -94,7 +94,7 @@ def tracked_menu_word():
@login_read_only
def tracked_menu_set():
tracker_type = 'set'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
@ -104,7 +104,7 @@ def tracked_menu_set():
@login_read_only
def tracked_menu_regex():
tracker_type = 'regex'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
@ -114,7 +114,7 @@ def tracked_menu_regex():
@login_read_only
def tracked_menu_yara():
tracker_type = 'yara'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
@ -124,7 +124,7 @@ def tracked_menu_yara():
@login_read_only
def tracked_menu_typosquatting():
tracker_type = 'typosquatting'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers,
@ -143,7 +143,7 @@ def tracked_menu_admin():
@login_required
@login_read_only
def show_tracker():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid', None)
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
if res[1] != 200: # invalid access
@ -292,7 +292,7 @@ def parse_add_edit_request(request_form):
def add_tracked_menu():
if request.method == 'POST':
input_dict = parse_add_edit_request(request.form)
user_id = current_user.get_id()
user_id = current_user.get_user_id()
res = Tracker.api_add_tracker(input_dict, user_id)
if res[1] == 200:
return redirect(url_for('hunters.trackers_dashboard'))
@ -310,12 +310,12 @@ def add_tracked_menu():
def tracker_edit():
if request.method == 'POST':
input_dict = parse_add_edit_request(request.form)
user_id = current_user.get_id()
user_id = current_user.get_user_id()
res = Tracker.api_edit_tracker(input_dict, user_id)
if res[1] == 200:
return redirect(url_for('hunters.show_tracker', uuid=res[0].get('uuid')))
else:
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid', None)
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
if res[1] != 200: # invalid access
@ -341,7 +341,7 @@ def tracker_edit():
@login_required
@login_analyst
def tracker_delete():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid')
res = Tracker.api_delete_tracker({'uuid': tracker_uuid}, user_id)
if res[1] != 200:
@ -354,7 +354,7 @@ def tracker_delete():
@login_required
@login_read_only
def get_json_tracker_graph():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid')
res = Tracker.api_check_tracker_acl(tracker_uuid, user_id)
if res:
@ -377,7 +377,7 @@ def get_json_tracker_graph():
@login_required
@login_admin
def tracker_object_add():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid')
object_global_id = request.args.get('gid')
if object_global_id.startswith('messages::'):
@ -398,7 +398,7 @@ def tracker_object_add():
@login_required
@login_analyst
def tracker_object_remove():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid')
object_global_id = request.args.get('gid')
res = Tracker.api_tracker_remove_object({'uuid': tracker_uuid, 'gid': object_global_id}, user_id)
@ -415,7 +415,7 @@ def tracker_object_remove():
@login_required
@login_admin
def tracker_objects():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
tracker_uuid = request.args.get('uuid', None)
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
if res[1] != 200: # invalid access
@ -572,7 +572,7 @@ def retro_hunt_add_task():
rule = yara_default_rule
rule_type='yara_default'
user_id = current_user.get_id()
user_id = current_user.get_user_id()
input_dict = {"name": name, "description": description, "creator": user_id,
"rule": rule, "type": rule_type,

View File

@ -91,7 +91,7 @@ def import_object_file():
@login_required
@login_analyst
def objects_misp_export():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
object_types = ail_core.get_all_objects_with_subtypes_tuple()
to_export = MISPExporter.get_user_misp_objects_to_export(user_id)
return render_template("export_object.html", object_types=object_types, to_export=to_export)
@ -101,7 +101,7 @@ def objects_misp_export():
@login_required
@login_analyst
def objects_misp_export_post():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
# Get new added Object
new_export = []
@ -177,7 +177,7 @@ def objects_misp_export_post():
@login_required
@login_analyst
def add_object_id_to_export():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
obj_type = request.args.get('type')
obj_id = request.args.get('id')
obj_subtype = request.args.get('subtype')
@ -199,7 +199,7 @@ def add_object_id_to_export():
@login_required
@login_analyst
def delete_object_id_to_export():
user_id = current_user.get_id()
user_id = current_user.get_user_id()
obj_type = request.args.get('type')
obj_id = request.args.get('id')
obj_subtype = request.args.get('subtype')

View File

@ -67,10 +67,10 @@ def show_investigation():
@investigations_b.route("/investigation/add", methods=['GET', 'POST'])
@login_required
@login_read_only
@login_analyst
def add_investigation():
if request.method == 'POST':
user_id = current_user.get_id()
user_id = current_user.get_user_id()
name = request.form.get("investigation_name")
date = request.form.get("investigation_date")
threat_level = request.form.get("threat_level")
@ -107,10 +107,10 @@ def add_investigation():
@investigations_b.route("/investigation/edit", methods=['GET', 'POST'])
@login_required
@login_read_only
@login_analyst
def edit_investigation():
if request.method == 'POST':
user_id = current_user.get_id()
user_id = current_user.get_user_id()
investigation_uuid = request.form.get("investigation_uuid")
name = request.form.get("investigation_name")
date = request.form.get("investigation_date")
@ -156,7 +156,7 @@ def edit_investigation():
@investigations_b.route("/investigation/delete", methods=['GET'])
@login_required
@login_read_only
@login_analyst
def delete_investigation():
investigation_uuid = request.args.get('uuid')
input_dict = {"uuid": investigation_uuid}

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file, send_from_directory
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only, no_cache

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file, send_from_directory
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only, no_cache

View File

@ -10,7 +10,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file, send_from_directory
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only, no_cache

View File

@ -12,7 +12,7 @@ import sys
from io import BytesIO
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file, send_from_directory
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only, no_cache

View File

@ -10,7 +10,7 @@ import sys
import json
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -10,7 +10,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response
from flask_login import login_required, current_user
from flask_login import login_required
# Import Role_Manager
from Role_Manager import login_admin, login_analyst, login_read_only

View File

@ -22,7 +22,7 @@ sys.path.append(os.environ['AIL_BIN'])
# Import Project packages
##################################
from lib import Users
from lib.Users import User
from lib.ail_users import AILUser
r_cache = Flask_config.r_cache
@ -39,68 +39,83 @@ root = Blueprint('root', __name__, template_folder='templates')
# ============= ROUTES ==============
@root.route('/login', methods=['POST', 'GET'])
@root.route('/login', methods=['POST', 'GET']) # TODO LOG BRUTEFORCE ATTEMPT
def login():
current_ip = request.remote_addr
login_failed_ip = r_cache.get('failed_login_ip:{}'.format(current_ip))
login_failed_ip = r_cache.get(f'failed_login_ip:{current_ip}')
# brute force by ip
# brute force by IP
if login_failed_ip:
login_failed_ip = int(login_failed_ip)
if login_failed_ip >= 5:
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_ip:{}'.format(current_ip)))
return render_template("login.html", error=error)
wait_time = r_cache.ttl(f'failed_login_ip:{current_ip}')
logging_error = f'Max Connection Attempts reached, Please wait {wait_time}s'
return render_template("login.html", error=logging_error)
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
next_page = request.form.get('next_page')
if password is None:
return render_template("login.html", error='Password is required.')
if username is not None:
user = User.get(username)
login_failed_user_id = r_cache.get('failed_login_user_id:{}'.format(username))
user = AILUser.get(username) # TODO ANONYMOUS USER
print(user.is_anonymous)
# brute force by user_id
login_failed_user_id = r_cache.get(f'failed_login_user_id:{username}')
if login_failed_user_id:
login_failed_user_id = int(login_failed_user_id)
if login_failed_user_id >= 5:
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_user_id:{}'.format(username)))
return render_template("login.html", error=error)
wait_time = r_cache.ttl(f'failed_login_user_id:{username}')
logging_error = f'Max Connection Attempts reached, Please wait {wait_time}s'
return render_template("login.html", error=logging_error)
if user.exists() and user.check_password(password):
if not Users.check_user_role_integrity(user.get_user_id()):
logging_error = 'Incorrect User ACL, Please contact your administrator'
return render_template("login.html", error=logging_error)
# Login User
user.rotate_session()
login_user(user)
if user and user.check_password(password):
if not Users.check_user_role_integrity(user.get_id()):
error = 'Incorrect User ACL, Please contact your administrator'
return render_template("login.html", error=error)
login_user(user) ## TODO: use remember me ?
if user.request_password_change():
return redirect(url_for('root.change_password'))
else:
# update note
# next page
if next_page and next_page!='None' and next_page!='/':
if next_page and next_page != 'None' and next_page != '/':
return redirect(next_page)
# dashboard
else:
return redirect(url_for('dashboard.index'))
# login failed
# LOGIN FAILED
else:
# set brute force protection
# logger.warning("Login failed, ip={}, username={}".format(current_ip, username))
r_cache.incr('failed_login_ip:{}'.format(current_ip))
r_cache.expire('failed_login_ip:{}'.format(current_ip), 300)
r_cache.incr('failed_login_user_id:{}'.format(username))
r_cache.expire('failed_login_user_id:{}'.format(username), 300)
r_cache.incr(f'failed_login_ip:{current_ip}')
r_cache.expire(f'failed_login_ip:{current_ip}', 300)
r_cache.incr(f'failed_login_user_id:{username}')
r_cache.expire(f'failed_login_user_id:{username}', 300)
#
error = 'Password Incorrect'
return render_template("login.html", error=error)
logging_error = 'Login/Password Incorrect'
return render_template("login.html", error=logging_error)
return 'please provide a valid username'
return 'Please provide a valid Username'
else:
next_page = request.args.get('next')
error = request.args.get('error')
return render_template("login.html" , next_page=next_page, error=error)
if current_user.is_authenticated:
return redirect(url_for('dashboard.index'))
else:
print(current_user)
next_page = request.args.get('next')
error = request.args.get('error')
return render_template("login.html", next_page=next_page, error=error)
@root.route('/change_password', methods=['POST', 'GET'])
@login_required
@ -112,11 +127,11 @@ def change_password():
if error:
return render_template("change_password.html", error=error)
if current_user.is_authenticated and password1!=None:
if password1==password2:
if current_user.is_authenticated and password1 != None:
if password1 == password2:
if Users.check_password_strength(password1):
user_id = current_user.get_id()
Users.create_user(user_id , password=password1, chg_passwd=False)
user_id = current_user.get_user_id()
Users.create_user(user_id, password=password1, chg_passwd=False)
# update Note
# dashboard
return redirect(url_for('dashboard.index', update_note=True))
@ -133,6 +148,7 @@ def change_password():
@root.route('/logout')
@login_required
def logout():
current_user.kill_session()
logout_user()
return redirect(url_for('root.login'))

View File

@ -9,7 +9,7 @@ import os
import sys
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, abort
from flask_login import login_required, current_user, login_user, logout_user
from flask_login import login_required
sys.path.append('modules')
import Flask_config

View File

@ -39,7 +39,7 @@ def login_admin(func):
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('admin')):
elif not current_user.is_in_role('admin'):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
@ -49,7 +49,7 @@ def login_analyst(func):
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('analyst')):
elif not current_user.is_in_role('analyst'):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
@ -59,7 +59,7 @@ def login_user(func):
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('user')):
elif not current_user.is_in_role('user'):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
@ -69,7 +69,7 @@ def login_user_no_api(func):
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('user_no_api')):
elif not current_user.is_in_role('user_no_api'):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
@ -79,7 +79,7 @@ def login_read_only(func):
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('read_only')):
elif not current_user.is_in_role('read_only'):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view