diff --git a/src/assets/css/components/views/detections/detection-overview.scss b/src/assets/css/components/views/detections/detection-overview.scss index 65c57ce5..4960ee9c 100644 --- a/src/assets/css/components/views/detections/detection-overview.scss +++ b/src/assets/css/components/views/detections/detection-overview.scss @@ -60,12 +60,13 @@ font-weight: 400; } - .row__content { + .row__content, .row__content1 { display: flex; //color: #3976CB; color: #046ECA; font-weight: 500; font-size: 14px; + align-items: center; &.row__content--link { font-style: italic; @@ -87,6 +88,17 @@ font-style: italic; color: #1890FF; } + + .row__content__icon { + font-size: 14px; + margin-right: 5px; + color: #1890FF; + } + + .row__content__svg { + font-size: 14px; + margin-right: 7px; + } } } } @@ -215,13 +227,20 @@ } } } -.row__tag { +.row__tag, .row__tag__level { display: flex; justify-content: center; align-items: center; padding: 0 4px; //color: white; } +.row__tag__level { + height: 16px; + font-size: 12px; + font-weight: 400; + color: #fff; + border-radius: 2px; +} .performance-event-remark { font-family: NotoSansSChineseRegular; diff --git a/src/components/advancedSearch/meta/parser.js b/src/components/advancedSearch/meta/parser.js index ff7839b4..11c5098e 100644 --- a/src/components/advancedSearch/meta/parser.js +++ b/src/components/advancedSearch/meta/parser.js @@ -1234,7 +1234,8 @@ export default class Parser { // 不区分大小写,用this.columnList里的label arr.forEach(item => { if (str.toLowerCase().indexOf(item.toLowerCase()) > -1) { - str = str.replace(new RegExp(item, 'gi'), item) + // todo 记录一下此处取消了转小写转换,后续搜索验证 + // str = str.replace(new RegExp(item, 'gi'), item) if (!operatorList.some(ite => str.includes(ite)) && str.toLowerCase() !== item.toLowerCase()) { str = this.checkFormatByStr(str) } diff --git a/src/mock/detectionList.js b/src/mock/detectionList.js new file mode 100644 index 00000000..059a8338 --- /dev/null +++ b/src/mock/detectionList.js @@ -0,0 +1,353 @@ +import Mock from 'mockjs' + +const urlAndVersion = BASE_CONFIG.baseUrl + BASE_CONFIG.apiVersion +const openMock = true +if (openMock) { + Mock.mock(new RegExp(urlAndVersion + '/detection/security/list.*'), 'get', function (requestObj) { + const result = [] + for (let i = 0; i < 20; i++) { + const obj = { + eventId: 1212, + eventType: 'Anonymity', + eventName: 'Tor', + eventKey: '2,1.1.1,12.2.2.2', + ruleId: 2, + ruleType: 'indicator_match', + isBuiltin: 1, + severity: 'critical', + offenderIp: '1.1.1.1', + victimIp: '2.2.2.2', + domain: '*.vioee.com', + app: 'vio', + startTime: 1697092617, + endTime: 1697092777, + durationS: 30000, + matchTimes: 1, + status: 1, + eventInfo: "{\'knowledge_id\': 123, \'name\': \'example_ioc_malware\', \'ioc_type\': \'domain\', \'ioc_value\': \'iocentity.com\'}", + eventInfoObj: { + knowledge_id: 123, + name: 'example_ioc_malware', + ioc_type: 'domain', + ioc_value: 'iocentity.com' + } + } + if (i % 2 === 0) { + obj.status = 0 + } + result.push(obj) + } + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/severity/timedistribution.*'), 'get', function (requestObj) { + const result = [ + { + statTime: 1697523900, + severity: 'critical', + count: 25 + }, + { + statTime: 1697524200, + severity: 'high', + count: 31 + }, + { + statTime: 1697524500, + severity: 'info', + count: 21 + }, + { + statTime: 1697524800, + severity: 'low', + count: 25 + }, + { + statTime: 1697525100, + severity: 'medium', + count: 32 + }, + { + statTime: 1697525400, + severity: 'critical', + count: 22 + }, + { + statTime: 1697525700, + severity: 'critical', + count: 23 + }, + { + statTime: 1697526000, + severity: 'critical', + count: 25 + }, + { + statTime: 1697526300, + severity: 'critical', + count: 21 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/severity/statistics.*'), 'get', function (requestObj) { + const result = [ + { + severity: 'critical', + count: 25 + }, + { + severity: 'high', + count: 31 + }, + { + severity: 'info', + count: 21 + }, + { + severity: 'low', + count: 25 + }, + { + severity: 'medium', + count: 32 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/event-type/statistics.*'), 'get', function (requestObj) { + const result = [ + { + eventType: 'Anonymity', + count: 25 + }, + { + eventType: 'Command and Control', + count: 31 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/offender-ip/statistics.*'), 'get', function (requestObj) { + const result = [ + { + offenderIp: '221.7.1.20', + count: 25 + }, + { + offenderIp: '58.247.118.253', + count: 31 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/victim-ip/statistics.*'), 'get', function (requestObj) { + const result = [ + { + victimIp: '21.77.1.201', + count: 25 + }, + { + victimIp: '58.47.118.153', + count: 31 + }, + { + victimIp: '22.47.223.57', + count: 43 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/status/statistics.*'), 'get', function (requestObj) { + const result = [ + { + status: 1, + count: 25 + }, + { + status: 0, + count: 31 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/ip/relation/event.*'), 'get', function (requestObj) { + const result = [ + { + eventId: 10010, + severity: 'high', + eventType: 'Command and Control', + offenderIp: '1.1.1.1', + victimIp: '2.2.2.2', + startTime: 1697092617 + } + ] + + const data = { + resultType: 'table', + result: result + } + + return { + msg: 'OK', + code: 200, + data: data + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/count.*'), 'get', function (requestObj) { + return { + msg: 'OK', + code: 200, + data: { + resultType: 'single', + result: 123 + } + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/ip.*'), 'get', function (requestObj) { + return { + msg: 'OK', + code: 200, + data: { + asn: { + id: 2, + asn: '14061', + organization: 'DIGITALOCEAN-ASN - DigitalOcean, LLC, US' + }, + malware: { + threatType: 'command and control', + malwareName: 'IcedID', + malwareAlias: 'BokBot,IceID', + mitreAttackDescription: '[IcedID](https://attack.mitre.org/software/S0483) is a modular banking malware designed to steal financial information that has been observed in the wild since at least 2017. [IcedID](https://attack.mitre.org/software/S0483) has been downloaded by [Emotet](https://attack.mitre.org/software/S0367) in multiple campaigns.(Citation: IBM IcedID November 2017)(Citation: Juniper IcedID June 2020)', + mitreAttackPlatforms: 'Windows', + mitreAttackTechniques: '[""Asymmetric Cryptography(T1573.002)"",""Asynchronous Procedure Call(T1055.004)"",""Browser Session Hijacking(T1185)"",""Domain Account(T1087.002)"",""Ingress Tool Transfer(T1105)"",""Malicious File(T1204.002)"",""Msiexec(T1218.007)"",""Native API(T1106)"",""Obfuscated Files or Information(T1027)"",""Permission Groups Discovery(T1069)"",""Registry Run Keys / Startup Folder(T1547.001)"",""Scheduled Task(T1053.005)"",""Software Packing(T1027.002)"",""Spearphishing Attachment(T1566.001)"",""Steganography(T1027.003)"",""System Information Discovery(T1082)"",""Visual Basic(T1059.005)"",""Web Protocols(T1071.001)"",""Windows Management Instrumentation(T1047)""]', + mitreAttackGroups: '[""TA551(G0127)""]', + confidenceLevel: 'high', + reference: '' + }, + location: { + continent: 'North America', + country: 'United States', + province: 'New York', + city: '', + lngwgs: '-74.006', + latwgs: '40.713', + isp: 'dba Omsoft', + owner: 'tie net' + } + } + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/domain.*'), 'get', function (requestObj) { + return { + msg: 'OK', + code: 200, + data: { + malware: { + threatType: 'command and control', + malwareName: 'IcedID', + malwareAlias: 'BokBot,IceID', + mitreAttackDescription: '[IcedID](https://attack.mitre.org/software/S0483) is a modular banking malware designed to steal financial information that has been observed in the wild since at least 2017. [IcedID](https://attack.mitre.org/software/S0483) has been downloaded by [Emotet](https://attack.mitre.org/software/S0367) in multiple campaigns.(Citation: IBM IcedID November 2017)(Citation: Juniper IcedID June 2020)', + mitreAttackPlatforms: 'Windows', + mitreAttackTechniques: '[""Asymmetric Cryptography(T1573.002)"",""Asynchronous Procedure Call(T1055.004)"",""Browser Session Hijacking(T1185)"",""Domain Account(T1087.002)"",""Ingress Tool Transfer(T1105)"",""Malicious File(T1204.002)"",""Msiexec(T1218.007)"",""Native API(T1106)"",""Obfuscated Files or Information(T1027)"",""Permission Groups Discovery(T1069)"",""Registry Run Keys / Startup Folder(T1547.001)"",""Scheduled Task(T1053.005)"",""Software Packing(T1027.002)"",""Spearphishing Attachment(T1566.001)"",""Steganography(T1027.003)"",""System Information Discovery(T1082)"",""Visual Basic(T1059.005)"",""Web Protocols(T1071.001)"",""Windows Management Instrumentation(T1047)""]', + mitreAttackGroups: '[""TA551(G0127)""]', + confidenceLevel: 'high', + reference: '' + }, + category: { + categoryName: '门户网站', + categoryGroup: '互联网', + reputationLevel: 'high' + } + } + } + }) + Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/app.*'), 'get', function (requestObj) { + return { + msg: 'OK', + code: 200, + data: { + category: { + appName: 'QQ', + appId: 333, + appCategory: '娱乐', + appSubcategory: '聊天', + appRisk: 'low', + appDescription: '聊天社交软件', + appLongname: 'Tencent qq', + appTechnology: 'socket', + appCompany: 'tencent', + appCompanyCategory: '互联网' + } + } + } + }) +} diff --git a/src/mock/index.js b/src/mock/index.js index f1d89666..77ff478b 100644 --- a/src/mock/index.js +++ b/src/mock/index.js @@ -3,3 +3,4 @@ import './linkMonitor' import './dns' import './entity' import './detection' +import './detectionList' diff --git a/src/utils/api.js b/src/utils/api.js index 5f536f17..3a6072b1 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -123,7 +123,20 @@ export const api = { listBasic: '/interface/detection/security/list/basic', listCount: '/interface/detection/security/list/count', overviewBasic: '/interface/detection/security/detail/overview/basic', - overviewEvent: '/interface/detection/security/detail/overview/event' + overviewEvent: '/interface/detection/security/detail/overview/event', + securityList: apiVersion + '/detection/security/list', // 安全事件列表 + timeDistribution: apiVersion + '/detection/security/severity/timedistribution', // 事件严重等级分布(顶部柱状图) + severityStatistics: apiVersion + '/detection/security/severity/statistics', // 事件严重等级统计(左侧filter事件严重等级和饼图) + statusStatistics: apiVersion + '/detection/security/status/statistics', // 事件状态统计 + eventTypeStatistics: apiVersion + '/detection/security/event-type/statistics', // 事件类型统计 + offenderIpStatistics: apiVersion + '/detection/security/offender-ip/statistics', // 攻击者IP统计 + victimIpStatistics: apiVersion + '/detection/security/victim-ip/statistics', // 受害者IP统计 + relationEvent: apiVersion + '/detection/security/ip/relation/event', // IP相关近期事件 + securityCount: apiVersion + '/detection/security/count', // 安全事件总数 + detail: apiVersion + '/detection/security/entity/detail', // 安全事件实体详情,后面得加上实体类型 + ipDetail: apiVersion + '/detection/security/entity/detail/ip', // 安全事件实体详情ip响应 + domainDetail: apiVersion + '/detection/security/entity/detail/domain', // 安全事件实体详情domain响应 + appDetail: apiVersion + '/detection/security/entity/detail/app' // 安全事件实体详情app响应 }, performanceEvent: { eventSeverityTrend: '/interface/detection/performance/filter/severityTrend', diff --git a/src/utils/static-data.js b/src/utils/static-data.js index db857223..9f85083a 100644 --- a/src/utils/static-data.js +++ b/src/utils/static-data.js @@ -334,11 +334,91 @@ export const columnList1 = [ } } ] +const securityEvent = [ + { + name: 'event_type', + type: 'string', + label: 'event_type', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'event_name', + type: 'string', + label: 'event_name', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'severity', + type: 'string', + label: 'severity', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'offender_ip', + type: 'string', + label: 'offender Ip', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'victim_ip', + type: 'string', + label: 'victim Ip', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'domain', + type: 'string', + label: 'domain', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + }, + { + name: 'app', + type: 'string', + label: 'app', + doc: { + constraints: { + operator_functions: '=,in,like' + } + } + } +] -let schemaEntityExplore = localStorage.getItem(storageKey.schemaEntityExplore) -schemaEntityExplore = schemaEntityExplore ? JSON.parse(schemaEntityExplore).entityMetadata.searchColumns : columnList1 +const schema = localStorage.getItem(storageKey.schemaEntityExplore) +const schemaEntityExplore = schema ? JSON.parse(schema).entityMetadata.searchColumns : columnList1 export const columnList = schemaEntityExplore +let securityEventMetadata = securityEvent +if (schema) { + if (JSON.parse(schema).securityEventMetadata) { + securityEventMetadata = JSON.parse(schema).securityEventMetadata.searchColumns + } +} +export const schemaDetectionSecurity = securityEventMetadata + export const operatorList = ['=', '!=', /* '>', '<', '>=', '<=', */'IN', 'NOT IN', 'LIKE', 'NOT LIKE'] export const connectionList = [ { diff --git a/src/views/detections/DetectionList.vue b/src/views/detections/DetectionList.vue index 342a88bc..69591dc7 100644 --- a/src/views/detections/DetectionList.vue +++ b/src/views/detections/DetectionList.vue @@ -3,12 +3,12 @@
-
{{ $t('npm.noData') }}
+
{{ $t('npm.noData') }}
import DetectionRow from '@/views/detections/DetectionRow' import Loading from '@/components/common/Loading' +import axios from 'axios' +import { api } from '@/utils/api' export default { name: 'DetectionList', components: { @@ -49,7 +51,8 @@ export default { collapseIndex: 0, tableId: 'detectionList', listDataCopy: [], - noData: false + noData: true, + myListData: [] // listData的克隆,避免因为修改listData里的malWareName而触发watch监听 } }, mounted () { @@ -60,6 +63,23 @@ export default { window.removeEventListener('mousewheel', this.handleScroll) }, methods: { + initData () { + this.myListData = [] + this.listData.forEach((item, i) => { + this.myListData.push(this.$_.cloneDeep(item)) + if (item.eventInfoObj) { + axios.get(`${api.detection.securityEvent.detail}/${item.eventInfoObj.ioc_type}/resource=${item.eventInfoObj.ioc_value}`).then(res => { + if (res.status === 200) { + this.myListData[i].malwareName = res.data.data.malware.malwareName + } else { + this.myListData[i].malwareName = '-' + } + }).catch(e => { + this.myListData[i].malwareName = '-' + }) + } + }) + }, switchCollapse (isCollapse, index) { this.isCollapse = isCollapse this.collapseIndex = index @@ -84,6 +104,7 @@ export default { }, watch: { listData: { + immediate: true, deep: true, handler (n) { if (!n || n.length === 0) { @@ -93,6 +114,7 @@ export default { } else { clearTimeout(this.timeout) this.noData = false + this.initData() } } } diff --git a/src/views/detections/DetectionRow.vue b/src/views/detections/DetectionRow.vue index a2c2c74e..3494699a 100644 --- a/src/views/detections/DetectionRow.vue +++ b/src/views/detections/DetectionRow.vue @@ -9,14 +9,15 @@
-
+
- {{ detection.securityType || '-' }} + + {{ detection.eventType || '-' }} {{detection.offenderIp || '-'}}
{{detection.domain}}
------- @@ -30,31 +31,31 @@
-
+
{{$t('detection.list.security')}} :   - {{detection.eventSecurity || '-'}} + {{detection.severity || '-'}}
{{$t('detections.severity')}} :   {{detection.eventSeverity || '-'}}
-
- - {{$t('detections.eventType')}} :   - {{detection.eventType || '-'}} -
-
+ + + + + +
{{$t('detection.list.malwareName')}} :   - {{detection.malwareName || '-'}} -
-
- - {{$t('detection.list.cryptominingPool')}} :   - {{detection.cryptominingPool || '-'}} + {{ $_.get(detection, 'malwareName', '-') || '-' }}
+ + + + +
{{$t('detection.list.startTime')}} :   @@ -63,9 +64,11 @@
{{$t('overall.duration')}} :   - - {{unitConvert(detection.durationMs, 'time', null, null, 0).join(' ') || '-'}} + + {{ detection.matchTimes || '-'}} {{ $t('detection.list.times') }} / + {{unitConvert(detection.durationS, 'time', 's', null, 0).join(' ') || '-'}} + +
Active
@@ -108,7 +111,7 @@ + + diff --git a/src/views/detections/DetectionSearch.vue b/src/views/detections/DetectionSearch.vue index cf1e010b..d3d184db 100644 --- a/src/views/detections/DetectionSearch.vue +++ b/src/views/detections/DetectionSearch.vue @@ -5,16 +5,16 @@
-
- -
+ + +
@@ -22,6 +22,7 @@ + +