chg: [Tracker] edit tracker

pull/534/head
Terrtia 2020-12-08 16:47:55 +01:00
parent e5ef95030c
commit 4fa320741c
No known key found for this signature in database
GPG Key ID: 1E1B1F50D84613D0
5 changed files with 471 additions and 47 deletions

View File

@ -2,19 +2,78 @@
# -*-coding:UTF-8 -*
import os
import re
import sys
import time
import redis
import uuid
import yara
import datetime
from flask import escape
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib/'))
import ConfigLoader
#import item_basic
config_loader = ConfigLoader.ConfigLoader()
r_serv_db = config_loader.get_redis_conn("ARDB_DB")
r_serv_tracker = config_loader.get_redis_conn("ARDB_Tracker")
config_loader = None
email_regex = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}'
email_regex = re.compile(email_regex)
special_characters = set('[<>~!?@#$%^&*|()_-+={}":;,.\'\n\r\t]/\\')
special_characters.add('\\s')
###############
#### UTILS ####
def is_valid_uuid_v4(UUID):
if not UUID:
return False
UUID = UUID.replace('-', '')
try:
uuid_test = uuid.UUID(hex=UUID, version=4)
return uuid_test.hex == UUID
except:
return False
def is_valid_regex(tracker_regex):
try:
re.compile(tracker_regex)
return True
except:
return False
def is_valid_mail(email):
result = email_regex.match(email)
if result:
return True
else:
return False
def verify_mail_list(mail_list):
for mail in mail_list:
if not is_valid_mail(mail):
return ({'status': 'error', 'reason': 'Invalid email', 'value': mail}, 400)
return None
##-- UTILS --##
###############
def get_tracker_by_uuid(tracker_uuid):
return r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'tracked')
def get_tracker_type(tracker_uuid):
return r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'type')
def get_tracker_level(tracker_uuid):
return int(r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'level'))
def get_tracker_user_id(tracker_uuid):
return r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'user_id')
def get_tracker_uuid_list(tracker, tracker_type):
return list(r_serv_tracker.smembers('all:tracker_uuid:{}:{}'.format(tracker_type, tracker)))
@ -27,6 +86,51 @@ def get_tracker_mails(tracker_uuid):
def get_tracker_description(tracker_uuid):
return r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'description')
def get_tracker_first_seen(tracker_uuid):
res = r_serv_tracker.zrange('tracker:stat:{}'.format(tracker_uuid), 0, 0)
if res:
return res[0]
else:
return None
def get_tracker_last_seen(tracker_uuid):
res = r_serv_tracker.zrevrange('tracker:stat:{}'.format(tracker_uuid), 0, 0)
if res:
return res[0]
else:
return None
def get_tracker_metedata(tracker_uuid, user_id=False, description=False, level=False, tags=False, mails=False, sparkline=False):
dict_uuid = {}
dict_uuid['tracker'] = get_tracker_by_uuid(tracker_uuid)
dict_uuid['type'] = get_tracker_type(tracker_uuid)
dict_uuid['date'] = r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'date')
dict_uuid['description'] = get_tracker_description(tracker_uuid)
dict_uuid['first_seen'] = get_tracker_first_seen(tracker_uuid)
dict_uuid['last_seen'] = get_tracker_last_seen(tracker_uuid)
if user_id:
dict_uuid['user_id'] = get_tracker_user_id(tracker_uuid)
if level:
dict_uuid['level'] = get_tracker_level(tracker_uuid)
if mails:
dict_uuid['mails'] = get_tracker_mails(tracker_uuid)
if tags:
dict_uuid['tags'] = get_tracker_tags(tracker_uuid)
if sparkline:
dict_uuid['sparkline'] = get_tracker_sparkline(tracker_uuid)
dict_uuid['uuid'] = tracker_uuid
return dict_uuid
def get_tracker_sparkline(tracker_uuid, num_day=6):
date_range_sparkline = Date.get_date_range(num_day)
sparklines_value = []
for date_day in date_range_sparkline:
nb_seen_this_day = r_serv_tracker.scard('tracker:item:{}:{}'.format(tracker_uuid, date_day))
if nb_seen_this_day is None:
nb_seen_this_day = 0
sparklines_value.append(int(nb_seen_this_day))
return sparklines_value
def add_tracked_item(tracker_uuid, item_id, item_date):
# track item
r_serv_tracker.sadd('tracker:item:{}:{}'.format(tracker_uuid, item_date), item_id)
@ -46,6 +150,234 @@ def get_tracker_last_updated_by_type(tracker_type):
epoch_update = 0
return float(epoch_update)
######################
#### TRACKERS ACL ####
# # TODO: use new package => duplicate fct
def is_in_role(user_id, role):
if r_serv_db.sismember('user_role:{}'.format(role), user_id):
return True
else:
return False
def is_tracker_in_global_level(tracker, tracker_type):
res = r_serv_tracker.smembers('all:tracker_uuid:{}:{}'.format(tracker_type, tracker))
if res:
for elem_uuid in res:
if r_serv_tracker.hget('tracker:{}'.format(elem_uuid), 'level')=='1':
return True
return False
def is_tracker_in_user_level(tracker, tracker_type, user_id):
res = r_serv_tracker.smembers('user:tracker:{}'.format(user_id))
if res:
for elem_uuid in res:
if r_serv_tracker.hget('tracker:{}'.format(elem_uuid), 'tracked')== tracker:
if r_serv_tracker.hget('tracker:{}'.format(elem_uuid), 'type')== tracker_type:
return True
return False
def api_is_allowed_to_edit_tracker(tracker_uuid, user_id):
if not is_valid_uuid_v4(tracker_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
tracker_creator = r_serv_tracker.hget('tracker:{}'.format(tracker_uuid), 'user_id')
if not tracker_creator:
return ({"status": "error", "reason": "Unknown uuid"}, 404)
if not is_in_role(user_id, 'admin') or user_id != tracker_creator:
return ({"status": "error", "reason": "Access Denied"}, 403)
return ({"uuid": tracker_uuid}, 200)
##-- ACL --##
#### CREATE TRACKER ####
def api_validate_tracker_to_add(tracker , tracker_type, nb_words=1):
if tracker_type=='regex':
if not is_valid_regex(tracker):
return ({"status": "error", "reason": "Invalid regex"}, 400)
elif tracker_type=='word' or tracker_type=='set':
# force lowercase
tracker = tracker.lower()
word_set = set(tracker)
set_inter = word_set.intersection(special_characters)
if set_inter:
return ({"status": "error", "reason": f'special character(s) not allowed: {set_inter}', "message": "Please use a python regex or remove all special characters"}, 400)
words = tracker.split()
# not a word
if tracker_type=='word' and len(words)>1:
tracker_type = 'set'
# ouput format: tracker1,tracker2,tracker3;2
if tracker_type=='set':
try:
nb_words = int(nb_words)
except:
nb_words = 1
if nb_words==0:
nb_words = 1
words_set = set(words)
words_set = sorted(words_set)
if nb_words > len(words_set):
nb_words = len(words_set)
tracker = ",".join(words_set)
tracker = "{};{}".format(tracker, nb_words)
elif tracker_type=='yara_custom':
if not is_valid_yara_rule(tracker):
return ({"status": "error", "reason": "Invalid custom Yara Rule"}, 400)
elif tracker_type=='yara_default':
if not is_valid_default_yara_rule(tracker):
return ({"status": "error", "reason": "The Yara Rule doesn't exist"}, 400)
else:
return ({"status": "error", "reason": "Incorrect type"}, 400)
return ({"status": "success", "tracker": tracker, "type": tracker_type}, 200)
def create_tracker(tracker, tracker_type, user_id, level, tags, mails, description, dashboard=0, tracker_uuid=None):
# edit tracker
if tracker_uuid:
edit_tracker = True
# check if type changed
old_type = get_tracker_type(tracker_uuid)
old_tracker = get_tracker_by_uuid(tracker_uuid)
old_level = get_tracker_level(tracker_uuid)
tracker_user_id = get_tracker_user_id(tracker_uuid)
# Create new tracker
else:
edit_tracker = False
# generate tracker uuid
tracker_uuid = str(uuid.uuid4())
old_type = None
old_tracker = None
# YARA
if tracker_type == 'yara_custom' or tracker_type == 'yara_default':
# delete yara rule
if tracker_type == 'yara_default' and old_type == 'yara':
if not is_default_yara_rule(old_tracker):
filepath = get_yara_rule_file_by_tracker_name(old_tracker)
if filepath:
os.remove(filepath)
tracker = save_yara_rule(tracker_type, tracker, tracker_uuid=tracker_uuid)
tracker_type = 'yara'
# create metadata
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'tracked', tracker)
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'type', tracker_type)
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'date', datetime.date.today().strftime("%Y%m%d"))
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'level', level)
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'dashboard', dashboard)
if not edit_tracker:
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'user_id', user_id)
if description:
r_serv_tracker.hset('tracker:{}'.format(tracker_uuid), 'description', description)
# type change
if edit_tracker:
r_serv_tracker.srem('all:tracker:{}'.format(old_type), old_tracker)
r_serv_tracker.srem('all:tracker_uuid:{}:{}'.format(old_type, old_tracker), tracker_uuid)
if level != old_level:
if level == 0:
r_serv_tracker.srem('global:tracker', tracker_uuid)
elif level == 1:
r_serv_tracker.srem('user:tracker:{}'.format(tracker_user_id), tracker_uuid)
if tracker_type != old_type:
if old_level == 0:
r_serv_tracker.srem('user:tracker:{}:{}'.format(tracker_user_id, old_type), tracker_uuid)
elif old_level == 1:
r_serv_tracker.srem('global:tracker:{}'.format(old_type), tracker_uuid)
if old_type=='yara':
if not is_default_yara_rule(old_tracker):
filepath = get_yara_rule_file_by_tracker_name(old_tracker)
if filepath:
os.remove(filepath)
# create all tracker set
r_serv_tracker.sadd('all:tracker:{}'.format(tracker_type), tracker)
# create tracker - uuid map
r_serv_tracker.sadd('all:tracker_uuid:{}:{}'.format(tracker_type, tracker), tracker_uuid)
# add display level set
if level == 0: # user only
r_serv_tracker.sadd('user:tracker:{}'.format(user_id), tracker_uuid)
r_serv_tracker.sadd('user:tracker:{}:{}'.format(user_id, tracker_type), tracker_uuid)
elif level == 1: # global
r_serv_tracker.sadd('global:tracker', tracker_uuid)
r_serv_tracker.sadd('global:tracker:{}'.format(tracker_type), tracker_uuid)
# create tracker tags list
for tag in tags:
r_serv_tracker.sadd('tracker:tags:{}'.format(tracker_uuid), escape(tag) )
# create tracker tags mail notification list
for mail in mails:
r_serv_tracker.sadd('tracker:mail:{}'.format(tracker_uuid), escape(mail) )
# toggle refresh module tracker list/set
r_serv_tracker.set('tracker:refresh:{}'.format(tracker_type), time.time())
if tracker_type != old_type: # toggle old type refresh
r_serv_tracker.set('tracker:refresh:{}'.format(old_type), time.time())
return tracker_uuid
def api_add_tracker(dict_input, user_id):
tracker = dict_input.get('tracker', None)
if not tracker:
return ({"status": "error", "reason": "Tracker not provided"}, 400)
tracker_type = dict_input.get('type', None)
if not tracker_type:
return ({"status": "error", "reason": "Tracker type not provided"}, 400)
nb_words = dict_input.get('nb_words', 1)
description = dict_input.get('description', '')
description = escape(description)
res = api_validate_tracker_to_add(tracker , tracker_type, nb_words=nb_words)
if res[1]!=200:
return res
tracker = res[0]['tracker']
tracker_type = res[0]['type']
tags = dict_input.get('tags', [])
mails = dict_input.get('mails', [])
res = verify_mail_list(mails)
if res:
return res
## TODO: add dashboard key
level = dict_input.get('level', 1)
try:
level = int(level)
if level not in range(0, 1):
level = 1
except:
level = 1
tracker_uuid = dict_input.get('uuid', None)
# check edit ACL
if tracker_uuid:
res = api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
if res[1] != 200:
return res
else:
# check if tracker already tracked in global
if level==1:
if is_tracker_in_global_level(tracker, tracker_type) and not tracker_uuid:
return ({"status": "error", "reason": "Tracker already exist"}, 409)
else:
if is_tracker_in_user_level(tracker, tracker_type, user_id) and not tracker_uuid:
return ({"status": "error", "reason": "Tracker already exist"}, 409)
tracker_uuid = create_tracker(tracker , tracker_type, user_id, level, tags, mails, description, tracker_uuid=tracker_uuid)
return ({'tracker': tracker, 'type': tracker_type, 'uuid': tracker_uuid}, 200)
##-- CREATE TRACKER --##
##############
#### YARA ####
def get_yara_rules_dir():
return os.path.join(os.environ['AIL_BIN'], 'trackers', 'yara')
@ -99,15 +431,32 @@ def is_valid_yara_rule(yara_rule):
except:
return False
def is_valid_default_yara_rule(yara_rule):
def is_default_yara_rule(tracked_yara_name):
yara_dir = get_yara_rules_dir()
filename = os.path.join(yara_dir, tracked_yara_name)
filename = os.path.realpath(filename)
try:
if tracked_yara_name.split('/')[0] == 'custom-rules':
return False
except:
return False
if not os.path.commonprefix([filename, yara_dir]) == yara_dir:
return False
else:
if os.path.isfile(filename):
return True
return False
def is_valid_default_yara_rule(yara_rule, verbose=True):
yara_dir = get_yara_rules_default_dir()
filename = os.path.join(yara_dir, yara_rule)
filename = os.path.realpath(filename)
# incorrect filename
if not os.path.commonprefix([filename, yara_dir]) == yara_dir:
print('error: file transversal')
print(yara_dir)
print(filename)
if verbose:
print('error: file transversal')
print(yara_dir)
print(filename)
return False
else:
if os.path.isfile(filename):
@ -126,6 +475,17 @@ def save_yara_rule(yara_rule_type, yara_rule, tracker_uuid=None):
filename = os.path.join('ail-yara-rules', 'rules', yara_rule)
return filename
def get_yara_rule_file_by_tracker_name(tracked_yara_name):
yara_dir = get_yara_rules_dir()
filename = os.path.join(yara_dir, tracked_yara_name)
filename = os.path.realpath(filename)
if not os.path.commonprefix([filename, yara_dir]) == yara_dir:
print('error: file transversal')
print(yara_dir)
print(filename)
return None
return filename
def get_yara_rule_content(yara_rule):
yara_dir = get_yara_rules_dir()
filename = os.path.join(yara_dir, yara_rule)
@ -157,7 +517,6 @@ def api_get_default_rule_content(default_yara_rule):
##-- YARA --##
if __name__ == '__main__':
res = is_valid_yara_rule('rule dummy { }')
print(res)

View File

@ -38,6 +38,8 @@ tokenizer = RegexpTokenizer('[\&\~\:\;\,\.\(\)\{\}\|\[\]\\\\/\-/\=\'\"\%\$\?\@\+
gaps=True, discard_empty=True)
def is_valid_uuid_v4(UUID):
if not UUID:
return False
UUID = UUID.replace('-', '')
try:
uuid_test = uuid.UUID(hex=UUID, version=4)
@ -215,11 +217,12 @@ def parse_tracked_term_to_add(term , term_type, nb_words=1):
words_set = set(words)
words_set = sorted(words_set)
if nb_words > len(words_set):
nb_words = len(words_set)
term = ",".join(words_set)
term = "{};{}".format(term, nb_words)
if nb_words > len(words_set):
nb_words = len(words_set)
elif term_type=='yara_custom':
if not Tracker.is_valid_yara_rule(term):
return ({"status": "error", "reason": "Invalid custom Yara Rule"}, 400)
@ -322,8 +325,11 @@ def delete_term(term_uuid):
r_serv_term.delete('tracker:stat:{}'.format(term_uuid))
if term_type == 'yara':
# # TODO:
pass
# delete custom rule
if not Tracker.is_default_yara_rule(term):
filepath = Tracker.get_yara_rule_file_by_tracker_name(term)
if filepath:
os.remove(filepath)
def replace_tracker_description(term_uuid, description):
description = escape(description)

View File

@ -93,8 +93,9 @@ def tracked_menu_yara():
@login_analyst
def add_tracked_menu():
if request.method == 'POST':
term = request.form.get("term")
term_type = request.form.get("tracker_type")
tracker = request.form.get("tracker")
tracker_uuid = request.form.get("tracker_uuid")
tracker_type = request.form.get("tracker_type")
nb_words = request.form.get("nb_word", 1)
description = request.form.get("description", '')
level = request.form.get("level", 0)
@ -102,15 +103,15 @@ def add_tracked_menu():
mails = request.form.get("mails", [])
# YARA #
if term_type == 'yara':
if tracker_type == 'yara':
yara_default_rule = request.form.get("yara_default_rule")
yara_custom_rule = request.form.get("yara_custom_rule")
if yara_custom_rule:
term = yara_custom_rule
term_type='yara_custom'
tracker = yara_custom_rule
tracker_type='yara_custom'
else:
term = yara_default_rule
term_type='yara_default'
tracker = yara_default_rule
tracker_type='yara_default'
# #
if level == 'on':
@ -121,17 +122,58 @@ def add_tracked_menu():
if tags:
tags = tags.split()
input_dict = {"term": term, "type": term_type, "nb_words": nb_words, "tags": tags, "mails": mails, "level": level, "description": description}
input_dict = {"tracker": tracker, "type": tracker_type, "nb_words": nb_words, "tags": tags, "mails": mails, "level": level, "description": description}
user_id = current_user.get_id()
res = Term.parse_json_term_to_add(input_dict, user_id)
# edit tracker
if tracker_uuid:
input_dict['uuid'] = tracker_uuid
res = Tracker.api_add_tracker(input_dict, user_id)
if res[1] == 200:
return redirect(url_for('hunter.tracked_menu'))
else:
## TODO: use modal
return Response(json.dumps(res[0], indent=2, sort_keys=True), mimetype='application/json'), res[1]
else:
all_yara_files = Tracker.get_all_default_yara_files()
return render_template("Add_tracker.html", all_yara_files=all_yara_files)
return render_template("edit_tracker.html", all_yara_files=Tracker.get_all_default_yara_files())
@hunter.route("/tracker/edit", methods=['GET', 'POST'])
@login_required
@login_analyst
def edit_tracked_menu():
user_id = current_user.get_id()
tracker_uuid = request.args.get('uuid', None)
res = Term.check_term_uuid_valid_access(tracker_uuid, user_id) # check if is author or admin
if res: # invalid access
return Response(json.dumps(res[0], indent=2, sort_keys=True), mimetype='application/json'), res[1]
dict_tracker = Tracker.get_tracker_metedata(tracker_uuid, user_id=True, level=True, description=True, tags=True, mails=True)
dict_tracker['tags'] = ' '.join(dict_tracker['tags'])
dict_tracker['mails'] = ' '.join(dict_tracker['mails'])
if dict_tracker['type'] == 'set':
dict_tracker['tracker'], dict_tracker['nb_words'] = dict_tracker['tracker'].split(';')
dict_tracker['tracker'] = dict_tracker['tracker'].replace(',', ' ')
elif dict_tracker['type'] == 'yara': #is_valid_default_yara_rule
if Tracker.is_default_yara_rule(dict_tracker['tracker']):
dict_tracker['yara_file'] = dict_tracker['tracker'].split('/')
dict_tracker['yara_file'] = dict_tracker['yara_file'][-2] + '/' + dict_tracker['yara_file'][-1]
dict_tracker['content'] = None
else:
dict_tracker['yara_file'] = None
dict_tracker['content'] = Tracker.get_yara_rule_content(dict_tracker['tracker'])
return render_template("edit_tracker.html", dict_tracker=dict_tracker,
all_yara_files=Tracker.get_all_default_yara_files())
## TO EDIT
# word
# set of word + nb words
# regex
# yara custum
# yara default ???? => allow edit ?
#### EDIT SHow Trackers ??????????????????????????????????????????????????
@hunter.route("/tracker/show_tracker")
@login_required

View File

@ -27,39 +27,41 @@
<div class="col-12 col-lg-10" id="core_content">
<div class="card mb-3 mt-1">
<div class="card-header">
<h5 class="card-title">Create a new tracker</h5>
<div class="card my-3">
<div class="card-header bg-dark text-white">
<h5 class="card-title">Edit a Tracker</h5>
</div>
<div class="card-body">
<p class="card-text">Select a tracker type.</p>
<form action="{{ url_for('hunter.add_tracked_menu') }}" method='post'>
{%if dict_tracker%}
<input id="tracker_uuid" name="tracker_uuid" class="form-control" type="text" value="{{dict_tracker['uuid']}}" hidden>
{%endif%}
<div class="row">
<div class="col-12 col-xl-9">
<div class="input-group mb-2 mr-sm-2">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-tag"></i></div>
<div class="input-group-text bg-danger text-white"><i class="fas fa-tag"></i></div>
</div>
<input id="tags" name="tags" class="form-control" placeholder="Tags (optional, space separated)" type="text">
<input id="tags" name="tags" class="form-control" placeholder="Tags (optional, space separated)" type="text" {%if dict_tracker%}{%if dict_tracker['tags']%}value="{{dict_tracker['tags']}}"{%endif%}{%endif%}>
</div>
<div class="input-group mb-2 mr-sm-2">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-at"></i></div>
<div class="input-group-text bg-secondary text-white"><i class="fas fa-at"></i></div>
</div>
<input id="mails" name="mails" class="form-control" placeholder="E-Mails Notification (optional, space separated)" type="text">
<input id="mails" name="mails" class="form-control" placeholder="E-Mails Notification (optional, space separated)" type="text" {%if dict_tracker%}{%if dict_tracker['mails']%}value="{{dict_tracker['mails']}}"{%endif%}{%endif%}>
</div>
<div class="input-group mb-2 mr-sm-2">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-pencil-alt"></i></div>
<div class="input-group-text bg-info text-white"><i class="fas fa-pencil-alt"></i></div>
</div>
<input id="description" name="description" class="form-control" placeholder="Tracker Description (optional)" type="text">
<input id="description" name="description" class="form-control" placeholder="Tracker Description (optional)" type="text" {%if dict_tracker%}{%if dict_tracker['description']%}value="{{dict_tracker['description']}}"{%endif%}{%endif%}>
</div>
</div>
<div class="col-12 col-xl-3">
<div class="custom-control custom-switch mt-1">
<input class="custom-control-input" type="checkbox" name="level" id="id_level" checked>
<input class="custom-control-input" type="checkbox" name="level" id="id_level" {%if dict_tracker%}{%if dict_tracker['level']==1%}checked{%endif%}{%else%}checked{%endif%}>
<label class="custom-control-label" for="id_level">
<i class="fas fa-users"></i>&nbsp;Show tracker to all Users
</label>
@ -68,6 +70,7 @@
</div>
<hr>
<h4>Tracker Type:</h4>
<select id="tracker_type" name="tracker_type" class="custom-select w-25 mb-3">
<option disabled selected value> -- Select a tracker type -- </option>
@ -81,10 +84,10 @@
<div class="row" id="simple_input">
<div class="col-12 col-lg-10">
<input id="term" name="term" class="form-control" placeholder="Terms to track (space separated)" type="text">
<input id="tracker" name="tracker" class="form-control" placeholder="Terms to track (space separated)" type="text" {%if dict_tracker%}{%if dict_tracker['tracker']!='yara'%}value="{{dict_tracker['tracker']}}"{%endif%}{%endif%}>
</div>
<div class="col-12 col-lg-2">
<input type="number" id="nb_word" name="nb_word" name="quantity" min="1" placeholder="Nb of keywords">
<input type="number" id="nb_word" name="nb_word" name="quantity" min="1" placeholder="Nb of keywords" {%if dict_tracker%}{%if dict_tracker['nb_words']%}value="{{dict_tracker['nb_words']}}"{%endif%}{%endif%}>
</div>
</div>
@ -92,11 +95,12 @@
<div class="mb-2" id="yara_rule">
<div class="" id="yara_default_rules">
<select class="custom-select w-100 mb-3" name="yara_default_rule" onchange="get_default_rule_content(this);">
<h6>Default YARA rules:</h6>
<select class="custom-select w-100 mb-3" id="yara_default_rule" name="yara_default_rule" onchange="get_default_rule_content(this);">
<option selected>Select a default rule</option>
{% for yara_types in all_yara_files %}
{% for yara_file in all_yara_files[yara_types] %}
<option value="{{yara_types}}/{{yara_file}}">{{yara_types}} - {{yara_file}}</option>
{% for yara_file_name in all_yara_files[yara_types] %}
<option value="{{yara_types}}/{{yara_file_name}}">{{yara_types}} - {{yara_file_name}}</option>
{% endfor %}
{% endfor %}
</select>
@ -107,14 +111,15 @@
<hr>
<h6>Custom YARA rules:</h6>
<div class="row" id="textarea">
<textarea class="form-control mx-3" id="text_input" name="yara_custom_rule" placeholder="Enter your own YARA rule" rows="5"></textarea>
<textarea class="form-control mx-3" id="text_input" name="yara_custom_rule" placeholder="Enter your own YARA rule" rows="5">{%if dict_tracker%}{%if dict_tracker['type']=='yara' and dict_tracker['content']%}{{dict_tracker['content']}}{%endif%}{%endif%}</textarea>
</div>
</div>
<br>
<button class="btn btn-success mt-2">
<i class="fas fa-plus"></i> Add Tracker
<i class="fas fa-plus"></i> {%if dict_tracker%}Edit{%else%}Create{%endif%} Tracker
</button>
</form>
@ -139,7 +144,7 @@ $(document).ready(function(){
$("#page-Tracker").addClass("active");
$("#nav_manual_crawler").addClass("active");
$("#tracker_desc").hide();
$("#term").hide();
$("#tracker").hide();
$("#nb_word").hide();
$("#yara_rule").hide();
@ -148,30 +153,38 @@ $(document).ready(function(){
if (tracker_type=="word") {
$("#tracker_desc").text("Token to track. You need to use a regex if you want to use one of the following special characters [<>~!?@#$%^&*|()_-+={}\":;,.\'\n\r\t]/\\ ");
$("#tracker_desc").show();
$("#term").show();
$("#tracker").show();
$("#nb_word").hide();
$("#yara_rule").hide();
} else if (tracker_type=="set") {
$("#tracker_desc").text("Set of Terms to track (space separated). This tracker is used to check if an item contain one or more terms specified in a set. If an item contain NB unique terms (by default NB of unique keywords = 1), this tracker is triggered. You need to use a regex if you want to use one of the following special characters [<>~!?@#$%^&*|()_-+={}\":;,.\'\n\r\t]/\\ ");
$("#tracker_desc").show();
$("#term").show();
$("#tracker").show();
$("#nb_word").show();
$("#yara_rule").hide();
} else if (tracker_type=="regex") {
$("#tracker_desc").text("Enter a valid Python regex");
$("#tracker_desc").show();
$("#term").show();
$("#tracker").show();
$("#nb_word").hide();
$("#yara_rule").hide();
} else if (tracker_type=="yara") {
$("#tracker_desc").text("Select a default yara rule or create your own rule:");
$("#tracker_desc").show();
$("#term").hide();
$("#tracker").hide();
$("#nb_word").hide();
$("#yara_rule").show();
}
});
{%if dict_tracker%}
$('#tracker_type').val('{{dict_tracker['type']}}').change();
{%if dict_tracker['type']=='yara' and dict_tracker['yara_file']%}
$('#yara_default_rule').val('{{dict_tracker['yara_file']}}').change();
{%endif%}
{%endif%}
});
function toggle_sidebar(){

View File

@ -171,10 +171,14 @@
</div>
<a href="{{ url_for('hunter.delete_tracker') }}?uuid={{tracker_metadata['uuid']}}" class="float-right" style="font-size: 15px">
<button class='btn btn-danger'><i class="fas fa-trash-alt"></i>
</button>
</a>
<div class="d-flex flex-row-reverse">
<a href="{{ url_for('hunter.delete_tracker') }}?uuid={{tracker_metadata['uuid']}}" style="font-size: 15px">
<button class='btn btn-danger'><i class="fas fa-trash-alt"></i></button>
</a>
<a href="{{ url_for('hunter.edit_tracked_menu') }}?uuid={{tracker_metadata['uuid']}}" class="mx-2" style="font-size: 15px">
<button class='btn btn-info'>Edit Tracker <i class="fas fa-pencil-alt"></i></button>
</a>
</div>
{%if yara_rule_content%}
<p class="my-0"></br></br><pre class="border bg-light">{{ yara_rule_content }}</pre></p>