增加仪表盘

增加仪表盘
This commit is contained in:
huoji
2022-09-21 19:58:49 +08:00
parent 3ddca10161
commit e1fb23c112
24 changed files with 306 additions and 106 deletions

BIN
Image/dashboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@@ -231,6 +231,25 @@ def push_process_raw(
return result
def query_last_raw_process_log(num):
global g_rawdata_table
sql_session = sessionmaker(bind=g_engine)
# 用g_rawdata_table 不行, utf8编码问题
start_time = int(round(time.time() * 1000))
end_time = start_time - 1000 * 60 * 60 * 24 * 7
raw_log = (
sql_session()
.query(raw_process_log)
# .filter(
# raw_process_log.timestamp >= end_time
# )
.limit(num)
.all()
)
sql_session().close()
return raw_log
def select_process_raw_log_by_time(start: int, end: int):
global g_rawdata_table
sql_session = sessionmaker(bind=g_engine)
@@ -245,7 +264,6 @@ def select_process_raw_log_by_time(start: int, end: int):
)
.all()
)
sql_session().close()
return raw_log
@@ -320,6 +338,22 @@ def query_one_threat(threat_id):
return threat
def query_raw_host_log_num(host):
global g_rawdata_table
sql_session = sessionmaker(bind=g_engine)
num = sql_session().query(g_rawdata_table).filter_by(host=host).count()
sql_session().close()
return num
def query_threat_all_num():
global g_threat_table
sql_session = sessionmaker(bind=g_engine)
threat = sql_session().query(g_threat_table).count()
sql_session().close()
return threat
def query_all_threat_log(query_type):
global g_threat_table
sql_session = sessionmaker(bind=g_engine)

64
Server/statistics.py Normal file
View File

@@ -0,0 +1,64 @@
import time
import sql
all_log_num = 0
host_list = {}
last_update_time = 0
def get_host_list():
global host_list
return host_list
def update_host_list(host):
global host_list
host_list[host] = 1
def update_loged_num(host):
global all_log_num
global host_list
global last_update_time
all_log_num += 1
if host not in host_list:
host_list[host] = {
'last_update_time': time.time(),
'log_num': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
'all_log_num': 0
}
host_list[host]['all_log_num'] += 1
if time.time() - host_list[host]['last_update_time'] > 60:
host_list[host]['last_update_time'] = time.time()
host_list[host]['log_num'].append(host_list[host]['all_log_num'])
host_list[host]['all_log_num'] = 0
if len(host_list[host]['log_num']) > 10:
del host_list[host]['log_num'][0]
def get_loged_num():
global all_log_num
if all_log_num > 30000000:
all_log_num = 0
return all_log_num
def get_threat_nums():
# sqlite的count啥的还不如自己查出来自己统计
host_list = get_host_list()
# 懒得做了...
# last_logs = sql.query_last_raw_process_log(10)
# for iter in last_logs:
# print(last_logs)
threat_datas = sql.query_all_threat_log(-1)
return_data = {"all": len(threat_datas), "confirm": 0,
"ingore": 0, "working": 0, "all_log_num": get_loged_num(), "host_list": host_list}
for iter in threat_datas:
if iter[9] == 1:
return_data["confirm"] += 1
elif iter[9] == 2:
return_data["ingore"] += 1
if iter[7] == 0:
return_data["working"] += 1
return return_data

View File

@@ -1 +1 @@
<!DOCTYPE html><html><head><title>Duck Sys Eye</title><meta charset=utf-8><meta name=description content=syseye><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=icons/favicon-16x16.png><link rel=icon type=image/ico href=favicon.ico><script defer src=js/vendor.8b656787.js></script><script defer src=js/app.b7308b45.js></script><link href=css/vendor.5b8581f0.css rel=stylesheet><link href=css/app.31d6cfe0.css rel=stylesheet></head><body><div id=q-app></div></body></html>
<!DOCTYPE html><html><head><title>Duck Sys Eye</title><meta charset=utf-8><meta name=description content=syseye><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=icons/favicon-16x16.png><link rel=icon type=image/ico href=favicon.ico><script defer src=js/vendor.3a0f655d.js></script><script defer src=js/app.1fab7ba3.js></script><link href=css/vendor.5b8581f0.css rel=stylesheet><link href=css/app.31d6cfe0.css rel=stylesheet></head><body><div id=q-app></div></body></html>

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
"use strict";(globalThis["webpackChunksyseye"]=globalThis["webpackChunksyseye"]||[]).push([[219],{4219:(a,e,t)=>{t.r(e),t.d(e,{default:()=>_});var n=t(3673),s=t(2323);function o(a,e,t,o,i,l){const r=(0,n.up)("q-td"),p=(0,n.up)("q-btn"),d=(0,n.up)("q-tr"),h=(0,n.up)("q-table");return(0,n.wg)(),(0,n.j4)(h,{class:"q-pa-lg",dense:a.$q.screen.lt.md,title:"白名单列表",columns:a.data_columns,rows:a.data_columns_data,loading:a.loading,pagination:a.pagination,"onUpdate:pagination":e[0]||(e[0]=e=>a.pagination=e),onRequest:a.onRequest},{body:(0,n.w5)((e=>[(0,n.Wm)(d,{props:e},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{key:"path",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.path),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"hash",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.hash),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"reason",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.reason),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"timestamp",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(a.time_parase(e.row.timestamp)),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"action",props:e},{default:(0,n.w5)((()=>[(0,n.Wm)(p,{color:"red",label:"移除白名单",onClick:t=>a.delete_white_hash(e.row.hash)},null,8,["onClick"])])),_:2},1032,["props"])])),_:2},1032,["props"])])),_:1},8,["dense","columns","rows","loading","pagination","onRequest"])}var i=t(52),l=t.n(i);const r=(0,n.aZ)({name:"WhiteList",data:function(){return{data_columns:[{name:"path",align:"center",label:"路径",field:"path"},{name:"hash",align:"center",label:"hash",field:"hash"},{name:"reason",align:"center",label:"原因",field:"reason"},{name:"timestamp",align:"center",label:"时间",field:"timestamp"},{name:"action",align:"center",label:"操作",field:"steamid"}],data_columns_data:[],loading:!1,pagination:{sortBy:"desc",descending:!1,page:1,rowsPerPage:10,rowsNumber:10}}},mounted(){this.onRequest({pagination:this.pagination,filter:void 0})},methods:{delete_white_hash(a){l().get("/api/v1/del/white_list?hash="+a).then((a=>{this.onRequest({pagination:this.pagination,filter:void 0})}))},time_parase(a){const e=a=>a<10?"0"+a:a,t=new Date(Number(a));console.log("time",a);const n=t.getFullYear(),s=t.getMonth()+1,o=t.getDate(),i=t.getHours(),l=t.getMinutes(),r=t.getSeconds();return n+"-"+e(s)+"-"+e(o)+" "+e(i)+":"+e(l)+":"+e(r)},onRequest(a){this.data_columns_data=[],this.loading=!0;const{page:e}=a.pagination;l().get("/api/v1/query/white_list_all").then((a=>{const t=a.data.result;console.log(t);for(let e=0;e<t.length;e++){const a=t[e];this.data_columns_data.push(a)}this.pagination.page=e,this.pagination.rowsNumber=this.data_columns_data.length,this.pagination.rowsPerPage=this.data_columns_data.length,this.loading=!1}))}}});var p=t(4260),d=t(1779),h=t(8186),g=t(3884),u=t(8240),m=t(7518),c=t.n(m);const w=(0,p.Z)(r,[["render",o]]),_=w;c()(r,"components",{QTable:d.Z,QTr:h.Z,QTd:g.Z,QBtn:u.Z})}}]);
"use strict";(globalThis["webpackChunksyseye"]=globalThis["webpackChunksyseye"]||[]).push([[219],{4219:(a,e,t)=>{t.r(e),t.d(e,{default:()=>_});var n=t(3673),s=t(2323);function o(a,e,t,o,i,l){const r=(0,n.up)("q-td"),p=(0,n.up)("q-btn"),d=(0,n.up)("q-tr"),h=(0,n.up)("q-table");return(0,n.wg)(),(0,n.j4)(h,{class:"q-pa-lg",dense:a.$q.screen.lt.md,title:"白名单列表",columns:a.data_columns,rows:a.data_columns_data,loading:a.loading,pagination:a.pagination,"onUpdate:pagination":e[0]||(e[0]=e=>a.pagination=e),onRequest:a.onRequest},{body:(0,n.w5)((e=>[(0,n.Wm)(d,{props:e},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{key:"path",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.path),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"hash",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.hash),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"reason",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.row.reason),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"timestamp",props:e},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(a.time_parase(e.row.timestamp)),1)])),_:2},1032,["props"]),(0,n.Wm)(r,{key:"action",props:e},{default:(0,n.w5)((()=>[(0,n.Wm)(p,{color:"red",label:"移除白名单",onClick:t=>a.delete_white_hash(e.row.hash)},null,8,["onClick"])])),_:2},1032,["props"])])),_:2},1032,["props"])])),_:1},8,["dense","columns","rows","loading","pagination","onRequest"])}var i=t(52),l=t.n(i);const r=(0,n.aZ)({name:"WhiteList",data:function(){return{data_columns:[{name:"path",align:"center",label:"路径",field:"path"},{name:"hash",align:"center",label:"hash",field:"hash"},{name:"reason",align:"center",label:"原因",field:"reason"},{name:"timestamp",align:"center",label:"时间",field:"timestamp"},{name:"action",align:"center",label:"操作",field:"steamid"}],data_columns_data:[],loading:!1,pagination:{sortBy:"desc",descending:!1,page:1,rowsPerPage:10,rowsNumber:10}}},mounted(){this.onRequest({pagination:this.pagination,filter:void 0})},methods:{delete_white_hash(a){l().get("/api/v1/del/white_list?hash="+a).then((a=>{this.onRequest({pagination:this.pagination,filter:void 0})}))},time_parase(a){const e=a=>a<10?"0"+a:a,t=new Date(Number(a));console.log("time",a);const n=t.getFullYear(),s=t.getMonth()+1,o=t.getDate(),i=t.getHours(),l=t.getMinutes(),r=t.getSeconds();return n+"-"+e(s)+"-"+e(o)+" "+e(i)+":"+e(l)+":"+e(r)},onRequest(a){this.data_columns_data=[],this.loading=!0;const{page:e}=a.pagination;l().get("/api/v1/query/white_list_all").then((a=>{const t=a.data.result;console.log(t);for(let e=0;e<t.length;e++){const a=t[e];this.data_columns_data.push(a)}this.pagination.page=e,this.pagination.rowsNumber=this.data_columns_data.length,this.pagination.rowsPerPage=this.data_columns_data.length,this.loading=!1}))}}});var p=t(4260),d=t(4147),h=t(8186),g=t(3884),u=t(8240),m=t(7518),c=t.n(m);const w=(0,p.Z)(r,[["render",o]]),_=w;c()(r,"components",{QTable:d.Z,QTr:h.Z,QTd:g.Z,QBtn:u.Z})}}]);

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
"use strict";(globalThis["webpackChunksyseye"]=globalThis["webpackChunksyseye"]||[]).push([[620],{620:(t,e,a)=>{a.r(e),a.d(e,{default:()=>Z});var s=a(3673),i=a(2323);const o={class:"q-gutter-md q-mb-sm q-pa-lg"},l={class:"row q-col-gutter-sm"},n={class:"text-h6"},r=(0,s.Uk)(" 由于python+sqlite数据库作为后端,理论上最高支持的主机数量为50. "),c={class:"text-subtitle2"},h={ref:"main_draw",style:{width:"100%",height:"600px"}};function m(t,e,a,m,u,d){const p=(0,s.up)("q-icon"),w=(0,s.up)("q-item-section"),g=(0,s.up)("q-item-label"),_=(0,s.up)("q-item"),b=(0,s.up)("q-card-section"),f=(0,s.up)("q-card"),y=(0,s.up)("q-banner"),v=(0,s.up)("q-popup-proxy");return(0,s.wg)(),(0,s.iD)("div",o,[(0,s._)("div",null,[(0,s.Wm)(f,{class:"bg-transparent no-shadow no-border"},{default:(0,s.w5)((()=>[(0,s.Wm)(b,{class:"q-pa-none"},{default:(0,s.w5)((()=>[(0,s._)("div",l,[((0,s.wg)(!0),(0,s.iD)(s.HY,null,(0,s.Ko)(t.Threatitems,((t,e)=>((0,s.wg)(),(0,s.iD)("div",{key:e,class:"col-md-3 col-sm-12 col-xs-12"},[(0,s.Wm)(_,{style:(0,i.j5)(`background-color: ${t.color1}`),class:"q-pa-none"},{default:(0,s.w5)((()=>[(0,s.Wm)(w,{side:"",style:(0,i.j5)(`background-color: ${t.color2}`),class:"q-pa-lg q-mr-none text-white"},{default:(0,s.w5)((()=>[(0,s.Wm)(p,{name:t.icon,color:"white",size:"24px"},null,8,["name"])])),_:2},1032,["style"]),(0,s.Wm)(w,{class:"q-pa-md q-ml-none text-white"},{default:(0,s.w5)((()=>[(0,s.Wm)(g,{class:"text-white text-h6 text-weight-bolder"},{default:(0,s.w5)((()=>[(0,s.Uk)((0,i.zw)(t.value),1)])),_:2},1024),(0,s.Wm)(g,null,{default:(0,s.w5)((()=>[(0,s.Uk)((0,i.zw)(t.title),1)])),_:2},1024)])),_:2},1024)])),_:2},1032,["style"])])))),128))])])),_:1})])),_:1})]),(0,s.Wm)(f,{class:"no-shadow",style:{background:"rbg(255,255,255)"}},{default:(0,s.w5)((()=>[(0,s.Wm)(b,null,{default:(0,s.w5)((()=>[(0,s._)("div",n,[(0,s.Uk)(" 主机数量: "+(0,i.zw)(t.threatStatistics.host_num)+"/50 ",1),(0,s.Wm)(p,{name:"info",class:"text-brown cursor-pointer"},{default:(0,s.w5)((()=>[(0,s.Wm)(v,{"transition-show":"flip-up","transition-hide":"flip-down"},{default:(0,s.w5)((()=>[(0,s.Wm)(y,{class:"bg-brown text-white"},{avatar:(0,s.w5)((()=>[(0,s.Wm)(p,{name:"lightbulb"})])),default:(0,s.w5)((()=>[r])),_:1})])),_:1})])),_:1})]),(0,s._)("div",c,"最近日志数量: "+(0,i.zw)(t.threatStatistics.all_log_num),1)])),_:1}),(0,s.Wm)(b,{class:"q-pt-none"},{default:(0,s.w5)((()=>[(0,s._)("div",h," 1 ",512)])),_:1})])),_:1})])}var u=a(52),d=a.n(u),p=a(2256);const w=(0,s.aZ)({name:"Dashboard",data(){return{Threatitems:[{title:"发现的威胁",icon:"remove_red_eye",value:"200",color1:"#5064b5",color2:"#3e51b5"},{title:"确认的威胁",icon:"flash_on",value:"500",color1:"#f37169",color2:"#f34636"},{title:"忽略的威胁",icon:"texture",value:"50",color1:"#ea6a7f",color2:"#ea4b64"},{title:"进行中的威胁",icon:"bar_chart",value:"1020",color1:"#a270b1",color2:"#9f52b1"}],threatStatistics:{all:1,confirm:0,ingore:1,working:0,host_list:{},host_num:10,all_log_num:647}}},methods:{get_threatStatistics(){d().get("/api/v1/get/threat_statistics",{"Content-Type":"application/json"}).then((t=>{const e=t.data;e.data&&(this.threatStatistics=e.data,this.threatStatistics.host_num=Object.keys(this.threatStatistics.host_list).length,this.Threatitems[0].value=this.threatStatistics.all,this.Threatitems[1].value=this.threatStatistics.confirm,this.Threatitems[2].value=this.threatStatistics.ingore,this.Threatitems[3].value=this.threatStatistics.working,console.log(this.threatStatistics),this.draw())}))},draw(){const t=[],e=[];for(const o in this.threatStatistics.host_list)t.push(o),e.push({name:o,type:"line",stack:"Total",areaStyle:{},emphasis:{focus:"series"},data:this.threatStatistics.host_list[o].log_num});const a=this.$refs.main_draw,s=p.S1(a),i={title:{text:"最近十分钟日志量"},tooltip:{trigger:"axis",axisPointer:{type:"cross",label:{backgroundColor:"#6a7985"}}},legend:{data:t},toolbox:{feature:{saveAsImage:{}}},grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0},xAxis:[{type:"category",boundaryGap:!1,data:["10min","9min","8min","7min","6min","5min","4min","3min","2min","1min"]}],yAxis:[{type:"value"}],series:e};s.setOption(i),setTimeout((()=>{s.resize()}),1e3)}},mounted(){this.get_threatStatistics()}});var g=a(4260),_=a(151),b=a(5589),f=a(3414),y=a(2035),v=a(4554),x=a(2350),q=a(3944),S=a(5607),k=a(7518),W=a.n(k);const T=(0,g.Z)(w,[["render",m]]),Z=T;W()(w,"components",{QCard:_.Z,QCardSection:b.Z,QItem:f.Z,QItemSection:y.Z,QIcon:v.Z,QItemLabel:x.Z,QPopupProxy:q.Z,QBanner:S.Z})}}]);

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
"use strict";(globalThis["webpackChunksyseye"]=globalThis["webpackChunksyseye"]||[]).push([[904],{6904:(s,a,e)=>{e.r(a),e.d(a,{default:()=>h});var r=e(3673);const n={class:"row q-gutter-md q-mb-sm q-pa-lg"};function t(s,a,e,t,c,o){return(0,r.wg)(),(0,r.iD)("h4",n,"施工中....")}const c=(0,r.aZ)({name:"Dashboard"});var o=e(4260);const u=(0,o.Z)(c,[["render",t]]),h=u}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -10,7 +10,7 @@ from flask import Flask, render_template, request
import plugin
import logging
import html
import statistics
app = Flask(
__name__,
template_folder="./templates",
@@ -53,18 +53,7 @@ def plugin_menu():
def threat_statistics():
if request.remote_addr not in config.ALLOW_ACCESS_IP:
return "Access Denied"
# sqlite的count啥的还不如自己查出来自己统计
threat_datas = sql.query_all_threat_log(-1)
return_data = {"all": len(threat_datas), "confirm": 0,
"ingore": 0, "working": 0}
for iter in threat_datas:
if iter[9] == 1:
return_data["confirm"] += 1
elif iter[9] == 2:
return_data["ingore"] += 1
if iter[7] == 0:
return_data["working"] += 1
return {"data": return_data}
return {"data": statistics.get_threat_nums()}
@app.route("/api/v1/query/white_list_all", methods=["GET"])
@@ -196,11 +185,12 @@ def process():
# 转小写
host = request.remote_addr
log.process_log(host, json.loads(body_data.lower()), body_data)
statistics.update_loged_num(host)
return {"status": "success"}
@app.route("/api/v1/log_hunt", methods=["POST"])
@ app.route("/api/v1/log_hunt", methods=["POST"])
def log_rescan():
if request.remote_addr not in config.ALLOW_ACCESS_IP:
return "Access Denied"
@@ -223,4 +213,5 @@ if __name__ == "__main__":
flask_log.setLevel(logging.ERROR)
print("注意,你正在使用测试版,请随时关注github以获取最新版本:")
print("https://github.com/RoomaSec/RmEye")
# statistics.get_threat_nums()
app.run(debug=True, host="0.0.0.0")

View File

@@ -123,7 +123,7 @@ export default defineComponent({
},
data: function () {
return {
selectLabel: 'non_hanlde_report',
selectLabel: 'dashboard',
drawer: false,
miniState: true,
plugin: [],

View File

@@ -1,10 +1,189 @@
<template>
<h4 class="row q-gutter-md q-mb-sm q-pa-lg">施工中....</h4>
</template>
<script>
import { defineComponent } from 'vue'
<div class="q-gutter-md q-mb-sm q-pa-lg">
<div>
<q-card class="bg-transparent no-shadow no-border">
<q-card-section class="q-pa-none">
<div class="row q-col-gutter-sm">
<div v-for="(item, index) in Threatitems" :key="index" class="col-md-3 col-sm-12 col-xs-12">
<q-item :style="`background-color: ${item.color1}`" class="q-pa-none">
<q-item-section side :style="`background-color: ${item.color2}`" class="q-pa-lg q-mr-none text-white">
<q-icon :name="item.icon" color="white" size="24px"></q-icon>
</q-item-section>
<q-item-section class="q-pa-md q-ml-none text-white">
<q-item-label class="text-white text-h6 text-weight-bolder">{{
item.value
}}</q-item-label>
<q-item-label>{{ item.title }}</q-item-label>
</q-item-section>
</q-item>
</div>
</div>
</q-card-section>
</q-card>
</div>
<q-card class="no-shadow" style="background: rbg(255,255,255)">
<q-card-section>
<div class="text-h6">
主机数量: {{threatStatistics.host_num}}/50 <q-icon name="info" class="text-brown cursor-pointer">
<q-popup-proxy transition-show="flip-up" transition-hide="flip-down">
<q-banner class="bg-brown text-white">
<template v-slot:avatar>
<q-icon name="lightbulb" />
</template>
由于python+sqlite数据库作为后端,理论上最高支持的主机数量为50.
</q-banner>
</q-popup-proxy>
</q-icon>
</div>
<div class="text-subtitle2">最近日志数量: {{threatStatistics.all_log_num}}</div>
</q-card-section>
<q-card-section class="q-pt-none">
<div ref="main_draw" style="width: 100%; height: 600px; ">
1
</div>
</q-card-section>
</q-card>
</div>
</template>
<script>
import {
defineComponent
} from 'vue'
import axios from 'axios'
import * as echarts from 'echarts'
export default defineComponent({
name: 'Dashboard'
name: 'Dashboard',
data () {
return {
Threatitems: [{
title: '发现的威胁',
icon: 'remove_red_eye',
value: '200',
color1: '#5064b5',
color2: '#3e51b5'
},
{
title: '确认的威胁',
icon: 'flash_on',
value: '500',
color1: '#f37169',
color2: '#f34636'
},
{
title: '忽略的威胁',
icon: 'texture',
value: '50',
color1: '#ea6a7f',
color2: '#ea4b64'
},
{
title: '进行中的威胁',
icon: 'bar_chart',
value: '1020',
color1: '#a270b1',
color2: '#9f52b1'
}
],
threatStatistics: {
all: 1,
confirm: 0,
ingore: 1,
working: 0,
host_list: {},
host_num: 10,
all_log_num: 647
}
}
},
methods: {
get_threatStatistics () {
axios
.get('/api/v1/get/threat_statistics', {
'Content-Type': 'application/json'
})
.then((response) => {
const data = response.data
if (data.data) {
this.threatStatistics = data.data
this.threatStatistics.host_num = Object.keys(this.threatStatistics.host_list).length
// Threatitems
this.Threatitems[0].value = this.threatStatistics.all
this.Threatitems[1].value = this.threatStatistics.confirm
this.Threatitems[2].value = this.threatStatistics.ingore
this.Threatitems[3].value = this.threatStatistics.working
console.log(this.threatStatistics)
this.draw()
}
})
},
draw () {
const hostList = []
const hostLoggedNumList = []
for (const key in this.threatStatistics.host_list) {
hostList.push(key)
hostLoggedNumList.push({
name: key,
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: this.threatStatistics.host_list[key].log_num
})
}
const dom = this.$refs.main_draw
const myChart = echarts.init(dom)
const option = {
title: {
text: '最近十分钟日志量'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: hostList
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
data: ['10min', '9min', '8min', '7min', '6min', '5min', '4min', '3min', '2min', '1min']
}],
yAxis: [{
type: 'value'
}],
series: hostLoggedNumList
}
myChart.setOption(option)
setTimeout(() => {
myChart.resize()
}, 1000)
}
},
mounted () {
this.get_threatStatistics()
}
})
</script>

View File

@@ -1,26 +1,5 @@
<template>
<div>
<div class="q-gutter-md q-mb-sm q-pa-lg">
<q-card class="bg-transparent no-shadow no-border">
<q-card-section class="q-pa-none">
<div class="row q-col-gutter-sm">
<div v-for="(item, index) in Threatitems" :key="index" class="col-md-3 col-sm-12 col-xs-12">
<q-item :style="`background-color: ${item.color1}`" class="q-pa-none">
<q-item-section side :style="`background-color: ${item.color2}`" class="q-pa-lg q-mr-none text-white">
<q-icon :name="item.icon" color="white" size="24px"></q-icon>
</q-item-section>
<q-item-section class="q-pa-md q-ml-none text-white">
<q-item-label class="text-white text-h6 text-weight-bolder">{{
item.value
}}</q-item-label>
<q-item-label>{{ item.title }}</q-item-label>
</q-item-section>
</q-item>
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="row">
<div class="col"></div>
<div class="col">
@@ -133,7 +112,7 @@
</div>
<q-drawer show-if-above v-if="processChainShowDetails" v-model="processChainShowDetails" side="right" bordered width="350" class="text-dark">
<q-list style="width: 100%;word-break: break-all;">
<q-item>
<q-item>
<q-item-section>活跃状态: {{processChainDetails.active ? "运行中" : "已结束"}}</q-item-section>
</q-item>
<q-separator />
@@ -161,13 +140,13 @@
<q-item-section>进程hash: {{processChainDetails.md5}}</q-item-section>
</q-item>
<q-separator />
<q-item>
<q-item>
<q-item-section>是否在白名单中: {{processChainDetails.isWhite ? "是" : "否"}}</q-item-section>
</q-item>
<q-separator />
<q-item>
<q-item-section>进程命中的规则:
<template v-for="(index, operation) in processChainDetails.hitRules" :key="index">
<template v-for="(index, operation) in processChainDetails.hitRules" :key="index">
<q-chip square color="rgb(239,243,246)">
{{ operation }}&nbsp;({{ index }})
</q-chip>
@@ -181,7 +160,7 @@
</q-item>
<q-item>
<q-item-section>attck矩阵:
<template v-for="(index, operation) in processChainDetails.hitAttck" :key="index">
<template v-for="(index, operation) in processChainDetails.hitAttck" :key="index">
<q-chip square color="rgb(239,243,246)">
{{ operation }}&nbsp;({{ index }})
</q-chip>
@@ -251,41 +230,6 @@ export default defineComponent({
width: '9px',
opacity: 0.2
},
threatStatistics: {
all: 1,
confirm: 0,
ingore: 1,
working: 0
},
Threatitems: [{
title: '发现的威胁',
icon: 'remove_red_eye',
value: '200',
color1: '#5064b5',
color2: '#3e51b5'
},
{
title: '确认的威胁',
icon: 'flash_on',
value: '500',
color1: '#f37169',
color2: '#f34636'
},
{
title: '忽略的威胁',
icon: 'texture',
value: '50',
color1: '#ea6a7f',
color2: '#ea4b64'
},
{
title: '进行中的威胁',
icon: 'bar_chart',
value: '1020',
color1: '#a270b1',
color2: '#9f52b1'
}
],
dialog: false,
maximizedToggle: true,
server_threat: {},
@@ -453,23 +397,7 @@ export default defineComponent({
}
})
},
get_threatStatistics () {
axios
.get('/api/v1/get/threat_statistics', {
'Content-Type': 'application/json'
})
.then((response) => {
const data = response.data
if (data.data) {
this.threatStatistics = data.data
// Threatitems
this.Threatitems[0].value = this.threatStatistics.all
this.Threatitems[1].value = this.threatStatistics.confirm
this.Threatitems[2].value = this.threatStatistics.ingore
this.Threatitems[3].value = this.threatStatistics.working
}
})
},
get_clientids () {
const queryType = this.$route.params.queryIndex
const queryIndex = (queryType === null || queryType === undefined) ? 0 : queryType
@@ -484,7 +412,6 @@ export default defineComponent({
data: []
}
this.server_threat.data = data.data
this.get_threatStatistics()
}
})
}

View File

@@ -25,6 +25,9 @@ https://key08.com/index.php/2022/08/09/1505.html
请牢记,RmEye自身定位是轻量级威胁检出工具
### 最新新闻
2022/9/22:
增加仪表盘,可视化展示检测结果
2022/9/21:
修复了秋季更新的几个bug,增加了`networkconnect``FileCreateTimeChange`的ds,增加了`brc4`的检测
@@ -49,6 +52,8 @@ https://github.com/RoomaSec/RmEye/blob/main/doc_day0_rule.md
### 检出截图
威胁列表(2022/9/20更新):
![image](Image/1.png)
仪表盘(2022/9/22更新):
![image](Image/dashboard.png)
进程链行为回溯
![image](Image/8.png)
powershell恶意执行: