mirror of https://github.com/MISP/misp-modules
new: [functionality] flowintel + multiple entry
parent
b5c459c71d
commit
1457575dda
|
@ -37,6 +37,7 @@ def create_app():
|
|||
app.register_blueprint(home_blueprint, url_prefix="/")
|
||||
app.register_blueprint(history_blueprint, url_prefix="/")
|
||||
app.register_blueprint(account_blueprint, url_prefix="/")
|
||||
csrf.exempt(home_blueprint)
|
||||
|
||||
return app
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class Session_db(db.Model):
|
|||
"id": self.id,
|
||||
"uuid": self.uuid,
|
||||
"modules": json.loads(self.modules_list),
|
||||
"query_enter": self.query_enter,
|
||||
"query_enter": json.loads(self.query_enter),
|
||||
"input_query": self.input_query,
|
||||
"config_module": json.loads(self.config_module),
|
||||
"result": json.loads(self.result),
|
||||
|
@ -51,7 +51,7 @@ class Session_db(db.Model):
|
|||
json_dict = {
|
||||
"uuid": self.uuid,
|
||||
"modules": json.loads(self.modules_list),
|
||||
"query": self.query_enter,
|
||||
"query": json.loads(self.query_enter),
|
||||
"input": self.input_query,
|
||||
"query_date": self.query_date.strftime('%Y-%m-%d %H:%M')
|
||||
}
|
||||
|
|
|
@ -146,8 +146,8 @@ def util_remove_node_session(node_uuid, parent, parent_path):
|
|||
child = parent["children"][i]
|
||||
if child["uuid"] == node_uuid:
|
||||
del parent_path["children"][i]
|
||||
return
|
||||
elif child["children"]:
|
||||
return True
|
||||
elif "children" in child and child["children"]:
|
||||
return util_remove_node_session(node_uuid, child, parent_path["children"][i])
|
||||
|
||||
def remove_node_session(node_uuid):
|
||||
|
@ -160,7 +160,9 @@ def remove_node_session(node_uuid):
|
|||
loc = i
|
||||
break
|
||||
elif q_value["children"]:
|
||||
return util_remove_node_session(node_uuid, q_value, sess[keys_list[i]])
|
||||
if util_remove_node_session(node_uuid, q_value, sess[keys_list[i]]):
|
||||
loc = i
|
||||
break
|
||||
if loc:
|
||||
del sess[keys_list[i]]
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import ast
|
||||
import json
|
||||
from flask import Blueprint, render_template, request, jsonify, session as sess
|
||||
from flask import Blueprint, redirect, render_template, request, jsonify, session as sess
|
||||
from flask_login import current_user
|
||||
from . import session_class as SessionModel
|
||||
from . import home_core as HomeModel
|
||||
from .utils.utils import admin_user_active
|
||||
from .utils.utils import admin_user_active, FLOWINTEL_URL
|
||||
|
||||
home_blueprint = Blueprint(
|
||||
'home',
|
||||
|
@ -13,18 +14,35 @@ home_blueprint = Blueprint(
|
|||
)
|
||||
|
||||
|
||||
@home_blueprint.route("/")
|
||||
@home_blueprint.route("/", methods=["GET", "POST"])
|
||||
def home():
|
||||
try:
|
||||
del sess["query"]
|
||||
except:
|
||||
pass
|
||||
sess["admin_user"] = bool(admin_user_active())
|
||||
if "query" in request.args:
|
||||
return render_template("home.html", query=request.args.get("query"))
|
||||
sess["query"] = ast.literal_eval(request.args.get("query"))
|
||||
if "query" in request.form:
|
||||
sess["query"] = json.loads(request.form.get("query"))
|
||||
return render_template("home.html")
|
||||
|
||||
@home_blueprint.route("/get_query", methods=['GET', 'POST'])
|
||||
def get_query():
|
||||
"""Get result from flowintel"""
|
||||
if "query" in sess:
|
||||
return {"query": sess.get("query")}
|
||||
return {"message": "No query"}
|
||||
|
||||
@home_blueprint.route("/home/<sid>", methods=["GET", "POST"])
|
||||
def home_query(sid):
|
||||
try:
|
||||
del sess["query"]
|
||||
except:
|
||||
pass
|
||||
sess["admin_user"] = admin_user_active()
|
||||
if "query" in request.args:
|
||||
query = request.args.get("query")
|
||||
sess["query"] = [request.args.get("query")]
|
||||
return render_template("home.html", query=query, sid=sid)
|
||||
return render_template("404.html")
|
||||
|
||||
|
@ -33,21 +51,28 @@ def query(sid):
|
|||
sess["admin_user"] = admin_user_active()
|
||||
session = HomeModel.get_session(sid)
|
||||
flag=False
|
||||
modules_list = []
|
||||
if session:
|
||||
flag = True
|
||||
query_loc = session.query_enter
|
||||
query_loc = json.loads(session.query_enter)
|
||||
modules_list = json.loads(session.modules_list)
|
||||
else:
|
||||
for s in SessionModel.sessions:
|
||||
if s.uuid == sid:
|
||||
flag = True
|
||||
query_loc = s.query
|
||||
session=s
|
||||
modules_list = session.modules_list
|
||||
query_str = ", ".join(query_loc)
|
||||
if len(query_str) > 40:
|
||||
query_str = query_str[0:40] + "..."
|
||||
if flag:
|
||||
return render_template("query.html",
|
||||
query=query_loc,
|
||||
query_str=query_str,
|
||||
sid=sid,
|
||||
input_query=session.input_query,
|
||||
modules=json.loads(session.modules_list),
|
||||
modules=modules_list,
|
||||
query_date=session.query_date.strftime('%Y-%m-%d %H:%M'))
|
||||
return render_template("404.html")
|
||||
|
||||
|
@ -60,18 +85,20 @@ def get_query_info(sid):
|
|||
flag=False
|
||||
if session:
|
||||
flag = True
|
||||
query_loc = session.query_enter
|
||||
query_loc = json.loads(session.query_enter)
|
||||
modules_list = json.loads(session.modules_list)
|
||||
else:
|
||||
for s in SessionModel.sessions:
|
||||
if s.uuid == sid:
|
||||
flag = True
|
||||
query_loc = s.query
|
||||
modules_list = s.modules_list
|
||||
session=s
|
||||
if flag:
|
||||
loc_dict = {
|
||||
"query": query_loc,
|
||||
"input_query": session.input_query,
|
||||
"modules": json.loads(session.modules_list),
|
||||
"modules": modules_list,
|
||||
"query_date": session.query_date.strftime('%Y-%m-%d %H:%M')
|
||||
}
|
||||
return loc_dict
|
||||
|
@ -227,3 +254,9 @@ def change_status():
|
|||
return {'message': 'Something went wrong', 'toast_class': "danger-subtle"}, 400
|
||||
return {'message': 'Need to pass "module_id"', 'toast_class': "warning-subtle"}, 400
|
||||
return {'message': 'Permission denied', 'toast_class': "danger-subtle"}, 403
|
||||
|
||||
|
||||
@home_blueprint.route("/flowintel_url")
|
||||
def flowintel_url():
|
||||
"""send result to flowintel-cm"""
|
||||
return {"url": f"{FLOWINTEL_URL}/analyzer/recieve_result"}, 200
|
||||
|
|
|
@ -163,7 +163,7 @@ def create_new_session_tree(current_session, parent_id):
|
|||
loc_json = {
|
||||
"uuid": loc_session.uuid,
|
||||
"modules": json.loads(loc_session.modules_list),
|
||||
"query": loc_session.query_enter,
|
||||
"query": json.loads(loc_session.query_enter),
|
||||
"input": loc_session.input_query,
|
||||
"query_date": loc_session.query_date.strftime('%Y-%m-%d %H:%M'),
|
||||
"config": json.loads(loc_session.config_module),
|
||||
|
|
|
@ -64,9 +64,12 @@ class Session_class:
|
|||
|
||||
def start(self):
|
||||
"""Start all worker"""
|
||||
for i in range(len(self.modules_list)):
|
||||
#need the index and the url in each queue item.
|
||||
self.jobs.put((i, self.modules_list[i]))
|
||||
cp = 0
|
||||
for i in self.query:
|
||||
for j in self.modules_list:
|
||||
self.jobs.put((cp, i, j))
|
||||
cp += 1
|
||||
#need the index and the url in each queue item.
|
||||
for _ in range(self.thread_count):
|
||||
worker = Thread(target=self.process)
|
||||
worker.daemon = True
|
||||
|
@ -111,44 +114,44 @@ class Session_class:
|
|||
|
||||
modules = query_get_module()
|
||||
loc_query = {}
|
||||
self.result[work[1]] = dict()
|
||||
# If Misp format
|
||||
for module in modules:
|
||||
if module["name"] == work[1]:
|
||||
if module["name"] == work[2]:
|
||||
if "format" in module["mispattributes"]:
|
||||
loc_query = {
|
||||
"type": self.input_query,
|
||||
"value": self.query,
|
||||
"value": work[1],
|
||||
"uuid": str(uuid.uuid4())
|
||||
}
|
||||
break
|
||||
|
||||
loc_config = {}
|
||||
if work[1] in self.config_module:
|
||||
loc_config = self.config_module[work[1]]
|
||||
if work[2] in self.config_module:
|
||||
loc_config = self.config_module[work[2]]
|
||||
|
||||
if loc_query:
|
||||
send_to = {"module": work[1], "attribute": loc_query, "config": loc_config}
|
||||
send_to = {"module": work[2], "attribute": loc_query, "config": loc_config}
|
||||
else:
|
||||
send_to = {"module": work[1], self.input_query: self.query, "config": loc_config}
|
||||
send_to = {"module": work[2], self.input_query: work[1], "config": loc_config}
|
||||
res = query_post_query(send_to)
|
||||
|
||||
## Sort attr in object by ui-priority
|
||||
if "results" in res:
|
||||
if "Object" in res["results"]:
|
||||
for obj in res["results"]["Object"]:
|
||||
loc_obj = get_object(obj["name"])
|
||||
if loc_obj:
|
||||
for attr in obj["Attribute"]:
|
||||
attr["ui-priority"] = loc_obj["attributes"][attr["object_relation"]]["ui-priority"]
|
||||
|
||||
# After adding 'ui-priority'
|
||||
obj["Attribute"].sort(key=lambda x: x["ui-priority"], reverse=True)
|
||||
if res:
|
||||
if "results" in res:
|
||||
if "Object" in res["results"]:
|
||||
for obj in res["results"]["Object"]:
|
||||
loc_obj = get_object(obj["name"])
|
||||
if loc_obj:
|
||||
for attr in obj["Attribute"]:
|
||||
attr["ui-priority"] = loc_obj["attributes"][attr["object_relation"]]["ui-priority"]
|
||||
|
||||
# After adding 'ui-priority'
|
||||
obj["Attribute"].sort(key=lambda x: x["ui-priority"], reverse=True)
|
||||
|
||||
|
||||
# print(res)
|
||||
if "error" in res:
|
||||
if res and "error" in res:
|
||||
self.nb_errors += 1
|
||||
self.result[work[1]] = res
|
||||
self.result[work[1]][work[2]] = res
|
||||
|
||||
self.jobs.task_done()
|
||||
return True
|
||||
|
@ -161,7 +164,7 @@ class Session_class:
|
|||
s = Session_db(
|
||||
uuid=str(self.uuid),
|
||||
modules_list=json.dumps(self.modules_list),
|
||||
query_enter=self.query,
|
||||
query_enter=json.dumps(self.query),
|
||||
input_query=self.input_query,
|
||||
config_module=json.dumps(self.config_module),
|
||||
result=json.dumps(self.result),
|
||||
|
|
|
@ -6,7 +6,7 @@ export default {
|
|||
},
|
||||
|
||||
template: `
|
||||
<li><a :href="'/query/'+history.uuid" :title="'Attribute: \\n' +history.input+ '\\n\\nModules: \\n' + history.modules">[[history.query]]</a></li>
|
||||
<li v-if="history.query"><a :href="'/query/'+history.uuid" :title="'Attribute: \\n' +history.input+ '\\n\\nModules: \\n' + history.modules">[[history.query.join(", ")]]</a></li>
|
||||
<ul>
|
||||
<template v-for="child in history.children">
|
||||
<history_view :history="child"></history_view>
|
||||
|
|
|
@ -48,7 +48,7 @@ export default {
|
|||
|
||||
<ul class="list-group list-group-horizontal" style="padding-top: 5px;">
|
||||
<li class="list-group-item">
|
||||
<h5>[[history.query]]</h5>
|
||||
<h5>[[history.query.join(", ")]]</h5>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<h5 style="color: brown"><u>Input Attributes</u></h5>
|
||||
|
@ -69,7 +69,7 @@ export default {
|
|||
<div class="collapse" :id="'collapse'+history.uuid" style="width: 70%; margin-left: 30px">
|
||||
<div class="card card-body">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">[[history.query]]</h5>
|
||||
<h5 class="mb-1">[[history.query.join(", ")]]</h5>
|
||||
<small><i>[[history.uuid]]</i></small>
|
||||
</div>
|
||||
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||
|
|
|
@ -10,13 +10,15 @@ function parseMispObject(misp_object, query_url, functionToCall){
|
|||
if(query_url){
|
||||
$query=$("<a>").attr("href", query_url+v.value).text("query").css("margin-left", "10px")
|
||||
}
|
||||
// `_${functionToCall.name}('${v.value}')` refer to 'window._query_as_same = query_as_same' in my vue file
|
||||
$query_same = $("<button>").attr({"onclick": `_${functionToCall.name}('${v.value}')`,
|
||||
"title": "Query this value with the same attribute and modules as the main query",
|
||||
"class": "btn btn-link"
|
||||
})
|
||||
.text("query as same")
|
||||
.css({"margin-left": "10px", "padding": "0", "--bs-btn-border-width": "0"})
|
||||
if(functionToCall){
|
||||
// `_${functionToCall.name}('${v.value}')` refer to 'window._query_as_same = query_as_same' in my vue file
|
||||
$query_same = $("<button>").attr({"onclick": `_${functionToCall.name}('${v.value}')`,
|
||||
"title": "Query this value with the same attribute and modules as the main query",
|
||||
"class": "btn btn-link"
|
||||
})
|
||||
.text("query as same")
|
||||
.css({"margin-left": "10px", "padding": "0", "--bs-btn-border-width": "0"})
|
||||
}
|
||||
}
|
||||
|
||||
$container.append(
|
||||
|
@ -74,12 +76,14 @@ function parseMispAttr(misp_attr, misp_types, key, query_url, query_as_same){
|
|||
$query=$("<a>").attr("href", query_url+misp_attr).text("query").css("margin-left", "10px")
|
||||
}
|
||||
// `_${functionToCall.name}('${misp_attr}')` refer to 'window._query_as_same = query_as_same' in my vue file
|
||||
$query_same = $("<button>").attr({"onclick": `_${query_as_same.name}('${misp_attr}')`,
|
||||
"title": "Query this value with the same attribute and modules as the main query",
|
||||
"class": "btn btn-link"
|
||||
})
|
||||
.text("query as same")
|
||||
.css({"margin-left": "10px", "padding": "0", "--bs-btn-border-width": "0"})
|
||||
if(query_as_same){
|
||||
$query_same = $("<button>").attr({"onclick": `_${query_as_same.name}('${misp_attr}')`,
|
||||
"title": "Query this value with the same attribute and modules as the main query",
|
||||
"class": "btn btn-link"
|
||||
})
|
||||
.text("query as same")
|
||||
.css({"margin-left": "10px", "padding": "0", "--bs-btn-border-width": "0"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<div class="list-group" style="margin-bottom: 20px;">
|
||||
<a :href="'/query/'+h.uuid" class="list-group-item list-group-item-action">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">[[h.query]]</h5>
|
||||
<h5 class="mb-1">[[h.query.join(", ")]]</h5>
|
||||
<small><i>[[h.uuid]]</i></small>
|
||||
</div>
|
||||
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<a style="text-decoration: none; color: black;" data-bs-toggle="collapse" :href="'#collapse'+his.uuid" role="button" aria-expanded="false" :aria-controls="'collapse'+his.uuid">
|
||||
<ul class="list-group list-group-horizontal">
|
||||
<li class="list-group-item">
|
||||
<h4>[[his.query]]</h4>
|
||||
<h4>[[his.query.join(", ")]]</h4>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<h5 style="color: brown"><u>Input Attributes</u></h5>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<div class="collapse" :id="'collapse'+his.uuid" style="width: 70%; margin-left:30px">
|
||||
<div class="card card-body">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">[[his.query]]</h5>
|
||||
<h5 class="mb-1">[[his.query.join(", ")]]</h5>
|
||||
<small><i>[[his.uuid]]</i></small>
|
||||
</div>
|
||||
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||
|
|
|
@ -19,10 +19,15 @@
|
|||
</div>
|
||||
<div class="col-11">
|
||||
<div style="width:50%; transform: translate(50%, 0);">
|
||||
<div>
|
||||
<input type="hidden" id="parent_id" value="{{sid}}">
|
||||
<input type="text" value="{{query}}" id="process-query" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
|
||||
</div>
|
||||
<template v-for="elem in cp_entries">
|
||||
<div style="margin-top: 10px;">
|
||||
<input type="hidden" id="parent_id" value="{{sid}}">
|
||||
<input type="text" v-if="queries" :value="queries[elem-1]" :id="'process-query-'+elem" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
|
||||
<input type="text" v-else :id="'process-query-'+elem" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
|
||||
</div>
|
||||
</template>
|
||||
<button @click="add_entry()" class="btn btn-secondary" style="margin-top: 10px;">Add new entry</button>
|
||||
<button @click="delete_entry()" class="btn btn-danger" style="margin-top: 10px;">Delete entry</button>
|
||||
<span v-if="status_site" style="color: brown;" id="status">[[status_site]]</span>
|
||||
</div>
|
||||
|
||||
|
@ -86,14 +91,35 @@
|
|||
|
||||
const progress = ref(0)
|
||||
|
||||
const current_query = ref()
|
||||
const current_query = ref([])
|
||||
const status_site = ref()
|
||||
|
||||
const config_query = ref([])
|
||||
|
||||
const cp_entries = ref(1)
|
||||
const queries = ref()
|
||||
|
||||
|
||||
async function fetchQuery(){
|
||||
const res = await fetch('/get_query')
|
||||
let loc = await res.json()
|
||||
if("message" in loc){
|
||||
queries.value = false
|
||||
}else{
|
||||
queries.value = loc["query"]
|
||||
cp_entries.value = queries.value.length
|
||||
}
|
||||
}
|
||||
fetchQuery()
|
||||
|
||||
|
||||
async function actionQuery(){
|
||||
current_query.value = $("#process-query").val()
|
||||
current_query.value = []
|
||||
for(let i=1;i<=cp_entries.value;i++){
|
||||
let loc_query_res = $("#process-query-"+i).val()
|
||||
if(loc_query_res)
|
||||
current_query.value.push(loc_query_res)
|
||||
}
|
||||
if (!current_query.value) {
|
||||
status_site.value = '↖ You need to type something'
|
||||
window.scrollTo(0, 0);
|
||||
|
@ -178,16 +204,6 @@
|
|||
width: '50%'
|
||||
})
|
||||
}
|
||||
if (!$('.select2-expansion').hasClass("select2-hidden-accessible")) {
|
||||
$('.select2-expansion').select2({
|
||||
theme: 'bootstrap-5'
|
||||
})
|
||||
}
|
||||
if (!$('.select2-hover').hasClass("select2-hidden-accessible")) {
|
||||
$('.select2-hover').select2({
|
||||
theme: 'bootstrap-5'
|
||||
})
|
||||
}
|
||||
|
||||
$('#input_select').on('change.select2', async function (e) {
|
||||
attr_selected.value = $(this).select2('data').map(item => item.id)[0]
|
||||
|
@ -199,7 +215,8 @@
|
|||
|
||||
if (!$('.select2-modules').hasClass("select2-hidden-accessible")) {
|
||||
$('.select2-modules').select2({
|
||||
theme: 'bootstrap-5'
|
||||
theme: 'bootstrap-5',
|
||||
closeOnSelect: false
|
||||
})
|
||||
$('#modules_select').on('change.select2', async function (e) {
|
||||
let loc_list = $(this).select2('data').map(item => item.id)
|
||||
|
@ -242,6 +259,13 @@
|
|||
return loc
|
||||
}
|
||||
|
||||
function add_entry(){
|
||||
cp_entries.value += 1
|
||||
}
|
||||
function delete_entry(){
|
||||
cp_entries.value -= 1
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
message_list,
|
||||
|
@ -251,9 +275,13 @@
|
|||
attr_selected,
|
||||
status_site,
|
||||
config_query,
|
||||
cp_entries,
|
||||
queries,
|
||||
actionQuery,
|
||||
pairedList,
|
||||
checked_attr,
|
||||
add_entry,
|
||||
delete_entry,
|
||||
generateCoreFormatUI
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<br> <br>
|
||||
<input type="hidden" id="share" value="{{sid}}">
|
||||
<div id="top" style="display: ruby; margin-top: 40px;">
|
||||
<h2>{{query}}</h2>
|
||||
<h2 title="{{', '.join(query)}}">{{query_str}}</h2>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" style="float: right;" role="group" aria-label="Basic mixed styles example">
|
||||
|
@ -21,7 +21,7 @@
|
|||
<div class="dropdown-menu p-4" style="min-width: 200px;">
|
||||
<div class="mb-3">
|
||||
<label for="query_as_params" class="form-label">To query:</label>
|
||||
<input type="email" class="form-control" id="query_as_params" placeholder="{{query}}">
|
||||
<input type="email" class="form-control" id="query_as_params" placeholder="{{', '.join(query)}}">
|
||||
<div id="query_as_params_error" style="color:brown"></div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-sm" @click="query_as_params()" style="border-radius: 50px;">Query</button>
|
||||
|
@ -54,9 +54,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<span v-if="status_site" style="margin-left: 5px; font-size: 13px; float: right;">[[status_site]]</span>
|
||||
<br>
|
||||
<button class="btn btn-secondary btn-sm" @click="send_flowintel_cm_all()" title="sendd all result to Flowintel-cm" style="float: right;">Flowintel-cm all</button>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Offcanvas to navigate throw current search tree -->
|
||||
<button class="btn btn-outline-primary" style="position: fixed; right: 0px; margin-top:30px" title="Session history" data-bs-toggle="offcanvas" data-bs-target="#offcanvasScrolling" aria-controls="offcanvasScrolling">
|
||||
<i class="fa-solid fa-bars"></i>
|
||||
</button>
|
||||
|
@ -71,7 +74,7 @@
|
|||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<ul>
|
||||
<li><a :href="'/query/'+history.uuid" :title="'Attribute: \n' +history.input+ '\n\nModules: \n' + history.modules">[[history.query]]</a></li>
|
||||
<li v-if="history.query"><a :href="'/query/'+history.uuid" :title="'Attribute: \n' +history.input+ '\n\nModules: \n' + history.modules">[[history.query.join(", ")]]</a></li>
|
||||
<ul>
|
||||
<template v-for="child in history.children">
|
||||
<history_view :history="child"></history_view>
|
||||
|
@ -96,166 +99,163 @@
|
|||
</ul>
|
||||
|
||||
<div class="row" style="margin-bottom: 50px;">
|
||||
<div class="col-10">
|
||||
<template v-if="tab_list == 'visual'">
|
||||
<div data-bs-spy="scroll" data-bs-target="#list-result" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0">
|
||||
<div class="accordion" v-if="Object.keys(modules_res).length" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key" v-for="result, key in modules_res">
|
||||
<template v-if="!('error' in result)">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key" class="accordion-collapse collapse show">
|
||||
<div class="accordion-body" >
|
||||
<template v-if="'Object' in result.results">
|
||||
<template v-for="obj in result.results.Object">
|
||||
<div v-html="parseMispObject(obj, '/home/{{sid}}?query=', query_as_same)[0].outerHTML"></div>
|
||||
</template>
|
||||
<div class="col-10">
|
||||
<div class="accordion" v-if="Object.keys(modules_res).length" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key_query" v-for="ele, key_query in modules_res">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpenMain-'+key_query" aria-expanded="true" :aria-controls="'panelsStayOpenMain-'+key_query">
|
||||
[[key_query]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpenMain-'+key_query" class="accordion-collapse collapse show">
|
||||
<button class="btn btn-secondary" @click="send_flowintel_cm(key_query)" title="Send this result to Flowintel-cm" style="margin-top: 10px;margin-left: 10px;">Flowintel-cm</button>
|
||||
<div class="accordion" style="padding: 25px">
|
||||
<div class="accordion-item" :id="'list-item-'+key_query+'-'+key" v-for="result, key in ele">
|
||||
<template v-if="!('error' in result)">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" style="height: 40px;" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key_query+'-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key_query+'-'+key" class="accordion-collapse collapse show">
|
||||
<!-- visual part -->
|
||||
<template v-if="tab_list == 'visual'">
|
||||
<div class="accordion-body" >
|
||||
<template v-if="'Object' in result.results">
|
||||
<template v-for="obj in result.results.Object">
|
||||
<div v-html="parseMispObject(obj, '/home/{{sid}}?query=', query_as_same)[0].outerHTML"></div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<template v-for="misp_attrs, key_loop in result.results">
|
||||
<div v-for="misp_attr in misp_attrs.values" class="accordion-body" v-html="parseMispAttr(misp_attr, misp_attrs.types, key_loop, '/home/{{sid}}?query=', query_as_same)[0].outerHTML"></div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<!-- <div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div> -->
|
||||
<template v-for="misp_attrs, key_loop in result.results">
|
||||
<div v-for="misp_attr in misp_attrs.values" class="accordion-body" v-html="parseMispAttr(misp_attr, misp_attrs.types, key_loop, '/home/{{sid}}?query=', query_as_same)[0].outerHTML"></div>
|
||||
</template>
|
||||
<!-- json part -->
|
||||
<template v-if="tab_list == 'json'">
|
||||
<div class="btn-group" role="group" style="padding: 5px; margin-left: 5px; margin-top: 5px;">
|
||||
<a class="btn btn-primary" :href="`/download/${sid}?module=${key}`" title="Download the json" >Download</a>
|
||||
</div>
|
||||
<div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors Part -->
|
||||
<hr style="margin-top: 50px; width: 95%">
|
||||
<h3 id="errors_part">Errors</h3>
|
||||
<div data-bs-spy="scroll" data-bs-target="#list-error" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0">
|
||||
<div class="accordion" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key" v-for="result, key in modules_res">
|
||||
<template v-if="'error' in result">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
<span style="margin-left: 5px;" title="Error">❌</span>
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key" class="accordion-collapse collapse show">
|
||||
<div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="tab_list == 'json'">
|
||||
<div v-if="Object.keys(modules_res).length">
|
||||
<h3 id="results_part">Results</h3>
|
||||
<div data-bs-spy="scroll" data-bs-target="#list-result" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0">
|
||||
<div class="accordion" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key" v-for="result, key in modules_res">
|
||||
<template v-if="!('error' in result)">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key" class="accordion-collapse collapse show">
|
||||
<a class="btn btn-primary" :href="`/download/${sid}?module=${key}`" title="Download the json" style="padding: 5px; margin-left: 5px; margin-top: 5px;">Download</a>
|
||||
<div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors Part -->
|
||||
<hr style="margin-top: 50px; width: 95%">
|
||||
<h3 id="errors_part">Errors</h3>
|
||||
<div data-bs-spy="scroll" data-bs-target="#list-error" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0">
|
||||
<div class="accordion" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key" v-for="result, key in modules_res">
|
||||
<template v-if="'error' in result">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
<span style="margin-left: 5px;" title="Error">❌</span>
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key" class="accordion-collapse collapse show">
|
||||
<div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="tab_list == 'markdown'">
|
||||
<div v-if="Object.keys(modules_res).length" class="accordion" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key" v-for="result, key in modules_res">
|
||||
<template v-if="!('error' in result)">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpen-'+key" aria-expanded="true" :aria-controls="'panelsStayOpen-'+key">
|
||||
[[key]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpen-'+key" class="accordion-collapse collapse show">
|
||||
<div class="accordion-body row">
|
||||
<template v-if="'Object' in result.results">
|
||||
<template v-for="obj, key_obj in result.results.Object">
|
||||
<pre>
|
||||
<!-- markdown part -->
|
||||
<template v-if="tab_list == 'markdown'">
|
||||
<div class="accordion-body">
|
||||
<template v-if="'Object' in result.results">
|
||||
<template v-for="obj, key_obj in result.results.Object">
|
||||
<pre>
|
||||
#### [[obj.name]]
|
||||
<template v-for="attr, key_attr in obj.Attribute">
|
||||
###### [[attr.object_relation]]
|
||||
Type: [[attr.type]]
|
||||
Value: [[attr.value]]
|
||||
</template>
|
||||
</pre>
|
||||
<hr>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="misp_attrs, key_loop in result.results">
|
||||
<template v-for="misp_attr in misp_attrs.values">
|
||||
<pre>
|
||||
</pre>
|
||||
<hr>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="misp_attrs, key_loop in result.results">
|
||||
<template v-for="misp_attr in misp_attrs.values">
|
||||
<pre>
|
||||
#### Attr [[key_loop +1]]
|
||||
Type: [[misp_attrs.types.join(", ")]]
|
||||
Value: [[misp_attr]]
|
||||
</pre>
|
||||
</template>
|
||||
</pre>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template> <!-- Not error -->
|
||||
</div>
|
||||
</div> <!-- Accordion -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors Part -->
|
||||
<hr style="margin-top: 50px; width: 95%">
|
||||
<h3 id="errors_part">Errors</h3>
|
||||
<div class="accordion" style="width: 95%">
|
||||
<div class="accordion-item" :id="'list-item-'+key_query" v-for="ele, key_query in modules_res">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpenMainError-'+key_query" aria-expanded="false" :aria-controls="'panelsStayOpenMainError-'+key_query">
|
||||
[[key_query]]
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpenMainError-'+key_query" class="accordion-collapse collapse">
|
||||
<div class="accordion" style="padding: 25px">
|
||||
<div class="accordion-item" :id="'list-item-'+key_query+'-'+key" v-for="result, key in ele">
|
||||
<template v-if="'error' in result">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" style="height: 40px;" data-bs-toggle="collapse" :data-bs-target="'#panelsStayOpenError-'+key_query+'-'+key" aria-expanded="false" :aria-controls="'panelsStayOpenError-'+key_query+'-'+key">
|
||||
[[key]]
|
||||
<span style="margin-left: 5px;" title="Error">❌</span>
|
||||
</button>
|
||||
</h2>
|
||||
<div :id="'panelsStayOpenError-'+key_query+'-'+key" class="accordion-collapse collapse">
|
||||
<template v-if="tab_list == 'visual' || tasb_list == 'json'">
|
||||
<div class="accordion-body" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- right menu -->
|
||||
<div id="list-result" class="list-group col-2" style="position: fixed; right: 0px;">
|
||||
<template v-for="result, key in modules_res">
|
||||
<a class="btn btn-outline-primary" data-bs-toggle="collapse" :href="'#collapse-menu-'+key" role="button" aria-expanded="false" :aria-controls="'collapse-menu-'+key">
|
||||
<template v-if="key.length > 20">
|
||||
[[key.substring(0, 21)]]...
|
||||
</template>
|
||||
<template v-else>
|
||||
[[key]]
|
||||
</template>
|
||||
</a>
|
||||
<div class="collapse" :id="'collapse-menu-'+key">
|
||||
<div class="card card-body">
|
||||
<template v-for="res, key_sub in result">
|
||||
<a class="list-group-item list-group-item-action" v-if="!('error' in res)" :href="'#list-item-'+key+'-'+key_sub">[[key_sub]]</a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div id="list-result" class="list-group col-2" style="position: fixed; right: 0px;">
|
||||
<a class="list-group-item list-group-item-action" v-if="tab_list == 'json'" style="background-color: #0d6efd; color:white" href="#results_part">Results</a>
|
||||
|
||||
<template v-for="result, key in modules_res">
|
||||
<a class="list-group-item list-group-item-action" v-if="!('error' in result)" :href="'#list-item-'+key">[[key]]</a>
|
||||
</template>
|
||||
|
||||
<template v-if="tab_list == 'json' || tab_list == 'visual'">
|
||||
<a class="list-group-item list-group-item-action" style="background-color: #0d6efd; color:white" href="#errors_part">Errors</a>
|
||||
<div id="list-error" class="list-group">
|
||||
<template v-for="result, key in modules_res">
|
||||
<a class="list-group-item list-group-item-action" v-if="'error' in result" :href="'#list-item-'+key" style="border-radius: 0;">[[key]]</a>
|
||||
</template>
|
||||
</div>
|
||||
<a class="btn btn-primary" style="background-color: #0d6efd; color:white" href="#errors_part">Errors</a>
|
||||
<template v-for="result, key in modules_res">
|
||||
<a class="btn btn-outline-primary" data-bs-toggle="collapse" :href="'#collapse-menu-error-'+key" role="button" aria-expanded="false" :aria-controls="'collapse-menu-error-'+key">
|
||||
<template v-if="key.length > 20">
|
||||
[[key.substring(0, 21)]]...
|
||||
</template>
|
||||
<template v-else>
|
||||
[[key]]
|
||||
</template>
|
||||
</a>
|
||||
<div class="collapse" :id="'collapse-menu-error-'+key">
|
||||
<div class="card card-body">
|
||||
<template v-for="res, key_sub in result">
|
||||
<a class="list-group-item list-group-item-action" v-if="'error' in res" :href="'#list-item-'+key+'-'+key_sub">[[key_sub]]</a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="goTop">[<a href="#top">Go Back Top</a>]</span>
|
||||
<div id="insert_form"></div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
|
@ -359,7 +359,7 @@ Value: [[misp_attr]]
|
|||
async function query_as_same(value){
|
||||
let result_dict = {"modules": query_info.value["modules"],
|
||||
"input": query_info.value["input_query"],
|
||||
"query": value,
|
||||
"query": [value],
|
||||
"parent_id": sid.value,
|
||||
"query_as_same": true,
|
||||
"config": {}
|
||||
|
@ -379,6 +379,7 @@ Value: [[misp_attr]]
|
|||
// query 'value' with same parameters without a parent
|
||||
async function query_as_params(){
|
||||
let loc = $("#query_as_params").val()
|
||||
loc = loc.split(', ')
|
||||
$("#query_as_params_error").text("")
|
||||
if(loc){
|
||||
let result_dict = {"modules": query_info.value["modules"],
|
||||
|
@ -403,6 +404,29 @@ Value: [[misp_attr]]
|
|||
}
|
||||
}
|
||||
|
||||
async function sender_flowintel(to_return){
|
||||
const res = await fetch('/flowintel_url')
|
||||
let loc = await res.json()
|
||||
const flowintel_cm_url = loc["url"]
|
||||
|
||||
$('#insert_form').append(
|
||||
$('<form>').attr({"action": flowintel_cm_url, "name": "flowintel", "method": "post", "style": "display:none"}).append(
|
||||
$("<input>").attr({"type": "text", "name": "result"}).val(JSON.stringify(to_return))
|
||||
)
|
||||
);
|
||||
document.forms['flowintel'].submit();
|
||||
}
|
||||
|
||||
async function send_flowintel_cm(key){
|
||||
let to_return = {}
|
||||
to_return[key] = modules_res.value[key]
|
||||
sender_flowintel(to_return)
|
||||
}
|
||||
|
||||
async function send_flowintel_cm_all(){
|
||||
sender_flowintel(modules_res.value)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
queryInfo()
|
||||
actionQuery()
|
||||
|
@ -425,7 +449,9 @@ Value: [[misp_attr]]
|
|||
parseMispAttr,
|
||||
active_tab,
|
||||
query_as_same,
|
||||
query_as_params
|
||||
query_as_params,
|
||||
send_flowintel_cm,
|
||||
send_flowintel_cm_all
|
||||
}
|
||||
}
|
||||
}).mount('.container-fluid')
|
||||
|
|
|
@ -12,6 +12,7 @@ CONF_PATH = os.path.join(os.getcwd(), "conf", "config.cfg")
|
|||
config.read(CONF_PATH)
|
||||
|
||||
MODULES = []
|
||||
FLOWINTEL_URL = Config.FLOWINTEL_URL
|
||||
|
||||
def query_get_module(headers={'Content-type': 'application/json'}):
|
||||
global MODULES
|
||||
|
|
|
@ -4,6 +4,7 @@ class Config:
|
|||
FLASK_URL = '127.0.0.1'
|
||||
FLASK_PORT = 7008
|
||||
MISP_MODULE = '127.0.0.1:6666'
|
||||
FLOWINTEL_URL = 'http://localhost:7006'
|
||||
|
||||
QUERIES_LIMIT = 200
|
||||
|
||||
|
|
Loading…
Reference in New Issue