Detection rules › Kusto
SAP BTP - Cloud Integration access policy tampering
Identifies changes to access policies in SAP Cloud Integration. Access policies control authorization for integration artifacts, defining which users and roles can access specific integration flows and related content. Unauthorized access policy manipulation could indicate: - Attacker granting themselves access to sensitive integration artifacts - Removal of security controls to enable further malicious activity - Defense evasion by modifying artifact references to hide unauthorized access
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Defense Impairment |
Rule body
id: 9e6f4b2c-0d3e-5a8f-c9b7-2f5d8a1e4c6b
kind: Scheduled
name: SAP BTP - Cloud Integration access policy tampering
description: |
Identifies changes to access policies in SAP Cloud Integration. Access policies control
authorization for integration artifacts, defining which users and roles can access specific
integration flows and related content.
Unauthorized access policy manipulation could indicate:
- Attacker granting themselves access to sensitive integration artifacts
- Removal of security controls to enable further malicious activity
- Defense evasion by modifying artifact references to hide unauthorized access
severity: High
status: Available
requiredDataConnectors:
- connectorId: SAPBTPAuditEvents
dataTypes:
- SAPBTPAuditLog_CL
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
- PrivilegeEscalation
relevantTechniques:
- T1548
- T1222
query: |
let accessPolicyTypes = dynamic(["Access Policy", "Artifact Reference"]);
let monitoredActions = dynamic(["Create", "Change", "Delete"]);
SAPBTPAuditLog_CL
| where Category == "audit.security-events"
| extend data_s = tostring(Message.data),
ipAddress = tostring(Message.ip)
| extend parsedData = parse_json(data_s)
| extend action = tostring(parsedData.action),
objectType = tostring(parsedData.objectType),
objectId = tostring(parsedData.objectId),
policyMessage = tostring(parsedData.attributes.message)
| where objectType in (accessPolicyTypes)
| where action in (monitoredActions)
| extend normalizedAction = case(
action == "Create", "created",
action == "Change", "modified",
action == "Delete", "deleted",
action
)
| extend MessageText = case(
objectType == "Access Policy", strcat("Access policy '", objectId, "' was ", normalizedAction),
objectType == "Artifact Reference", strcat("Artifact reference '", objectId, "' was ", normalizedAction),
strcat(objectType, " '", objectId, "' was ", normalizedAction)
)
| project
UpdatedOn,
UserName,
MessageText,
ObjectType = objectType,
ObjectId = objectId,
Action = action,
PolicyMessage = policyMessage,
Tenant,
ipAddress,
CloudApp = "SAP Cloud Integration"
| extend AccountName = split(UserName, "@")[0], UPNSuffix = split(UserName, "@")[1]
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ipAddress
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: CloudApp
alertDetailsOverride:
alertDisplayNameFormat: 'SAP Cloud Integration: {{MessageText}}'
alertDescriptionFormat: |
{{MessageText}} by {{UserName}} from IP {{ipAddress}}.
This could indicate:
- Legitimate access policy administration
- Unauthorized privilege escalation attempt
- Attacker modifying security controls to access sensitive integrations
customDetails:
ObjectType: ObjectType
ObjectId: ObjectId
Action: Action
PolicyMessage: PolicyMessage
SourceIP: ipAddress
version: 1.0.1
Stages and Predicates
Parameters
let accessPolicyTypes = dynamic(["Access Policy", "Artifact Reference"]);
let monitoredActions = dynamic(["Create", "Change", "Delete"]);
Stage 1: source
SAPBTPAuditLog_CL
Stage 2: where
| where Category == "audit.security-events"
Stage 3: extend (3 consecutive steps)
| extend data_s = tostring(Message.data),
ipAddress = tostring(Message.ip)
| extend parsedData = parse_json(data_s)
| extend action = tostring(parsedData.action),
objectType = tostring(parsedData.objectType),
objectId = tostring(parsedData.objectId),
policyMessage = tostring(parsedData.attributes.message)
Stage 4: where
| where objectType in (accessPolicyTypes)
Stage 5: where
| where action in (monitoredActions)
Stage 6: extend
| extend normalizedAction = case(
action == "Create", "created",
action == "Change", "modified",
action == "Delete", "deleted",
action
)
normalizedAction =if
action == "Create""created"elif
action == "Change""modified"elif
action == "Delete""deleted"else
actionStage 7: extend
| extend MessageText = case(
objectType == "Access Policy", strcat("Access policy '", objectId, "' was ", normalizedAction),
objectType == "Artifact Reference", strcat("Artifact reference '", objectId, "' was ", normalizedAction),
strcat(objectType, " '", objectId, "' was ", normalizedAction)
)
MessageText =if
objectType == "Access Policy"strcat("Access policy '", objectId, "' was ", normalizedAction)elif
objectType == "Artifact Reference"strcat("Artifact reference '", objectId, "' was ", normalizedAction)else
strcat(objectType, " '", objectId, "' was ", normalizedAction)Stage 8: project
| project
UpdatedOn,
UserName,
MessageText,
ObjectType = objectType,
ObjectId = objectId,
Action = action,
PolicyMessage = policyMessage,
Tenant,
ipAddress,
CloudApp = "SAP Cloud Integration"
Stage 9: extend
| extend AccountName = split(UserName, "@")[0], UPNSuffix = split(UserName, "@")[1]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Category | eq |
| field:"Category" kind:eq value:"audit.security-events" |
action | in |
| field:"action" kind:in |
objectType | in |
| field:"objectType" kind:in |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Action | project |
CloudApp | project |
MessageText | project |
ObjectId | project |
ObjectType | project |
PolicyMessage | project |
Tenant | project |
UpdatedOn | project |
UserName | project |
ipAddress | project |
AccountName | extend |
UPNSuffix | extend |