Skip to content

Commit

Permalink
Improvements to the threat intel view (#3289)
Browse files Browse the repository at this point in the history
* Tag colors in intelligence view

* Human readable IOC types

* remove debug log

* Formatting

* Fix lint?

* Attempt to bump node versions in actions
  • Loading branch information
tomchop authored Feb 11, 2025
1 parent b17313e commit 8dcccd5
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
python-version: ['3.9', '3.10']
python-version: ["3.9", "3.10"]

steps:
- uses: actions/checkout@v2
Expand Down
27 changes: 21 additions & 6 deletions data/intelligence_tag_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,36 @@

malware:
weight: 100
class: 'danger'
type: 'danger'

bad:
weight: 90
type: 'danger'

suspicious:
weight: 50
class: 'warning'
type: 'warning'

good:
weight: 10
type: 'legit'

legit:
weight: 10
class: 'success'
type: 'legit'

default:
weight: 0
class: 'info'
type: 'default'

export:
weight: 100
type: 'info'

regexes:
'^GROUPNAME':
weight: 100
class: 'danger'
weight: 100
type: 'danger'
'^inv_':
weight: 80
type: 'warning'
12 changes: 6 additions & 6 deletions timesketch/frontend-ng/src/utils/ThreatIntelMetadata.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
const IOCTypes = [
{ regex: /^(\/[\S]+)+$/i, type: 'fs_path' },
{ regex: /^([-\w]+\.)+[a-z]{2,}$/i, type: 'hostname' },
{ regex: /^(\/[\S]+)+$/i, type: 'fs_path', humanReadable: 'Filesystem path' },
{ regex: /^([-\w]+\.)+[a-z]{2,}$/i, type: 'hostname', humanReadable: 'Hostname' },
{
regex: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g,
type: 'ipv4',
},
{ regex: /^[0-9a-f]{64}$/i, type: 'hash_sha256' },
{ regex: /^[0-9a-f]{40}$/i, type: 'hash_sha1' },
{ regex: /^[0-9a-f]{32}$/i, type: 'hash_md5' },
{ regex: /^[0-9a-f]{64}$/i, type: 'hash_sha256', humanReadable: 'SHA256' },
{ regex: /^[0-9a-f]{40}$/i, type: 'hash_sha1', humanReadable: 'SHA1' },
{ regex: /^[0-9a-f]{32}$/i, type: 'hash_md5', humanReadable: 'MD5' },
// Match any "other" selection
{ regex: /./g, type: 'other' },
{ regex: /./g, type: 'other', humanReadable: 'Other' },
]

export {IOCTypes}
91 changes: 61 additions & 30 deletions timesketch/frontend-ng/src/views/ThreatIntel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,14 @@ limitations under the License.
-->
<template>
<div>
<ts-indicator-dialog
:dialog.sync="indicatorDialog"
:index="currentIndex"
:tag-info="tagInfo"
:ioc="indicator"
@open-dialog="indicatorDialog = true"
@close-dialog="
<ts-indicator-dialog :dialog.sync="indicatorDialog" :index="currentIndex" :tag-info="tagInfo" :ioc="indicator"
@open-dialog="indicatorDialog = true" @close-dialog="
indicatorDialog = false
currentIndex = -1
"
@save="
saveIntelligence($event)
currentIndex = -1
" @save="
saveIntelligence($event)
indicatorDialog = false
"
>
">
</ts-indicator-dialog>

<v-container fluid>
Expand All @@ -39,12 +32,9 @@ limitations under the License.
</v-btn>

<v-card outlined class="mt-3 mx-3">
<v-data-table
:headers="headers"
:items="intelligenceData"
<v-data-table :headers="headers" :items="intelligenceData"
:footer-props="{ 'items-per-page-options': [10, 40, 80, 100, 200, 500], 'show-current-page': true }"
:items-per-page="40"
>
:items-per-page="40" selectable>
<template v-slot:item.search="{ item }">
<v-btn icon small @click="generateSearchQuery(item.ioc)">
<v-icon title="Search this indicator" small>mdi-magnify</v-icon>
Expand All @@ -53,19 +43,21 @@ limitations under the License.

<template v-slot:item.externalURI="{ item }">
<v-icon title="Open link" v-if="item.externalURI" x-small>mdi-open-in-new</v-icon>
<a
style="text-decoration: none"
v-if="getValidUrl(item.externalURI)"
:href="getValidUrl(item.externalURI)"
target="_blank"
>
{{ getValidUrl(item.externalURI).host }}</a
>
<a style="text-decoration: none" v-if="getValidUrl(item.externalURI)" :href="getValidUrl(item.externalURI)"
target="_blank">
{{ getValidUrl(item.externalURI).host }}</a>
</template>

<template v-slot:item.type="{ item }">
{{ getIocTypeMetadata(item).humanReadable }}
</template>

<template v-slot:item.tags="{ item }">
<v-chip-group>
<v-chip small v-for="tag in item.tags" :key="tag" @click="searchForIOC(tag)">
{{ tag }}
<v-chip small v-for="tag in augmentedTags(item.tags).sort((a, b) => b.weight - a.weight)"
:color="tag.color" :text-color="tag.textColor" :outlined="tag.style === 'outlined'" :key="tag.name"
@click="searchForIOC(tag)">
{{ tag.name }}
</v-chip>
</v-chip-group>
</template>
Expand All @@ -88,6 +80,7 @@ limitations under the License.
import ApiClient from '../utils/RestApiClient.js'
import EventBus from '../event-bus.js'
import TsIndicatorDialog from '../components/ThreatIntel/IndicatorDialog.vue'
import { IOCTypes } from '@/utils/ThreatIntelMetadata'

const defaultQueryFilter = () => {
return {
Expand Down Expand Up @@ -119,6 +112,14 @@ export default {
indicatorDialog: false,
currentIndex: -1,
indicator: '',
tagMetadata: { default: { weight: 0, type: 'default' } },
tagColorDefinitions: {
danger: { color: 'red', textColor: 'white' },
warning: { color: 'orange', textColor: 'white' },
legit: { color: 'green', textColor: 'white' },
default: { color: 'default', textColor: null },
info: { color: 'blue', textColor: null, style: 'outlined' }
}
}
},
computed: {
Expand All @@ -142,6 +143,35 @@ export default {
addIndicator() {
this.indicatorDialog = true
},
loadTagMetadata() {
ApiClient.getTagMetadata().then((response) => {
this.tagMetadata = response.data
})
},
metadataForTag(tag) {
let metadata = this.tagMetadata['default'];
if (this.tagMetadata[tag]) {
metadata = this.tagMetadata[tag]
} else {
for (var regex in this.tagMetadata['regexes']) {
if (tag.match(regex)) {
metadata = this.tagMetadata['regexes'][regex]
}
}
}
return { ...this.tagColorDefinitions[metadata.type], name: tag, weight: metadata.weight }
},
augmentedTags(tags) {
return tags.map(tag => this.metadataForTag(tag))
},
getIocTypeMetadata(ioc) {
let iocTypeMetatada = IOCTypes.find(def => def.type === ioc.type)
if (iocTypeMetatada !== undefined) {
return iocTypeMetatada
} else {
return IOCTypes.find(def => def.type === 'other')
}
},
deleteIndicator(index) {
if (confirm('Delete indicator?')) {
this.intelligenceAttribute.value.data.splice(index, 1)
Expand Down Expand Up @@ -230,13 +260,14 @@ export default {
})
},
showIndicatorDialog(payload) {
this.indicator = payload
this.indicatorDialog = true
this.indicator = payload
this.indicatorDialog = true
},
},
mounted() {
EventBus.$on('addIndicator', this.showIndicatorDialog)
this.buildTagInfo()
this.loadTagMetadata()
},
beforeDestroy() {
EventBus.$off('addIndicator')
Expand Down

0 comments on commit 8dcccd5

Please sign in to comment.