Detection rules › Kusto
1Password - Non-privileged vault user permission change
This will alert when user permissions have changed within a non-privileged vault which have been implemented by an actor that was not the target user account. Once this analytics rule is triggered it will group all related future alerts for upto an hour when all related entities are the same. Ref: https://1password.com/ Ref: https://github.com/securehats/
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| 1Password | any: User vault access (catch-all) |
Rule body
id: 327e0579-7c03-4ec7-acf5-a29dcc4a12b6
name: 1Password - Non-privileged vault user permission change
version: 1.0.0
kind: Scheduled
description: |-
This will alert when user permissions have changed within a non-privileged vault which have been implemented by an actor that was not the target user account. Once this analytics rule is triggered it will group all related future alerts for upto an hour when all related entities are the same.
Ref: https://1password.com/
Ref: https://github.com/securehats/
severity: Medium
requiredDataConnectors:
- connectorId: 1Password
dataTypes:
- OnePasswordEventLogs_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
relevantTechniques:
- T1098
query: |-
let watchlist =
_GetWatchlist("PV1PW")
| project SearchKey
;
// Insert the vault UUIDs below when using the dynamic vaults list within the analytics rule itself
let vaults = dynamic([""]);
OnePasswordEventLogs_CL
| where log_source == "auditevents"
| where action has_any("grant", "revoke", "update")
| where object_type == "uva"
| where tostring(actor_details.email) != tostring(aux_details.email)
// Enable the line below when using the "Privileged Vaults - 1PW" watchlist
| where object_uuid !in (watchlist)
// Enable the line below when using the dynamic vaults list within the analytics rule itself
// | where object_uuid !in (vaults)
| extend
TargetUsername = aux_details.email
, ActorUsername = actor_details.email
, SrcIpAddr = session.ip
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1h
matchingMethod: AllEntities
suppressionDuration: 5h
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: ActorUsername
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetUsername
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
Stages and Predicates
Parameters
let vaults = dynamic([""]);
Let binding: watchlist
let watchlist = _GetWatchlist("PV1PW")
| project SearchKey;
Stage 1: source
OnePasswordEventLogs_CL
Stage 2: where
| where log_source == "auditevents"
Stage 3: where
| where action has_any("grant", "revoke", "update")
Stage 4: where
| where object_type == "uva"
Stage 5: where
| where tostring(actor_details.email) != tostring(aux_details.email)
Stage 6: where
| where object_uuid !in (watchlist)
Stage 7: extend
| extend
TargetUsername = aux_details.email
, ActorUsername = actor_details.email
, SrcIpAddr = session.ip
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
object_uuid | eq | watchlist | excludes:object_uuid field:"object_uuid" value:"watchlist" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | match |
| field:"action" kind:match |
log_source | eq |
| field:"log_source" kind:eq value:"auditevents" |
object_type | eq |
| field:"object_type" kind:eq value:"uva" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActorUsername | extend |
SrcIpAddr | extend |
TargetUsername | extend |