Detection rules › Kusto

SAP BTP - Cloud Integration access policy tampering

Status
available
Severity
high
Time window
15m
Source
github.com/Azure/Azure-Sentinel

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

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 =
ifaction == "Create""created"
elifaction == "Change""modified"
elifaction == "Delete""deleted"
elseaction

Stage 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 =
ifobjectType == "Access Policy"strcat("Access policy '", objectId, "' was ", normalizedAction)
elifobjectType == "Artifact Reference"strcat("Artifact reference '", objectId, "' was ", normalizedAction)
elsestrcat(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.

FieldKindValuesSearch
Categoryeq
  • audit.security-events
field:"Category" kind:eq value:"audit.security-events"
actionin
  • Change
  • Create
  • Delete
field:"action" kind:in
objectTypein
  • Access Policy
  • Artifact Reference
field:"objectType" kind:in

Output fields

These fields are emitted when the rule matches.

FieldSource
Actionproject
CloudAppproject
MessageTextproject
ObjectIdproject
ObjectTypeproject
PolicyMessageproject
Tenantproject
UpdatedOnproject
UserNameproject
ipAddressproject
AccountNameextend
UPNSuffixextend