From 6fdef8e970e956e034bb2ed4f3367c34084fd981 Mon Sep 17 00:00:00 2001 From: JocLRojas Date: Wed, 5 Aug 2026 17:34:28 +0300 Subject: [PATCH] feat(filters): update bitdefender_gz, azure-eventhub and windows-events filters --- filters/antivirus/bitdefender_gz.yml | 391 +++++++++++++++++++++++++-- filters/azure/azure-eventhub.yml | 236 +++++++++++++++- filters/windows/windows-events.yml | 15 + 3 files changed, 609 insertions(+), 33 deletions(-) diff --git a/filters/antivirus/bitdefender_gz.yml b/filters/antivirus/bitdefender_gz.yml index aed53eab5..bc73922ea 100644 --- a/filters/antivirus/bitdefender_gz.yml +++ b/filters/antivirus/bitdefender_gz.yml @@ -1,4 +1,4 @@ -# Bitdefender GravityZone filter, version 3.0.2 +# Bitdefender GravityZone filter, version 3.1.0 # Based on https://www.bitdefender.com/business/support/en/77212-237089-event-types.html # and the previous version of the same filter @@ -128,7 +128,8 @@ pipeline: pattern: '{{.greedy}}' source: log.restData - # Using grok to parse kv issued fields with space + # ---- CEF-aware extraction of space-bearing extension values ---- + - grok: patterns: - fieldName: log.2trash @@ -139,6 +140,23 @@ pipeline: pattern: '{{.greedy}}' source: log.restData + - grok: + patterns: + - fieldName: log.dvcFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.dvcToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}dvc=' + - fieldName: log.dvcFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.dvcFull")' + - grok: patterns: - fieldName: log.2trash @@ -149,24 +167,239 @@ pipeline: pattern: '{{.greedy}}' source: log.restData - # Applying grok to remove unnecessary data - grok: patterns: - - fieldName: log.deviceIps + - fieldName: log.requestFull pattern: '{{.greedy}}{{.space}}' - fieldName: log.irrelevant pattern: '{{.greedy}}' - source: log.dvcToParse + source: log.requestToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}request=' + - fieldName: log.requestFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.requestFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}act=' + - fieldName: log.actToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData - grok: patterns: - - fieldName: log.requested + - fieldName: log.actFull pattern: '{{.greedy}}{{.space}}' - fieldName: log.irrelevant pattern: '{{.greedy}}' - source: log.requestToParse + source: log.actToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}act=' + - fieldName: log.actFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.actFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}sproc=' + - fieldName: log.sprocToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.sprocFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.sprocToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}sproc=' + - fieldName: log.sprocFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.sprocFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}filePath=' + - fieldName: log.filePathToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.filePathFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.filePathToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}filePath=' + - fieldName: log.filePathFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.filePathFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZDetectionName=' + - fieldName: log.BitdefenderGZDetectionNameToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.BitdefenderGZDetectionNameFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.BitdefenderGZDetectionNameToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZDetectionName=' + - fieldName: log.BitdefenderGZDetectionNameFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.BitdefenderGZDetectionNameFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZAttackTypes=' + - fieldName: log.BitdefenderGZAttackTypesToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.BitdefenderGZAttackTypesFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.BitdefenderGZAttackTypesToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZAttackTypes=' + - fieldName: log.BitdefenderGZAttackTypesFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.BitdefenderGZAttackTypesFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}suser=' + - fieldName: log.suserToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.suserFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.suserToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}suser=' + - fieldName: log.suserFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.suserFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}fname=' + - fieldName: log.fnameToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.fnameFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.fnameToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}fname=' + - fieldName: log.fnameFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.fnameFull")' + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZMalwareName=' + - fieldName: log.BitdefenderGZMalwareNameToParse + pattern: '{{.data}}{{.word}}\=' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.restData + + - grok: + patterns: + - fieldName: log.BitdefenderGZMalwareNameFull + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.irrelevant + pattern: '{{.greedy}}' + source: log.BitdefenderGZMalwareNameToParse + + - grok: + patterns: + - fieldName: log.2trash + pattern: '{{.data}}BitdefenderGZMalwareName=' + - fieldName: log.BitdefenderGZMalwareNameFull + pattern: '{{.greedy}}' + source: log.restData + where: '!exists("log.BitdefenderGZMalwareNameFull")' - # Using the kv filter with default config, usefull in key-value logs - kv: fieldSplit: " " valueSplit: "=" @@ -181,12 +414,13 @@ pipeline: - rename: from: - log.src - to: origin.ip + to: target.ip - rename: from: - - log.deviceIps - to: origin.ip + - log.dvcFull + to: target.ip + where: '!exists("target.ip")' - rename: from: @@ -195,19 +429,30 @@ pipeline: - rename: from: - - log.sproc - to: target.path + - log.sprocFull + to: target.process - rename: from: - - log.filePath - to: origin.path + - log.filePathFull + to: target.path - rename: from: - - log.act + - log.actFull + - log.BitdefenderGZMainAction to: action + - rename: + from: + - log.BitdefenderGZDetectionNameFull + to: log.BitdefenderGZDetectionName + + - rename: + from: + - log.BitdefenderGZAttackTypesFull + to: log.BitdefenderGZAttackTypes + # Removing unnecessary characters - trim: function: prefix @@ -250,6 +495,89 @@ pipeline: fields: - log.processPid + - rename: + from: + - log.start + - log.end + - log.BitdefenderGZDetectionTime + to: deviceTime + + - rename: + from: + - log.severity + to: severity + + - rename: + from: + - log.BitdefenderGZComputerFQDN + to: target.domain + + - rename: + from: + - log.suserFull + to: target.user + + - rename: + from: + - log.BitdefenderGZMalwareNameFull + to: target.malware + + - rename: + from: + - log.BitdefenderGZMalwareType + to: target.malwareType + + - rename: + from: + - log.BitdefenderGZMalwareHash + - log.BitdefenderGZFileHashSha256 + to: target.sha256 + + - rename: + from: + - log.fileHash + to: target.md5 + + - rename: + from: + - log.fnameFull + to: target.filename + + - rename: + from: + - log.requestFull + to: origin.url + + - rename: + from: + - log.BitdefenderGZDetectionLocalPort + to: target.port + + - rename: + from: + - log.BitdefenderGZDetectionAttackerIp + to: origin.ip + + - rename: + from: + - log.BitdefenderGZEventSourceIP + to: origin.ip + + # Adding actionResult field to indicate whether the action was successful or failed + - add: + function: string + params: + key: actionResult + value: success + where: 'oneOf("action", ["blocked", "block", "aph_blocked", "portscan_blocked", "deleted", "disinfected", "quarantined", "restored"])' + + - add: + function: string + params: + key: actionResult + value: failed + where: 'oneOf("action", ["still present", "ignored", "no action", "reportOnly"])' + # Adding geolocation to origin ip - dynamic: plugin: com.utmstack.geolocation @@ -262,29 +590,34 @@ pipeline: - cast: fields: - origin.port + - target.port to: int - # Adding action result - - add: - function: string - params: - key: actionResult - value: "blocked" - where: 'oneOf("action", ["blocked", "quarantined", "deleted", "disinfected"])' - - # Removing unused fields + # Removing unused fields. - delete: fields: - log.0trash - log.1trash - log.2trash + - log.3trash - log.restData - log.irrelevant - - log.spt - - log.src + - log.cefVersion + - log.dvcFull + - log.dvcToParse + - log.requestToParse + - log.actToParse + - log.sprocToParse + - log.filePathToParse + - log.fnameToParse + - log.BitdefenderGZDetectionNameToParse + - log.BitdefenderGZMalwareNameToParse + - log.BitdefenderGZAttackTypesToParse + - log.suserToParse + - log.act - log.sproc - log.filePath - log.dvc - log.request - - log.dvcToParse - - log.cefVersion \ No newline at end of file + - log.suser + - log.fname \ No newline at end of file diff --git a/filters/azure/azure-eventhub.yml b/filters/azure/azure-eventhub.yml index e11dcc129..460c25a22 100644 --- a/filters/azure/azure-eventhub.yml +++ b/filters/azure/azure-eventhub.yml @@ -1,11 +1,13 @@ -# Azure Envent-Hub filter, version 2.0.6 -# +# Azure Event-Hub filter, version 2.0.7 +# # Documentations # 1- https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/activity-log # 2- https://learn.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-schema +# 3- https://learn.microsoft.com/en-us/azure/event-grid/event-schema-subscriptions +# 4- https://learn.microsoft.com/en-us/azure/event-grid/system-topics +# pipeline: - - dataTypes: - - azure + - dataTypes: azure steps: - json: source: raw @@ -816,6 +818,232 @@ pipeline: - log.properties.userAgent to: log.propertiesUserAgent + # .......................................................................# + # ===== EVENT GRID SCHEMA ===== # + # # + # Handles Azure Event Grid System Topic payloads (schema: # + # https://learn.microsoft.com/en-us/azure/event-grid/event-schema-subscriptions). + # .......................................................................# + + - rename: + from: + - log.data.httpRequest.clientIpAddress + - log.data.claims.ipaddr + to: origin.ip + where: '!exists("origin.ip") && (exists("log.data.httpRequest.clientIpAddress") || exists("log.data.claims.ipaddr"))' + + - rename: + from: + - log.data.httpRequest.url + to: target.url + where: '!exists("target.url") && exists("log.data.httpRequest.url")' + + - rename: + from: + - log.data.httpRequest.method + to: log.propertiesRequestMethod + where: '!exists("log.propertiesRequestMethod") && exists("log.data.httpRequest.method")' + + - rename: + from: + - log.data.claims.upn + to: origin.user + where: '!exists("origin.user") && exists("log.data.claims.upn")' + + - rename: + from: + - log.data.claims.name + to: origin.user + where: '!exists("origin.user") && exists("log.data.claims.name")' + + - rename: + from: + - log.data.authorization.evidence.role + to: origin.group + where: '!exists("origin.group") && exists("log.data.authorization.evidence.role")' + + - rename: + from: + - log.data.correlationId + to: log.correlationId + where: '!exists("log.correlationId") && exists("log.data.correlationId")' + + - rename: + from: + - log.data.operationName + to: log.operationName + where: '!exists("log.operationName") && exists("log.data.operationName")' + + - rename: + from: + - log.data.authorization.action + to: log.authorizationAction + where: exists("log.data.authorization.action") + + - rename: + from: + - log.data.authorization.scope + to: log.authorizationScope + where: exists("log.data.authorization.scope") + + - rename: + from: + - log.data.authorization.evidence.principalId + to: log.principalId + where: exists("log.data.authorization.evidence.principalId") + + - rename: + from: + - log.data.authorization.evidence.principalType + to: log.principalType + where: exists("log.data.authorization.evidence.principalType") + + - rename: + from: + - log.data.authorization.evidence.roleAssignmentId + to: log.roleAssignmentId + where: exists("log.data.authorization.evidence.roleAssignmentId") + + - rename: + from: + - log.data.authorization.evidence.roleAssignmentScope + to: log.roleAssignmentScope + where: exists("log.data.authorization.evidence.roleAssignmentScope") + + - rename: + from: + - log.data.authorization.evidence.roleDefinitionId + to: log.roleDefinitionId + where: exists("log.data.authorization.evidence.roleDefinitionId") + + - rename: + from: + - log.data.resourceProvider + to: log.resourceProvider + where: exists("log.data.resourceProvider") + + - rename: + from: + - log.data.resourceUri + to: log.resourceUri + where: exists("log.data.resourceUri") + + - rename: + from: + - log.data.subscriptionId + to: log.subscriptionId + where: exists("log.data.subscriptionId") + + - rename: + from: + - log.data.tenantId + to: log.aadTenantId + where: '!exists("log.aadTenantId") && exists("log.data.tenantId")' + + - rename: + from: + - log.data.httpRequest.clientRequestId + to: log.clientRequestId + where: exists("log.data.httpRequest.clientRequestId") + + - rename: + from: + - log.eventType + to: log.eventGridEventType + where: exists("log.eventType") + + - rename: + from: + - log.subject + to: log.eventGridSubject + where: exists("log.subject") + + - rename: + from: + - log.topic + to: log.eventGridTopic + where: exists("log.topic") + + - rename: + from: + - log.dataVersion + to: log.eventGridDataVersion + where: exists("log.dataVersion") + + - rename: + from: + - log.metadataVersion + to: log.eventGridMetadataVersion + where: exists("log.metadataVersion") + + - add: + function: 'string' + params: + key: actionResult + value: 'success' + where: '!exists("actionResult") && equalsIgnoreCase("log.data.status", "Succeeded")' + + - add: + function: 'string' + params: + key: actionResult + value: 'failed' + where: '!exists("actionResult") && equalsIgnoreCase("log.data.status", "Failed")' + + - add: + function: 'string' + params: + key: actionResult + value: 'success' + where: '!exists("actionResult") && endsWith("log.eventGridEventType", "Success")' + + - add: + function: 'string' + params: + key: actionResult + value: 'failed' + where: '!exists("actionResult") && endsWith("log.eventGridEventType", "Failure")' + + - add: + function: 'string' + params: + key: actionResult + value: 'blocked' + where: '!exists("actionResult") && endsWith("log.eventGridEventType", "Cancel")' + + - add: + function: 'string' + params: + key: severity + value: 'medium' + where: '!exists("severity") && oneOf("actionResult", ["failed", "blocked"])' + + - rename: + from: + - log.data.status + to: log.eventGridStatus + where: exists("log.data.status") + + - delete: + fields: + - log.data.claims.aio + - log.data.claims.acrs + - log.data.claims.appidacr + - log.data.claims.aud + - log.data.claims.exp + - log.data.claims.iat + - log.data.claims.iss + - log.data.claims.nbf + - log.data.claims.puid + - log.data.claims.rh + - log.data.claims.uti + - log.data.claims.ver + - log.data.claims.xms_act_fct + - log.data.claims.xms_ftd + - log.data.claims.xms_idrel + - log.data.claims.xms_sub_fct + - log.data.claims.xms_tcdt + # Adding action result - add: function: 'string' diff --git a/filters/windows/windows-events.yml b/filters/windows/windows-events.yml index 07050d7bd..1cea949aa 100644 --- a/filters/windows/windows-events.yml +++ b/filters/windows/windows-events.yml @@ -224,6 +224,21 @@ pipeline: - log.data.TargetUserSid to: log.eventDataTargetUserSid + - rename: + from: + - log.data.TargetSid + to: log.eventDataTargetSid + + - rename: + from: + - log.data.CallerProcessId + to: log.eventDataCallerProcessId + + - rename: + from: + - log.data.CallerProcessName + to: log.eventDataCallerProcessName + - rename: from: - log.data.TransmittedServices