chg: [website] query page

pull/654/head
David Cruciani 2024-02-08 11:30:55 +01:00
parent 8276650165
commit 30f84f6512
No known key found for this signature in database
GPG Key ID: 8690CDE1E3994B9B
7 changed files with 220 additions and 131 deletions

View File

@ -1,3 +1,4 @@
import json
from flask import Flask, Blueprint, render_template, request, jsonify
from . import home_core as HomeModel
from . import session as SessionModel
@ -14,6 +15,25 @@ home_blueprint = Blueprint(
def home():
return render_template("home.html")
@home_blueprint.route("/query/<sid>")
def query(sid):
session = HomeModel.get_session(sid)
flag=False
if session:
flag = True
query_loc = session.query_enter
else:
for s in SessionModel.sessions:
if s.id == sid:
flag = True
query_loc = s.query
session=s
if flag:
return render_template("query.html", query=query_loc, sid=sid, input_query=session.input_query, modules=json.loads(session.glob_query))
return render_template("404.html")
@home_blueprint.route("/get_modules")
def get_modules():
"""Return all modules available"""

View File

@ -154,7 +154,7 @@ class Session_class:
histories = History.query.all()
while len(histories) > 3:
while len(histories) > 10:
history = History.query.order_by(History.id).all()
Session_db.query.filter_by(id=history[0].session_id).delete()
History.query.filter_by(id=history[0].id).delete()

View File

@ -37,7 +37,6 @@ div#searchbox {
border: 1px solid #ccc;
border-radius: 5px 0 0 5px;
padding-left: .75em;
width: 80%;
outline: none;
}
button#query {

View File

@ -5,7 +5,7 @@
{% extends 'base.html' %}
{% block content %}
<div id="top"> <h1>History</h1> </div>
<h1 id="top">History</h1>
<hr>
<br>
@ -13,13 +13,12 @@
<div v-if="history">
<template v-for="h, key in history">
<div class="list-group" style="margin-bottom: 20px;">
<!-- <a :href="'/query/'+h.uuid" class="list-group-item list-group-item-action"> -->
<a href="#" class="list-group-item list-group-item-action">
<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">[[key+1]]- [[h.query]]</h5>
<small><i>[[h.uuid]]</i></small>
</div>
<p class="mb-1" style="color: green;"><u>Input</u>:</p>
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
<div>[[h.input]]</div>
<br>
<p class="mb-1" style="color: #2000ff;"><u>Modules</u>:</p>

View File

@ -13,16 +13,10 @@
<hr>
<br>
<div>
<div id="searchbox">
<input type="hidden" id="share" value="{{share}}">
<input type="text" id="process-query" placeholder="Enter here..." autofocus>
<!-- <button id="query" @click="actionQuery()">[[query]]</button> -->
<div style="width:50%; transform: translate(50%, 0);">
<div>
<input type="text" id="process-query" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
</div>
<div v-if="is_searching" class="progress">
<div class="progress-bar progress-bar-striped active" id="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" :style="'width:'+progress + '%;'">
</div>
</div>
<span v-if="status_site" id="status">[[status_site]]</span>
</div>
@ -48,7 +42,7 @@
<div class="row" style="margin-top: 2px;">
<div>
<div>
<h4>Input</h4>
<h4>Input Attributes</h4>
</div>
<div>
<select data-placeholder="Input" class="select2-input form-control" name="input_select" id="input_select">
@ -63,31 +57,33 @@
</div>
<!-- Results modules selection -->
<div v-if="Object.keys(modules_list).length">
<div class="row" v-if="attr_selected.length">
<div class="col-5" v-if="modules_list.expansion.length">
<div class="col-5">
<h4>Expansion</h4>
</div>
<template v-if="modules_list">
<div v-if="Object.keys(modules_list).length">
<div class="row" v-if="attr_selected.length">
<div class="col-5" v-if="modules_list.expansion.length">
<div class="col-5">
<h4>Expansions Modules</h4>
</div>
<select data-placeholder="Expansion" class="select2-expansion form-control" multiple name="expansion_select" id="expansion_select">
<template v-for="key in modules_list.expansion">
<option v-if="key.mispattributes.input.includes(attr_selected)" :value="key.name" :title="key.meta.description">[[key.name]]</option>
</template>
</select>
</div>
<div class="col-5" v-if="modules_list.hover.length">
<div class="col-5">
<h4>Hover</h4>
<select data-placeholder="Expansion" class="select2-expansion form-control" multiple name="expansion_select" id="expansion_select">
<template v-for="key in modules_list.expansion">
<option v-if="key.mispattributes.input.includes(attr_selected)" :value="key.name" :title="key.meta.description">[[key.name]]</option>
</template>
</select>
</div>
<div class="col-5" v-if="modules_list.hover.length">
<div class="col-5">
<h4>Hover Modules</h4>
</div>
<select data-placeholder="Hover" class="select2-hover form-control" multiple name="hover_select" id="hover_select">
<template v-for="key in modules_list.hover">
<option v-if="key.mispattributes.input.includes(attr_selected)" :value="key.name" :title="key.meta.description">[[key.name]]</option>
</template>
</select>
</div>
<select data-placeholder="Hover" class="select2-hover form-control" multiple name="hover_select" id="hover_select">
<template v-for="key in modules_list.hover">
<option v-if="key.mispattributes.input.includes(attr_selected)" :value="key.name" :title="key.meta.description">[[key.name]]</option>
</template>
</select>
</div>
</div>
</div>
</template>
<!-- Display in case a module as reauest_on_query activate -->
<div v-if="config_query.length" style="margin-top: 10px;" class="row">
@ -106,50 +102,6 @@
<button class="btn btn-primary" @click="actionQuery()">Query</button>
<!-- Results Part -->
<hr>
<div class="row" v-if="Object.keys(modules_res).length">
<div class="col-10">
<h3 id="results_part">Results</h3>
<div class="accordion">
<div class="accordion-item" 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" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
</div>
</template>
</div>
</div>
<!-- Errors Part -->
<hr style="margin-top: 50px">
<h3 id="errors_part">Errors</h3>
<div class="accordion">
<div class="accordion-item" 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 class="col-1" style="position: fixed; right: 0px; box-shadow: 0 2px 5px 0 rgb(0 0 0 / 5%), 0 2px 10px 0 rgb(0 0 0 / 5%);">
<div style="padding: 10px;"><a style="text-decoration: none;" href="#results_part">Results</a></div>
<div style="padding: 10px;"><a style="text-decoration: none;" href="#errors_part">Errors</a></div>
</div>
</div>
{% endblock %}
{% block script %}
@ -160,14 +112,10 @@
delimiters: ['[[', ']]'],
setup() {
const query = ref("Query")
const is_searching = ref(false)
const modules_list = ref({})
const misp_attributes_list = ref({})
const attr_selected = ref([])
const sid = ref(null)
let last_registered = 0
const modules_res = ref({})
const progress = ref(0)
let expansion_bool = false
@ -189,8 +137,6 @@
}
if (query.value == 'Query') {
last_registered = 0;
is_searching.value = true
progress.value = 0
let error_flag = false
@ -221,10 +167,10 @@
})
if(await res.status == 201){
let loc = await res.json()
is_searching.value = true
sid.value = loc['id']
query.value = 'Stop'
pollScan();
console.log(loc['id']);
await nextTick()
window.location.href="/query/" + loc['id']
}else{
let loc = await res.json()
query.value = 'Query'
@ -238,41 +184,6 @@
}
}
function pollScan() {
// Loop function to update the list of identified domains
$.getJSON('/status/' + sid.value, function(data) {
progress.value = Math.round((data['complete']/data['total'])*100)
status_site.value = 'Processed ' + data['complete'] + ' of ' + data['total']
if (data['remaining'] > 0) {
setTimeout(pollScan, 3000);
} else {
// Button Stop pressed
if (data['stopped'])
status_site.value = 'Stopped ! ' + data['complete'] - data["nb_errors"] + ' Success. ' + data["nb_errors"] + ' Errors. ' + data['complete'] + ' Total.'
// Display result of the search
else
status_site.value = data['complete'] - data["nb_errors"] + ' Success. ' + data["nb_errors"] + ' Errors. ' + data['complete'] + ' Total.'
query.value = 'Query'
}
if (last_registered < data['registered']) {
last_registered = data['registered']
fetchResult();
}
});
}
async function fetchResult(){
modules_res.value = {}
const res = await fetch("/result/"+sid.value)
let loc = await res.json()
modules_res.value = loc
}
@ -381,12 +292,10 @@
message_list,
query,
progress,
is_searching,
modules_list,
misp_attributes_list,
attr_selected,
status_site,
modules_res,
config_query,
actionQuery,
expansion_module,

View File

@ -0,0 +1,162 @@
<!--
Author: David Cruciani
-->
{% extends 'base.html' %}
{% block content %}
<h1 id="top">MISP Modules</h1>
<hr>
<br>
<div style="width:50%; transform: translate(50%, 0);">
<div>
<input type="hidden" id="share" value="{{sid}}">
<input type="text" id="process-query" value="{{query}}" class="form-control" style="border-radius: 5px;" />
</div>
<div v-if="is_searching" class="progress" >
<div class="progress-bar progress-bar-striped active" id="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" :style="'width:'+progress + '%;'">
</div>
</div>
<span v-if="status_site" id="status">[[status_site]]</span>
</div>
<button style="margin-top: 10px;" class="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseInfo" aria-expanded="false" aria-controls="collapseInfo">
More Info
</button>
<div class="collapse" id="collapseInfo">
<div class="card card-body">
<div class="row">
<div class="col">
<h4>Input Attribute:</h4>
{{input_query}}
</div>
<div class="col">
<h4>Modules:</h4>
{%for module in modules%} {{module}}, {%endfor%}
</div>
</div>
</div>
</div>
<div style="margin-top: 10px;"><a href="/">New query</a></div>
<br/>
<!-- Results Part -->
<hr>
<div class="row" v-if="Object.keys(modules_res).length">
<div class="col-10">
<h3 id="results_part">Results</h3>
<div class="accordion">
<div class="accordion-item" 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" v-html="generateCoreFormatUI(result)[0].outerHTML"></div>
</div>
</template>
</div>
</div>
<!-- Errors Part -->
<hr style="margin-top: 50px">
<h3 id="errors_part">Errors</h3>
<div class="accordion">
<div class="accordion-item" 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 class="col-1" style="position: fixed; right: 0px; box-shadow: 0 2px 5px 0 rgb(0 0 0 / 5%), 0 2px 10px 0 rgb(0 0 0 / 5%);">
<div style="padding: 10px;"><a style="text-decoration: none;" href="#results_part">Results</a></div>
<div style="padding: 10px;"><a style="text-decoration: none;" href="#errors_part">Errors</a></div>
</div>
</div>
<span id="goTop">[<a href="#top">Go Back Top</a>]</span>
{% endblock %}
{% block script %}
<script type="module">
const { createApp, ref, onMounted, nextTick, defineComponent} = Vue
import {message_list} from '/static/js/toaster.js'
createApp({
delimiters: ['[[', ']]'],
setup() {
const is_searching = ref(false)
const sid = ref(null)
let last_registered = 0
const modules_res = ref({})
const progress = ref(0)
const status_site = ref()
function actionQuery(){
is_searching.value = true
sid.value = $("#share").val()
pollScan();
}
function pollScan() {
// Loop function to update the list of identified domains
$.getJSON('/status/' + sid.value, function(data) {
progress.value = Math.round((data['complete']/data['total'])*100)
status_site.value = 'Processed ' + data['complete'] + ' of ' + data['total']
if (data['remaining'] > 0) {
setTimeout(pollScan, 3000);
} else {
// Button Stop pressed
if (data['stopped'])
status_site.value = 'Stopped ! ' + data['complete'] - data["nb_errors"] + ' Success. ' + data["nb_errors"] + ' Errors. ' + data['complete'] + ' Total.'
// Display result of the search
else
status_site.value = data['complete'] - data["nb_errors"] + ' Success. ' + data["nb_errors"] + ' Errors. ' + data['complete'] + ' Total.'
}
if (last_registered < data['registered']) {
last_registered = data['registered']
fetchResult();
}
});
}
async function fetchResult(){
modules_res.value = {}
const res = await fetch("/result/"+sid.value)
let loc = await res.json()
modules_res.value = loc
}
onMounted(() => {
actionQuery()
})
return {
message_list,
progress,
status_site,
is_searching,
modules_res,
generateCoreFormatUI
}
}
}).mount('.container')
</script>
{% endblock %}

View File

@ -1,14 +1,14 @@
<!--Main Navigation-->
<header>
<!-- Sidebar -->
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<nav id="sidebarMenu" class="d-lg-block sidebar bg-white">
<nav id="sidebarMenu" class="collapse d-lg-block sidebar collapse bg-white">
<a class="navbar-brand" style="margin-left: 20px;" href="/">
<img src="{{ url_for('static',filename='image/misp.png') }}" height="55" alt="Misp Logo" loading="lazy" />
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="position-sticky">
<div class="list-group list-group-flush mx-3 mt-4">