Query Details

Exposed Tokens Overview Of Token Artifcats

Query

// Overview of detected token artifacts by Exposure Management
// Hunting query to get list of PRT, Session Cookies and CLI authentication artifacts
// with details of endpoint security posture.

let PrimaryRefresh = ExposureGraphEdges
    | where EdgeLabel == @"has credentials of"
    | join kind = inner (
        ExposureGraphNodes
        | project NodeId, RawData = parse_json(NodeProperties)["rawData"], EntityIds
    ) on $left.SourceNodeId == $right.NodeId
    | where parse_json(EdgeProperties)["rawData"]["primaryRefreshToken"]["primaryRefreshToken"] == 'true'
    | extend TokenType = tostring(parse_json(EdgeProperties)["rawData"]["primaryRefreshToken"]["type"])
    | project EdgeId, SourceNodeId, SourceNodeName, SourceNodeLabel, EdgeLabel, TargetNodeId, TargetNodeName, TokenType, RawData, EntityIds;
let SessionCookie = ExposureGraphNodes
    // Accessing Azure Portal from this device as secondary user (seperated profile)
    | where NodeLabel == "entra-userCookie"
    | extend AccountObjectId = tostring(parse_json(NodeProperties)["rawData"]["entraCookiesSecretData"]["entraObjectId"])
    | join kind=inner ( ExposureGraphNodes
        | extend AccountObjectId = tostring(parse_json(NodeProperties)["rawData"]["accountObjectId"])
        | project UserNodeId = NodeId, UserNodeName = NodeName, AccountObjectId
    ) on AccountObjectId
    | join kind=inner ( 
        ExposureGraphEdges
        ) on $left.NodeId == $right.TargetNodeId
    | extend TokenType = tostring(parse_json(NodeProperties)["rawData"]["entraCookiesSecretData"]["type"])
    | project EdgeId, SourceNodeId, SourceNodeName, SourceNodeLabel, EdgeLabel, TargetNodeId = UserNodeId, TargetNodeName = UserNodeName, TokenType, TokenNodeId = TargetNodeId, TokenNodeName = TargetNodeName, RawData = parse_json(NodeProperties)["rawData"], EntityIds;
let AzureCliToken = ExposureGraphNodes
    // RT and AT in Azure CLI e.g., privileged account not primary user but will be used on this device
    | where NodeLabel == "user-azure-cli-secret"
    | extend AccountSid = tostring(parse_json(NodeProperties)["rawData"]["userAzureCliSecretData"]["userSid"])
    | join kind=inner ( ExposureGraphNodes
        | extend AccountSid = tostring(parse_json(NodeProperties)["rawData"]["aadSid"])
        | project UserNodeId = NodeId, UserNodeName = NodeName, AccountSid
    ) on AccountSid
    | join kind=inner ( 
        ExposureGraphEdges
        ) on $left.NodeId == $right.TargetNodeId
    | extend TokenType = tostring(parse_json(NodeProperties)["rawData"]["userAzureCliSecretData"]["type"])
    | project EdgeId, SourceNodeId, SourceNodeName, SourceNodeLabel, EdgeLabel, TargetNodeId = UserNodeId, TargetNodeName = UserNodeName, TokenType, TokenNodeId = TargetNodeId, TokenNodeName = TargetNodeName, RawData = parse_json(NodeProperties)["rawData"];
union PrimaryRefresh, SessionCookie, AzureCliToken
// Enrichment to MDE insights
| mv-apply EntityIds = parse_json(EntityIds) on (
    where EntityIds.type =~ "DeviceInventoryId"
    | extend DeviceId = tostring(EntityIds.id)
)
| extend HighRiskVulnerability = iff(parse_json(RawData)["highRiskVulnerabilityInsights"]["hasHighOrCritical"] == 'true', true, false)
| extend CredentialGuard = iff(parse_json(RawData)["hasGuardMisconfigurations"] has 'Credential Guard', false, true)
| summarize TokenArtifacts = make_list(TokenType) by
        User = TargetNodeName,
        Device = SourceNodeName,
        DeviceId,
        PublicIP = tostring(parse_json(RawData)["publicIP"]),
        ExposureScore = tostring(parse_json(RawData)["exposureScore"]),
        RiskScore = tostring(parse_json(RawData)["riskScore"]),
        HighRiskOrCriticalVulnerability = tostring(HighRiskVulnerability),
        MaxCvssScore = tostring(parse_json(RawData)["highRiskVulnerabilityInsights"]["maxCvssScore"]),
        AllowedRDP = tostring(parse_json(RawData)["rdpStatus"]["allowConnections"]),
        CredentialGuard = tostring(CredentialGuard),
        TpmActivated = tostring(parse_json(RawData)["tpmData"]["activated"])
| join kind = leftouter ( AlertEvidence
    | where isnotempty(DeviceId)
    | summarize Alerts = make_set(Title), AlertCategories = make_set(Categories) by DeviceId
) on DeviceId
| project-away DeviceId1

Explanation

This query is designed to provide an overview of detected token artifacts related to security exposure management. It focuses on identifying and detailing three types of authentication artifacts: Primary Refresh Tokens (PRT), Session Cookies, and Azure CLI tokens. Here's a simplified breakdown of what the query does:

  1. Primary Refresh Tokens (PRT):

    • It identifies nodes in the exposure graph that have credentials labeled as "primaryRefreshToken."
    • It extracts details about these tokens, including their type and associated raw data.
  2. Session Cookies:

    • It identifies nodes labeled as "entra-userCookie," which represent session cookies used for accessing Azure Portal.
    • It joins these nodes with user nodes based on account object IDs to gather more information about the user associated with the session cookie.
  3. Azure CLI Tokens:

    • It identifies nodes labeled as "user-azure-cli-secret," which represent tokens used in Azure CLI.
    • It joins these nodes with user nodes based on account SIDs to gather more information about the user associated with the Azure CLI token.
  4. Combining Results:

    • The results from the three types of tokens are combined into a single dataset.
  5. Enrichment with Device Insights:

    • The query enriches the data with additional security insights from Microsoft Defender for Endpoint (MDE).
    • It checks for high-risk vulnerabilities, Credential Guard status, and other security configurations.
  6. Summarization:

    • It summarizes the data by listing the types of tokens detected for each user and device.
    • It includes additional details such as public IP, exposure score, risk score, and security configurations.
  7. Alert Integration:

    • It joins the summarized data with alert evidence to include any relevant security alerts associated with the devices.

The final output provides a comprehensive view of token artifacts and their associated security posture, helping security teams assess potential risks and vulnerabilities.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: March 5, 2025

Tables

ExposureGraphEdgesExposureGraphNodesAlertEvidence

Keywords

ExposureManagementDevicesUserAzurePortalAzureCLISecurityVulnerabilityInsights

Operators

letwherejoinonparse_jsonextendtostringprojectunionmv-applyiffhassummarizemake_listmake_setby=~isnotemptyproject-away

Actions