From 906d856ee77526b748f6f9e3698c31ec7f5b4817 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Tue, 15 Jun 2021 14:17:32 +0200 Subject: [PATCH 01/11] Add generation of memory alerts to generate data script --- .../common/endpoint/generate_data.ts | 196 +++++++++++++++--- .../common/endpoint/types/index.ts | 10 + 2 files changed, 177 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 7e03d9b61fc10e..a837ec95ba2ef4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -7,6 +7,7 @@ import uuid from 'uuid'; import seedrandom from 'seedrandom'; +import { assertNever } from '@kbn/std'; import { AlertEvent, DataStream, @@ -387,12 +388,49 @@ const eventsDefaultDataStream = { namespace: 'default', }; +enum AlertTypes { + MALWARE = 'MALWARE', + MEMORY_SIGNATURE = 'MEMORY_SIGNATURE', + MEMORY_SHELLCODE = 'MEMORY_SHELLCODE', +} + const alertsDefaultDataStream = { type: 'logs', dataset: 'endpoint.alerts', namespace: 'default', }; +const alertsDefaultDll = [ + { + pe: { + architecture: 'x64', + }, + code_signature: { + subject_name: 'Cybereason Inc', + trusted: true, + }, + + hash: { + md5: '1f2d082566b0fc5f2c238a5180db7451', + sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d', + sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2', + }, + + path: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe', + Ext: { + compile_time: 1534424710, + mapped_address: 5362483200, + mapped_size: 0, + malware_classification: { + identifier: 'Whitelisted', + score: 0, + threshold: 0, + version: '3.0.0', + }, + }, + }, +]; + export class EndpointDocGenerator extends BaseDataGenerator { commonInfo: HostInfo; sequence: number = 0; @@ -501,16 +539,15 @@ export class EndpointDocGenerator extends BaseDataGenerator { data_stream: metadataDataStream, }; } - /** - * Creates an alert from the simulated host represented by this EndpointDocGenerator + * Creates a malware alert from the simulated host represented by this EndpointDocGenerator * @param ts - Timestamp to put in the event * @param entityID - entityID of the originating process * @param parentEntityID - optional entityID of the parent process, if it exists * @param ancestry - an array of ancestors for the generated alert * @param alertsDataStream the values to populate the data_stream fields when generating alert documents */ - public generateAlert({ + public generateMalwareAlert({ ts = new Date().getTime(), entityID = this.randomString(10), parentEntityID, @@ -611,38 +648,139 @@ export class EndpointDocGenerator extends BaseDataGenerator { }, }, }, - dll: [ - { - pe: { - architecture: 'x64', - }, - code_signature: { - subject_name: 'Cybereason Inc', - trusted: true, - }, - - hash: { - md5: '1f2d082566b0fc5f2c238a5180db7451', - sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d', - sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2', - }, + dll: alertsDefaultDll, + }; + } - path: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe', - Ext: { - compile_time: 1534424710, - mapped_address: 5362483200, - mapped_size: 0, - malware_classification: { - identifier: 'Whitelisted', - score: 0, - threshold: 0, - version: '3.0.0', + /** + * Creates a memory alert from the simulated host represented by this EndpointDocGenerator + * @param ts - Timestamp to put in the event + * @param entityID - entityID of the originating process + * @param parentEntityID - optional entityID of the parent process, if it exists + * @param ancestry - an array of ancestors for the generated alert + * @param alertsDataStream the values to populate the data_stream fields when generating alert documents + */ + public generateMemoryAlert({ + ts = new Date().getTime(), + entityID = this.randomString(10), + parentEntityID, + ancestry = [], + alertsDataStream = alertsDefaultDataStream, + alertType, + }: { + ts?: number; + entityID?: string; + parentEntityID?: string; + ancestry?: string[]; + alertsDataStream?: DataStream; + alertType?: AlertTypes; + } = {}): AlertEvent { + const processName = this.randomProcessName(); + const isShellcode = alertType === AlertTypes.MEMORY_SHELLCODE; + return { + ...this.commonInfo, + data_stream: alertsDataStream, + '@timestamp': ts, + ecs: { + version: '1.6.0', + }, + // disabling naming-convention to accommodate external field + // eslint-disable-next-line @typescript-eslint/naming-convention + Memory_protection: { + feature: isShellcode ? 'shellcode_thread' : 'signature', + self_injection: true, + }, + event: { + action: 'start', + kind: 'alert', + category: 'memory', + code: 'memory_signature', + id: this.seededUUIDv4(), + dataset: 'endpoint', + module: 'endpoint', + type: 'info', + sequence: this.sequence++, + }, + file: {}, + process: { + pid: 2, + name: processName, + start: ts, + uptime: 0, + entity_id: entityID, + executable: `C:/fake/${processName}`, + parent: parentEntityID ? { entity_id: parentEntityID, pid: 1 } : undefined, + hash: { + md5: 'fake md5', + sha1: 'fake sha1', + sha256: 'fake sha256', + }, + Ext: { + ancestry, + code_signature: [ + { + trusted: false, + subject_name: 'bad signer', }, + ], + user: 'SYSTEM', + token: { + integrity_level_name: 'high', + }, + malware_signature: { + all_names: 'Windows.Trojan.FakeAgent', + identifier: 'diagnostic-malware-signature-v1-fake', }, }, - ], + }, + dll: alertsDefaultDll, }; } + /** + * Creates an alert from the simulated host represented by this EndpointDocGenerator + * @param ts - Timestamp to put in the event + * @param entityID - entityID of the originating process + * @param parentEntityID - optional entityID of the parent process, if it exists + * @param ancestry - an array of ancestors for the generated alert + * @param alertsDataStream the values to populate the data_stream fields when generating alert documents + */ + public generateAlert({ + ts = new Date().getTime(), + entityID = this.randomString(10), + parentEntityID, + ancestry = [], + alertsDataStream = alertsDefaultDataStream, + }: { + ts?: number; + entityID?: string; + parentEntityID?: string; + ancestry?: string[]; + alertsDataStream?: DataStream; + } = {}): AlertEvent { + const alertType = this.randomChoice(Object.values(AlertTypes)); + switch (alertType) { + case AlertTypes.MALWARE: + return this.generateMalwareAlert({ + ts, + entityID, + parentEntityID, + ancestry, + alertsDataStream, + }); + case AlertTypes.MEMORY_SIGNATURE: + case AlertTypes.MEMORY_SHELLCODE: + return this.generateMemoryAlert({ + ts, + entityID, + parentEntityID, + ancestry, + alertsDataStream, + alertType, + }); + default: + return assertNever(alertType); + } + } /** * Creates an event, customized by the options parameter diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 1e0d798cf7f07d..6e88ea24f63c71 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -297,6 +297,12 @@ export type AlertEvent = Partial<{ }>; }>; }>; + // disabling naming-convention to accommodate external field + // eslint-disable-next-line @typescript-eslint/naming-convention + Memory_protection: Partial<{ + feature: ECSField; + self_injection: ECSField; + }>; process: Partial<{ command_line: ECSField; ppid: ECSField; @@ -330,6 +336,10 @@ export type AlertEvent = Partial<{ >; }>; user: ECSField; + malware_signature: Partial<{ + all_names: ECSField; + identifier: ECSField; + }>; }>; }>; file: Partial<{ From fd6558a5d5f1d4a9a7bdcdd007af30fa65ababef Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Wed, 16 Jun 2021 13:09:15 +0200 Subject: [PATCH 02/11] Set the correct event code for memory alerts generation --- .../plugins/security_solution/common/endpoint/generate_data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index a837ec95ba2ef4..40b9f42072ad47 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -694,7 +694,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { action: 'start', kind: 'alert', category: 'memory', - code: 'memory_signature', + code: isShellcode ? 'malicious_thread' : 'memory_signature', id: this.seededUUIDv4(), dataset: 'endpoint', module: 'endpoint', From 7f642581bf00e66c64475c0624aef129cac1fe19 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Wed, 16 Jun 2021 17:10:25 +0200 Subject: [PATCH 03/11] Add exceptions fields for memory alerts --- .../common/ecs/file/index.ts | 6 + .../security_solution/common/ecs/index.ts | 3 + .../common/ecs/memory_protection/index.ts | 14 ++ .../exceptionable_endpoint_fields.json | 4 +- .../common/components/exceptions/helpers.tsx | 155 +++++++++++++++--- 5 files changed, 160 insertions(+), 22 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts diff --git a/x-pack/plugins/security_solution/common/ecs/file/index.ts b/x-pack/plugins/security_solution/common/ecs/file/index.ts index 5e409b1095cf59..59b8a139cc6727 100644 --- a/x-pack/plugins/security_solution/common/ecs/file/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/file/index.ts @@ -14,9 +14,15 @@ export interface CodeSignature { subject_name: string[]; trusted: string[]; } + +export interface Token { + integrity_level_name: string; +} + export interface Ext { code_signature?: CodeSignature[] | CodeSignature; original?: Original; + token?: Token; } export interface Hash { md5?: string[]; diff --git a/x-pack/plugins/security_solution/common/ecs/index.ts b/x-pack/plugins/security_solution/common/ecs/index.ts index 8054b3c8521db5..fd6dc74e49ea26 100644 --- a/x-pack/plugins/security_solution/common/ecs/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/index.ts @@ -30,6 +30,7 @@ import { ProcessEcs } from './process'; import { SystemEcs } from './system'; import { ThreatEcs } from './threat'; import { Ransomware } from './ransomware'; +import { MemoryProtection } from './memory_protection'; export interface Ecs { _id: string; @@ -63,4 +64,6 @@ export interface Ecs { // This should be temporary eql?: { parentId: string; sequenceNumber: string }; Ransomware?: Ransomware; + // eslint-disable-next-line @typescript-eslint/naming-convention + Memory_protection?: MemoryProtection; } diff --git a/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts new file mode 100644 index 00000000000000..13fc6c0eb8c7df --- /dev/null +++ b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export interface MemoryProtection { + cross_session: boolean; + // should this be a enum with 'signature' and ' shellcode_thread' ? are there more options? + feature: string; + parent_to_child: boolean; + self_injection: boolean; + unique_key_v1: string; +} diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json index d5134945441f51..b54d82f6bd364b 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json @@ -108,5 +108,7 @@ "user.email", "user.hash", "user.id", - "Ransomware.feature" + "Ransomware.feature", + "Memory_protection.feature", + "Memory_protection.self_injection" ] diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx index 20413a64936613..2c79e632cfd5fa 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx @@ -477,6 +477,100 @@ export const getPrepopulatedRansomwareException = ({ }; }; +export const getPrepopulatedMemorySignatureException = ({ + listId, + ruleName, + eventCode, + listNamespace = 'agnostic', + alertEcsData, +}: { + listId: string; + listNamespace?: NamespaceType; + ruleName: string; + eventCode: string; + alertEcsData: Flattened; +}): ExceptionsBuilderExceptionItem => { + const { process } = alertEcsData; + return { + ...getNewExceptionItem({ listId, namespaceType: listNamespace, ruleName }), + entries: addIdToEntries([ + { + field: 'Memory_protection.feature', + operator: 'included', + type: 'match', + value: alertEcsData.Memory_protection?.feature ?? '', + }, + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: process?.executable ?? '', + }, + { + field: 'process.name.caseless', + operator: 'included', + type: 'match', + value: process?.name ?? '', + }, + { + field: 'process.hash.sha256', + operator: 'included', + type: 'match', + value: process?.hash?.sha256 ?? '', + }, + ]), + }; +}; +export const getPrepopulatedMemoryShellcodeException = ({ + listId, + ruleName, + eventCode, + listNamespace = 'agnostic', + alertEcsData, +}: { + listId: string; + listNamespace?: NamespaceType; + ruleName: string; + eventCode: string; + alertEcsData: Flattened; +}): ExceptionsBuilderExceptionItem => { + const { process } = alertEcsData; + return { + ...getNewExceptionItem({ listId, namespaceType: listNamespace, ruleName }), + entries: addIdToEntries([ + { + field: 'Memory_protection.feature', + operator: 'included', + type: 'match', + value: alertEcsData.Memory_protection?.feature ?? '', + }, + { + field: 'Memory_protection.self_injection', + operator: 'included', + type: 'match', + value: String(alertEcsData.Memory_protection?.self_injection) ?? '', + }, + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: process?.executable ?? '', + }, + { + field: 'process.name.caseless', + operator: 'included', + type: 'match', + value: process?.name ?? '', + }, + { + field: 'process.Ext.token.integrity_level_name', + operator: 'included', + type: 'match', + value: process?.Ext?.token?.integrity_level_name ?? '', + }, + ]), + }; +}; /** * Determines whether or not any entries within the given exceptionItems contain values not in the specified ECS mapping */ @@ -518,26 +612,45 @@ export const defaultEndpointExceptionItems = ( const { event: alertEvent } = alertEcsData; const eventCode = alertEvent?.code ?? ''; - if (eventCode === 'ransomware') { - return getProcessCodeSignature(alertEcsData).map((codeSignature) => - getPrepopulatedRansomwareException({ - listId, - ruleName, - eventCode, - codeSignature, - alertEcsData, - }) - ); + switch (eventCode) { + case 'memory_signature': + return [ + getPrepopulatedMemorySignatureException({ + listId, + ruleName, + eventCode, + alertEcsData, + }), + ]; + case 'malicious_thread': + return [ + getPrepopulatedMemoryShellcodeException({ + listId, + ruleName, + eventCode, + alertEcsData, + }), + ]; + case 'ransomware': + return getProcessCodeSignature(alertEcsData).map((codeSignature) => + getPrepopulatedRansomwareException({ + listId, + ruleName, + eventCode, + codeSignature, + alertEcsData, + }) + ); + default: + // By default return the standard prepopulated Endpoint Exception fields + return getFileCodeSignature(alertEcsData).map((codeSignature) => + getPrepopulatedEndpointException({ + listId, + ruleName, + eventCode, + codeSignature, + alertEcsData, + }) + ); } - - // By default return the standard prepopulated Endpoint Exception fields - return getFileCodeSignature(alertEcsData).map((codeSignature) => - getPrepopulatedEndpointException({ - listId, - ruleName, - eventCode, - codeSignature, - alertEcsData, - }) - ); }; From d3819a07b2cd3ca22fed889063eb56eb4d41feb0 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 17 Jun 2021 10:40:11 +0200 Subject: [PATCH 04/11] Update generator to use malware as the memory alerts category --- .../plugins/security_solution/common/endpoint/generate_data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 40b9f42072ad47..49a7545b633049 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -693,7 +693,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { event: { action: 'start', kind: 'alert', - category: 'memory', + category: 'malware', code: isShellcode ? 'malicious_thread' : 'memory_signature', id: this.seededUUIDv4(), dataset: 'endpoint', From 708355ce0cf807da3d70226411c96b8f9b9bcc98 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 17 Jun 2021 17:22:09 +0200 Subject: [PATCH 05/11] Add missing memory shellcode_thread fields add tests for the memory exception default fields --- .../common/ecs/file/index.ts | 15 ++ .../security_solution/common/ecs/index.ts | 2 + .../common/ecs/memory_protection/index.ts | 10 +- .../common/ecs/process/index.ts | 1 + .../common/endpoint/generate_data.ts | 26 ++- .../common/endpoint/types/index.ts | 19 ++ .../components/exceptions/helpers.test.tsx | 167 ++++++++++++++++++ .../common/components/exceptions/helpers.tsx | 41 ++++- 8 files changed, 274 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/security_solution/common/ecs/file/index.ts b/x-pack/plugins/security_solution/common/ecs/file/index.ts index 59b8a139cc6727..32ee16d330f411 100644 --- a/x-pack/plugins/security_solution/common/ecs/file/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/file/index.ts @@ -19,10 +19,25 @@ export interface Token { integrity_level_name: string; } +export interface MemoryPe { + imphash?: string; +} + +export interface StartAddressDetails { + allocation_type?: string; + allocation_size?: number; + region_size?: number; + region_protection?: string; + memory_pe?: MemoryPe; +} + export interface Ext { code_signature?: CodeSignature[] | CodeSignature; original?: Original; token?: Token; + start_address_allocation_offset?: number; + start_address_bytes_disasm_hash?: string; + start_address_details?: StartAddressDetails; } export interface Hash { md5?: string[]; diff --git a/x-pack/plugins/security_solution/common/ecs/index.ts b/x-pack/plugins/security_solution/common/ecs/index.ts index fd6dc74e49ea26..ea3d384e1211f3 100644 --- a/x-pack/plugins/security_solution/common/ecs/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/index.ts @@ -31,6 +31,7 @@ import { SystemEcs } from './system'; import { ThreatEcs } from './threat'; import { Ransomware } from './ransomware'; import { MemoryProtection } from './memory_protection'; +import { Target } from './target'; export interface Ecs { _id: string; @@ -66,4 +67,5 @@ export interface Ecs { Ransomware?: Ransomware; // eslint-disable-next-line @typescript-eslint/naming-convention Memory_protection?: MemoryProtection; + Target?: Target; } diff --git a/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts index 13fc6c0eb8c7df..a7ae882aba5aef 100644 --- a/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts @@ -5,10 +5,10 @@ * 2.0. */ export interface MemoryProtection { - cross_session: boolean; + cross_session?: boolean; // should this be a enum with 'signature' and ' shellcode_thread' ? are there more options? - feature: string; - parent_to_child: boolean; - self_injection: boolean; - unique_key_v1: string; + feature?: string; + parent_to_child?: boolean; + self_injection?: boolean; + unique_key_v1?: string; } diff --git a/x-pack/plugins/security_solution/common/ecs/process/index.ts b/x-pack/plugins/security_solution/common/ecs/process/index.ts index 820ecc5560e6c5..0eb2400466e640 100644 --- a/x-pack/plugins/security_solution/common/ecs/process/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/process/index.ts @@ -37,4 +37,5 @@ export interface ProcessParentData { export interface Thread { id?: number[]; start?: string[]; + Ext?: Ext; } diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index a2920793b096ff..e3bad6bb1c9ff4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -685,7 +685,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { } = {}): AlertEvent { const processName = this.randomProcessName(); const isShellcode = alertType === AlertTypes.MEMORY_SHELLCODE; - return { + const newAlert: AlertEvent = { ...this.commonInfo, data_stream: alertsDataStream, '@timestamp': ts, @@ -743,6 +743,30 @@ export class EndpointDocGenerator extends BaseDataGenerator { }, dll: alertsDefaultDll, }; + + // shellcode_thread memory alert have an additional process field + if (isShellcode) { + newAlert.Target = { + process: { + thread: { + Ext: { + start_address_allocation_offset: 0, + start_address_bytes_disasm_hash: 'a disam hash', + start_address_details: { + allocation_type: 'PRIVATE', + allocation_size: 4000, + region_size: 4000, + region_protection: 'RWX', + memory_pe: { + imphash: 'a hash', + }, + }, + }, + }, + }, + }; + } + return newAlert; } /** * Creates an alert from the simulated host represented by this EndpointDocGenerator diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 6e88ea24f63c71..f2ea787a3e9411 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -303,6 +303,25 @@ export type AlertEvent = Partial<{ feature: ECSField; self_injection: ECSField; }>; + Target: Partial<{ + process: Partial<{ + thread: Partial<{ + Ext: Partial<{ + start_address_allocation_offset: ECSField; + start_address_bytes_disasm_hash: ECSField; + start_address_details: Partial<{ + allocation_type: ECSField; + allocation_size: ECSField; + region_size: ECSField; + region_protection: ECSField; + memory_pe: Partial<{ + imphash: ECSField; + }>; + }>; + }>; + }>; + }>; + }>; process: Partial<{ command_line: ECSField; ppid: ECSField; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx index 383b177d40c647..51aef37c647f66 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx @@ -939,5 +939,172 @@ describe('Exception helpers', () => { }, ]); }); + + test('it should return pre-populated memory signature items for event code `memory_signature`', () => { + const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', { + _id: '123', + process: { + name: 'some name', + executable: 'some file path', + hash: { + sha256: 'some hash', + }, + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + Memory_protection: { + feature: 'signature', + }, + event: { + code: 'memory_signature', + }, + }); + + expect(defaultItems[0].entries).toEqual([ + { + field: 'Memory_protection.feature', + operator: 'included', + type: 'match', + value: 'signature', + id: '123', + }, + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: 'some file path', + id: '123', + }, + { + field: 'process.name.caseless', + operator: 'included', + type: 'match', + value: 'some name', + id: '123', + }, + { + field: 'process.hash.sha256', + operator: 'included', + type: 'match', + value: 'some hash', + id: '123', + }, + ]); + }); + + test('it should return pre-populated memory shellcode items for event code `malicious_thread`', () => { + const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', { + _id: '123', + process: { + name: 'some name', + executable: 'some file path', + Ext: { + token: { + integrity_level_name: 'high', + }, + }, + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + Memory_protection: { + feature: 'shellcode_thread', + self_injection: true, + }, + event: { + code: 'malicious_thread', + }, + Target: { + process: { + thread: { + Ext: { + start_address_allocation_offset: 0, + start_address_bytes_disasm_hash: 'a disam hash', + start_address_details: { + allocation_type: 'PRIVATE', + allocation_size: 4000, + region_size: 4000, + region_protection: 'RWX', + memory_pe: { + imphash: 'a hash', + }, + }, + }, + }, + }, + }, + }); + + expect(defaultItems[0].entries).toEqual([ + { + field: 'Memory_protection.feature', + operator: 'included', + type: 'match', + value: 'shellcode_thread', + id: '123', + }, + { + field: 'Memory_protection.self_injection', + operator: 'included', + type: 'match', + value: 'true', + id: '123', + }, + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: 'some file path', + id: '123', + }, + { + field: 'process.name.caseless', + operator: 'included', + type: 'match', + value: 'some name', + id: '123', + }, + { + field: 'process.Ext.token.integrity_level_name', + operator: 'included', + type: 'match', + value: 'high', + id: '123', + }, + { + field: 'Target.process.thread.Ext.start_address_details', + type: 'nested', + entries: [ + { + field: 'allocation_type', + operator: 'included', + type: 'match', + value: 'PRIVATE', + id: '123', + }, + { + field: 'allocation_size', + operator: 'included', + type: 'match', + value: '4000', + id: '123', + }, + { field: 'region_size', operator: 'included', type: 'match', value: '4000', id: '123' }, + { + field: 'region_protection', + operator: 'included', + type: 'match', + value: 'RWX', + id: '123', + }, + { + field: 'memory_pe.imphash', + operator: 'included', + type: 'match', + value: 'a hash', + id: '123', + }, + ], + id: '123', + }, + ]); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx index 2c79e632cfd5fa..61534660614991 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx @@ -534,7 +534,7 @@ export const getPrepopulatedMemoryShellcodeException = ({ eventCode: string; alertEcsData: Flattened; }): ExceptionsBuilderExceptionItem => { - const { process } = alertEcsData; + const { process, Target } = alertEcsData; return { ...getNewExceptionItem({ listId, namespaceType: listNamespace, ruleName }), entries: addIdToEntries([ @@ -568,6 +568,45 @@ export const getPrepopulatedMemoryShellcodeException = ({ type: 'match', value: process?.Ext?.token?.integrity_level_name ?? '', }, + { + field: 'Target.process.thread.Ext.start_address_details', + type: 'nested', + entries: [ + { + field: 'allocation_type', + operator: 'included', + type: 'match', + value: Target?.process?.thread?.Ext?.start_address_details?.allocation_type ?? '', + }, + { + field: 'allocation_size', + operator: 'included', + type: 'match', + value: + String(Target?.process?.thread?.Ext?.start_address_details?.allocation_size) ?? '', + }, + { + field: 'region_size', + operator: 'included', + type: 'match', + value: String(Target?.process?.thread?.Ext?.start_address_details?.region_size) ?? '', + }, + { + field: 'region_protection', + operator: 'included', + type: 'match', + value: + String(Target?.process?.thread?.Ext?.start_address_details?.region_protection) ?? '', + }, + { + field: 'memory_pe.imphash', + operator: 'included', + type: 'match', + value: + String(Target?.process?.thread?.Ext?.start_address_details?.memory_pe?.imphash) ?? '', + }, + ], + }, ]), }; }; From c050bca1ed14a98ef4d9af0a4db33aefa2b4babd Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Fri, 18 Jun 2021 10:38:09 +0200 Subject: [PATCH 06/11] Change the target folder to target_type --- x-pack/plugins/security_solution/common/ecs/index.ts | 2 +- .../common/ecs/target_type/index.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/security_solution/common/ecs/target_type/index.ts diff --git a/x-pack/plugins/security_solution/common/ecs/index.ts b/x-pack/plugins/security_solution/common/ecs/index.ts index ea3d384e1211f3..610a2fd1f6e9ed 100644 --- a/x-pack/plugins/security_solution/common/ecs/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/index.ts @@ -31,7 +31,7 @@ import { SystemEcs } from './system'; import { ThreatEcs } from './threat'; import { Ransomware } from './ransomware'; import { MemoryProtection } from './memory_protection'; -import { Target } from './target'; +import { Target } from './target_type'; export interface Ecs { _id: string; diff --git a/x-pack/plugins/security_solution/common/ecs/target_type/index.ts b/x-pack/plugins/security_solution/common/ecs/target_type/index.ts new file mode 100644 index 00000000000000..3c19b51173a043 --- /dev/null +++ b/x-pack/plugins/security_solution/common/ecs/target_type/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ProcessEcs } from '../process'; + +export interface Target { + process: ProcessEcs; +} From 5d0484e1f55baddf6092e1f7dfc095e06c382983 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Mon, 21 Jun 2021 11:12:16 +0200 Subject: [PATCH 07/11] Add Target.process.thread fields to excepctionable fields --- .../exceptions/exceptionable_endpoint_fields.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json index b54d82f6bd364b..bb81f7a00cc144 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json @@ -25,6 +25,13 @@ "Target.process.pe.original_file_name", "Target.process.pe.product", "Target.process.pgid", + "Target.process.thread.Ext.start_address_details.allocation_type", + "Target.process.thread.Ext.start_address_bytes_disasm_hash", + "Target.process.thread.Ext.start_address_allocation_offset", + "Target.process.thread.Ext.start_address_details.allocation_size", + "Target.process.thread.Ext.start_address_details.region_size", + "Target.process.thread.Ext.start_address_details.region_protection", + "Target.process.thread.Ext.start_address_details.memory_pe.imphash", "agent.id", "agent.type", "agent.version", From 55800eb2d06763a6666c186eecebebf0681bcb3c Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Tue, 29 Jun 2021 09:04:28 +0200 Subject: [PATCH 08/11] Remove unused comment --- .../security_solution/common/ecs/memory_protection/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts index a7ae882aba5aef..8115fc0dcd26e8 100644 --- a/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/memory_protection/index.ts @@ -6,7 +6,6 @@ */ export interface MemoryProtection { cross_session?: boolean; - // should this be a enum with 'signature' and ' shellcode_thread' ? are there more options? feature?: string; parent_to_child?: boolean; self_injection?: boolean; From 1efeb8eaac6d8803181ae6aa23f3ce12f58aba1f Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 1 Jul 2021 17:32:20 +0200 Subject: [PATCH 09/11] Use a function to return defaultDlls instead of mutable data --- .../common/endpoint/generate_data.ts | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 2477d70ead21e5..255ab8f0a598c9 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -400,37 +400,6 @@ const alertsDefaultDataStream = { namespace: 'default', }; -const alertsDefaultDll = [ - { - pe: { - architecture: 'x64', - }, - code_signature: { - subject_name: 'Cybereason Inc', - trusted: true, - }, - - hash: { - md5: '1f2d082566b0fc5f2c238a5180db7451', - sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d', - sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2', - }, - - path: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe', - Ext: { - compile_time: 1534424710, - mapped_address: 5362483200, - mapped_size: 0, - malware_classification: { - identifier: 'Whitelisted', - score: 0, - threshold: 0, - version: '3.0.0', - }, - }, - }, -]; - export class EndpointDocGenerator extends BaseDataGenerator { commonInfo: HostInfo; sequence: number = 0; @@ -656,7 +625,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { }, }, }, - dll: alertsDefaultDll, + dll: this.getAlertsDefaultDll(), }; } @@ -741,7 +710,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { }, }, }, - dll: alertsDefaultDll, + dll: this.getAlertsDefaultDll(), }; // shellcode_thread memory alert have an additional process field @@ -814,6 +783,42 @@ export class EndpointDocGenerator extends BaseDataGenerator { } } + /** + * Returns the default DLLs used in alerts + */ + private getAlertsDefaultDll() { + return [ + { + pe: { + architecture: 'x64', + }, + code_signature: { + subject_name: 'Cybereason Inc', + trusted: true, + }, + + hash: { + md5: '1f2d082566b0fc5f2c238a5180db7451', + sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d', + sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2', + }, + + path: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe', + Ext: { + compile_time: 1534424710, + mapped_address: 5362483200, + mapped_size: 0, + malware_classification: { + identifier: 'Whitelisted', + score: 0, + threshold: 0, + version: '3.0.0', + }, + }, + }, + ]; + } + /** * Creates an event, customized by the options parameter * @param options - Allows event field values to be specified From f1f968f455cfaab2a895226ba5abab59a529da22 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Mon, 12 Jul 2021 09:44:32 +0200 Subject: [PATCH 10/11] Add missing types for StartAddressDetails --- .../security_solution/common/ecs/file/index.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/common/ecs/file/index.ts b/x-pack/plugins/security_solution/common/ecs/file/index.ts index 32ee16d330f411..0c9dde20011f49 100644 --- a/x-pack/plugins/security_solution/common/ecs/file/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/file/index.ts @@ -24,10 +24,22 @@ export interface MemoryPe { } export interface StartAddressDetails { - allocation_type?: string; + allocation_base?: number; + allocation_protection?: string; allocation_size?: number; - region_size?: number; + allocation_type?: string; + bytes_address?: number; + bytes_allocation_offset?: number; + bytes_compressed?: string; + bytes_compressed_present?: string; + mapped_path?: string; + mapped_pe_detected?: boolean; + memory_pe_detected?: boolean; + region_base?: number; region_protection?: string; + region_size?: number; + region_state?: string; + strings?: string; memory_pe?: MemoryPe; } From 571902e168b56c984126c3dc58b40bf6093b500e Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Mon, 12 Jul 2021 09:47:10 +0200 Subject: [PATCH 11/11] Add additional exceptionable_endpoint_fields as suggested --- .../exceptions/exceptionable_endpoint_fields.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json index 147969043d0175..c37be60545ab2e 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json @@ -2,10 +2,12 @@ "Endpoint.policy.applied.id", "Target.process.Ext.services", "Target.process.Ext.user", + "Target.process.executable", "Target.process.hash.md5", "Target.process.hash.sha1", "Target.process.hash.sha256", "Target.process.hash.sha512", + "Target.process.name", "Target.process.parent.hash.md5", "Target.process.parent.hash.sha1", "Target.process.parent.hash.sha256", @@ -24,6 +26,7 @@ "Target.process.thread.Ext.start_address_details.region_size", "Target.process.thread.Ext.start_address_details.region_protection", "Target.process.thread.Ext.start_address_details.memory_pe.imphash", + "Target.process.thread.Ext.start_address_bytes", "agent.id", "agent.type", "agent.version", @@ -75,10 +78,13 @@ "host.type", "process.Ext.services", "process.Ext.user", + "process.Ext.code_signature", + "process.executable", "process.hash.md5", "process.hash.sha1", "process.hash.sha256", "process.hash.sha512", + "process.name", "process.parent.hash.md5", "process.parent.hash.sha1", "process.parent.hash.sha256",