Query Details

Azure Activity with Federated Credentials outside of GitHub Workflow activity

Fed Cred Az Activity Without Sign In Workflow

Query

// Workflow runs and sign-ins from GitHub
let GitHubFederated = _GetWatchlist('GitHubFederatedCredentials');
let GitHubEvents = GitHubFederated
| extend ServicePrincipalId = tostring(ServicePrincipalId)
| extend GitHubOrganization = tostring(split(Repo, "/")[0])
| extend GitHubRepository = tostring(split(Repo, "/")[1])
| extend FedCredSubjectIdentifier = SubjectIdentifier
| join kind=inner (
AADServicePrincipalSignInLogs
| where ServicePrincipalCredentialKeyId == "00000000-0000-0000-0000-000000000000"
)on $left.ServicePrincipalId == $right.ServicePrincipalId
| project AADSignInTime = TimeGenerated, AADCorrelationId = CorrelationId, IPAddress, ServicePrincipalResource = ResourceDisplayName, AADSignInLocation = Location, ServicePrincipalId, ServicePrincipalCredentialKeyId, AADSignInResult = ResultType, AADTokenId = UniqueTokenIdentifier, FedCredSubjectIdentifier = SubjectIdentifier, GitHubRepoName = Repo
| extend GitHubOrganization = tostring(split(GitHubRepoName, "/")[0])
| extend GitHubRepository = tostring(split(GitHubRepoName, "/")[1])
| join kind=inner (
    GitHubAuditLogPolling_CL
    | where action_s == "workflows.completed_workflow_run"
    | project GitHubRepoName = repo_s, WorkflowRunId = workflow_run_id_d, WorkflowName = name_s, WorkflowActor = actor_s, WorkflowStartedTime = started_at_t, WorkflowCompletedTime = completed_at_t, WorkflowConslusion = conclusion_s
    ) on $left.GitHubRepoName == $right.GitHubRepoName
| where AADSignInTime between (todatetime(WorkflowStartedTime) .. todatetime(WorkflowCompletedTime));
// Azure Activities from Federated Credentials 
GitHubFederated
| extend ServicePrincipalId = tostring(ServicePrincipalId)
| join kind=inner (
AzureActivity
| extend AzClaims = parse_json(Claims_d)
| extend AzObjProp = parse_json(Properties_d)
| extend AzResourceId = tostring(AzObjProp.entity)
| extend AzActivityResource = tostring(AzClaims.aud)
| project AzCorrelationId = CorrelationId, AzTimeStamp = TimeGenerated, AzIpAddress = CallerIpAddress, AzSpId = Caller, AzClaims = parse_json(Claims_d), AzObjProp = parse_json(Properties_d), AzResourceId = tostring(AzObjProp.entity), AzActivityResource = tostring(AzClaims.aud)
)on $left.ServicePrincipalId == $right.AzSpId
| join kind=leftouter GitHubEvents on $left.AzSpId == $right.ServicePrincipalId, $left.AzIpAddress == $right.IPAddress
| where isempty(WorkflowStartedTime) or AzTimeStamp !between (WorkflowStartedTime .. WorkflowCompletedTime)  
| project AzResourceId, AzSpId, ServicePrincipalId, ServicePrincipalName, AzIpAddress, IPAddress, WorkflowStartedTime, WorkflowCompletedTime, AzTimeStamp
| extend timestamp = AzTimeStamp, AccountCustomEntity = ServicePrincipalName, IPCustomEntity = AzIpAddress

Explanation

This query is designed to detect potentially suspicious activity involving Azure Service Principals with Federated Credentials. Here's a simplified breakdown of what it does:

  1. Purpose: The query identifies instances where a Service Principal with Federated Credentials is used for Azure management activities, but there is no corresponding GitHub workflow or sign-in event recorded during the same time frame.

  2. Data Sources:

    • It uses a watchlist named GitHubFederatedCredentials to identify relevant Service Principals.
    • It checks Azure Active Directory (AAD) sign-in logs and GitHub audit logs for workflow activities.
  3. Process:

    • It first gathers data on GitHub workflow runs and sign-ins associated with the Service Principals.
    • It then collects Azure activities performed by these Service Principals.
    • The query looks for Azure activities that do not have a matching GitHub workflow event or sign-in within the same time window.
  4. Alert Trigger:

    • An alert is triggered if there are any such unmatched Azure activities, indicating potential unauthorized or unexpected use of the Service Principal.
  5. Frequency: The query runs every 4 hours, checking the past 4 hours of activity.

  6. Severity: The severity of the alert is set to "Medium," suggesting that while the activity is suspicious, it may not be immediately critical.

  7. Tactics and Techniques:

    • The query is associated with tactics like Persistence and Impact, and techniques such as T1098 (Account Manipulation) and T1496 (Resource Hijacking).
  8. Entity Mappings:

    • The query maps detected entities to account, IP, and Azure resource entities for further investigation.

In summary, this query helps in monitoring and identifying potentially unauthorized use of Azure Service Principals with Federated Credentials, especially when such usage is not accompanied by expected GitHub workflow activities.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: February 9, 2024

Tables

AADServicePrincipalSignInLogsGitHubAuditLogPolling_CLAzureActivity

Keywords

AzureActivityFederatedCredentialsGitHubWorkflowServicePrincipalSignInLogsAuditLogPollingClaimsPropertiesResourceDisplayNameLocationResultTypeUniqueTokenIdentifierRepoActorConclusionCorrelationIdTimeGeneratedCallerIpAddressEntityAccountCustom

Operators

letextendtostringsplitjoinonprojectwherebetweentodatetimeparse_jsonisempty!betweenorkind=innerkind=leftouter$left$right

Severity

Medium

Tactics

PersistenceImpact

MITRE Techniques

Frequency: 4h

Period: 4h

Actions

GitHub