Skip to content

Commit

Permalink
[Security Solution] Analyzer with sysmon via filebeat (#152418)
Browse files Browse the repository at this point in the history
## Summary

Related issue: #148043

With the switch from beats to elastic agent, analyzer broke for sysmon
data ingested via elastic agent, as some fields the code expects to
exist became slightly different, this pr updates the frontend and server
side api of analyzer to work with both old winlogbeat style sysmom
ingestion and new elastic agent + filebeat shipping sysmon generated
data.



https://user-images.githubusercontent.com/56408403/222063497-64b2853e-5d09-4178-b336-1007886c396b.mov

Video with 8.6 agent/fleet + latest main kibana/es + windows 10 w/sysmon
vm

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
kqualters-elastic authored Mar 1, 2023
1 parent 242d7bc commit a9313ee
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,27 @@ describe('InvestigateInResolverAction', () => {

expect(isInvestigateInResolverActionEnabled(data)).toBeFalsy();
});

it('returns true for process event from sysmon via filebeat', () => {
const data: Ecs = {
_id: '1',
agent: { type: ['filebeat'] },
event: { dataset: ['windows.sysmon_operational'] },
process: { entity_id: ['always_unique'] },
};

expect(isInvestigateInResolverActionEnabled(data)).toBeTruthy();
});

it('returns false for process event from filebeat but not from sysmon', () => {
const data: Ecs = {
_id: '1',
agent: { type: ['filebeat'] },
event: { dataset: ['windows.not_sysmon'] },
process: { entity_id: ['always_unique'] },
};

expect(isInvestigateInResolverActionEnabled(data)).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,20 @@
import { get } from 'lodash/fp';
import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';

export const isInvestigateInResolverActionEnabled = (ecsData?: Ecs) =>
(get(['agent', 'type', 0], ecsData) === 'endpoint' ||
(get(['agent', 'type', 0], ecsData) === 'winlogbeat' &&
get(['event', 'module', 0], ecsData) === 'sysmon')) &&
get(['process', 'entity_id'], ecsData)?.length === 1 &&
get(['process', 'entity_id', 0], ecsData) !== '';
export const isInvestigateInResolverActionEnabled = (ecsData?: Ecs) => {
const agentType = get(['agent', 'type', 0], ecsData);
const processEntityIds = get(['process', 'entity_id'], ecsData);
const firstProcessEntityId = get(['process', 'entity_id', 0], ecsData);
const eventModule = get(['event', 'module', 0], ecsData);
const eventDataStream = get(['event', 'dataset'], ecsData);
const datasetIncludesSysmon =
Array.isArray(eventDataStream) &&
eventDataStream.some((datastream) => datastream.includes('windows.sysmon'));
const agentTypeIsEndpoint = agentType === 'endpoint';
const agentTypeIsWinlogBeat = agentType === 'winlogbeat' && eventModule === 'sysmon';
const isEndpointOrSysmonFromWinlogBeat =
agentTypeIsEndpoint || agentTypeIsWinlogBeat || datasetIncludesSysmon;
const hasProcessEntityId =
processEntityIds != null && processEntityIds.length === 1 && firstProcessEntityId !== '';
return isEndpointOrSysmonFromWinlogBeat && hasProcessEntityId;
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ export const supportedSchemas: SupportedSchema[] = [
name: 'process.name',
},
},
{
name: 'sysmonViaFilebeat',
constraints: [
{
field: 'agent.type',
value: 'filebeat',
},
{
field: 'event.dataset',
value: 'windows.sysmon_operational',
},
],
schema: {
id: 'process.entity_id',
parent: 'process.parent.entity_id',
name: 'process.name',
},
},
];

export function getFieldAsString(doc: unknown, field: string): string | undefined {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export class EventsQuery extends BaseResolverQuery {
return {
body: this.query(filters),
index: this.indexPatterns,
allow_partial_search_results: true,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('Pagination', () => {
const builder = PaginationBuilder.createBuilder(100);
expect(builder.buildQueryFields('a', 'desc').sort).toStrictEqual([
{ '@timestamp': 'desc' },
{ a: 'asc' },
{ a: { order: 'asc', unmapped_type: 'long' } },
]);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type SortFields = [
{
'@timestamp': string;
},
{ [x: string]: string }
{ [x: string]: { order: string; unmapped_type?: string } }
];

/**
Expand Down Expand Up @@ -177,7 +177,10 @@ export class PaginationBuilder {
tiebreaker: string,
timeSort: TimeSortDirection = 'asc'
): PaginationFields {
const sort: SortFields = [{ '@timestamp': timeSort }, { [tiebreaker]: 'asc' }];
const sort: SortFields = [
{ '@timestamp': timeSort },
{ [tiebreaker]: { order: 'asc', unmapped_type: 'long' } },
];
let searchAfter: SearchAfterFields | undefined;
if (this.timestamp && this.eventID) {
searchAfter = [this.timestamp, this.eventID];
Expand Down

0 comments on commit a9313ee

Please sign in to comment.