Skip to content

[New Rule] Entra ID device-bound PRT cookie replay from unusual IP - #6706

Merged
terrancedejesus merged 10 commits into
mainfrom
rule-entra-prt-browsercore
Sep 10, 2026
Merged

[New Rule] Entra ID device-bound PRT cookie replay from unusual IP#6706
terrancedejesus merged 10 commits into
mainfrom
rule-entra-prt-browsercore

Conversation

@terrancedejesus

@terrancedejesus terrancedejesus commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

related: #6705

Two Entra ID sign-in rules for PRT cookie replay (PRTremote / TokenTactics style): a stolen WAM PRT is redeemed off-box with a first-party FOCI tooling client, while the token keeps the workstation deviceid so compliant-device CA can still succeed.

  • Entra ID Device-Bound PRT Replay via First-Party App from Unusual IP - ES|QL join: Windows Sign-In / WAM IPs vs Azure CLI, PowerShell, VS Code, Graph CLI, Azure AD PowerShell, or Visual Studio redeeming a PRT for Graph / SharePoint / Exchange from an IP that is not on that device session.
  • Entra ID Device-Bound PRT from Unusual Device IP - new terms on (device_id, source.ip) for the same clients, for when Windows Sign-In is outside the correlation window.

Teams, Office, OneDrive SyncEngine, Authentication Broker, Outlook Mobile, Bing, and Azure Portal are omitted (split-tunnel M365 egress). Replay events require is_compliant or is_managed.

Screenshot 2026-08-28 at 12 40 53 PM

Checklist

  • Added a label for the type of pr: Rule: New
  • Secret and sensitive material has been managed correctly

Rule: New

  • Detailed description of the rule
  • Related issues/PRs linked, references included
  • name and description descriptive
  • note includes investigation guide
  • threat mapped to ATT&CK
  • Testing evidence provided

Detect FOCI tooling clients redeeming a stolen workstation PRT off-box, where the token keeps the original deviceid so compliant-device CA can still succeed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@terrancedejesus terrancedejesus added Integration: Azure azure related rules Rule: New Proposal for new rule Domain: Cloud labels Aug 28, 2026
@terrancedejesus terrancedejesus self-assigned this Aug 28, 2026
…sual_ip rule

Removed outdated references from the Azure credential access rule.
Updated minimum stack version to the latest supported for 9.X releases.
@terrancedejesus
terrancedejesus marked this pull request as ready for review August 29, 2026 00:40
Copilot AI lite review requested due to automatic review settings August 29, 2026 00:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds two new Microsoft Entra ID sign-in detection rules intended to identify device-bound PRT (WAM PRT SSO cookie) replay activity (PRTremote/TokenTactics-style), focusing on first-party FOCI tooling clients redeeming PRTs for high-value Microsoft 365 resources from unusual IPs.

Changes:

  • Adds a new-terms (KQL) rule to flag first-seen (device_id, source.ip) pairs for PRT redemptions by selected first-party tooling clients.
  • Adds an ES|QL correlation rule that compares Windows Sign-In / WAM “device session” IPs to replay IPs for the same user+device.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
rules/integrations/azure/credential_access_entra_id_prt_from_unusual_device_ip.toml New-terms rule for first-seen device-bound PRT redemption IPs per device.
rules/integrations/azure/credential_access_entra_id_prt_cookie_replay_unusual_ip.toml ES
Suppressed comments (3)

rules/integrations/azure/credential_access_entra_id_prt_from_unusual_device_ip.toml:94

  • [[rule.threat]] includes the Initial Access tactic (TA0001), but the tags list is missing the corresponding Tactic: Initial Access tag; tags should include one Tactic: entry per tactic in the threat mapping.
    "Data Source: Microsoft Entra ID Sign-in Logs",
    "Platform: Entra ID",
    "Tactic: Credential Access",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
    "Rule Type: New Terms",
]

rules/integrations/azure/credential_access_entra_id_prt_cookie_replay_unusual_ip.toml:100

  • [[rule.threat]] includes the Initial Access tactic (TA0001), but the tags list is missing the corresponding Tactic: Initial Access tag; tags should include one Tactic: entry per tactic in the threat mapping.
    "Platform: Entra ID",
    "Tactic: Credential Access",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
    "Rule Type: ESQL",
]
timestamp_override = "event.ingested"

rules/integrations/azure/credential_access_entra_id_prt_cookie_replay_unusual_ip.toml:109

  • The ES|QL query comment says "find successful sign-in events where a managed device exists", but the filter only checks that device_id is not null (it does not check managed/compliant at that point). This makes the inline query documentation misleading.
// find successful sign-in events where a managed device exists
| where event.dataset == "azure.signinlogs"
    and azure.signinlogs.properties.status.error_code == 0
    and azure.signinlogs.properties.device_detail.device_id is not null


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +2 to +5
creation_date = "2026/08/27"
integration = ["azure"]
maturity = "production"
updated_date = "2026/08/28"
Comment on lines +111 to +135
| eval Esql.is_device_session = azure.signinlogs.properties.app_display_name == "Windows Sign In"
or user_agent.original == "Windows-AzureAD-Authentication-Provider/1.0"

// filter for tooling FOCI clients that can redeem a PRT (replay)
| eval Esql.is_prt_replay = azure.signinlogs.properties.app_id in (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46", // Microsoft Azure CLI
"1950a258-227b-4e31-a9cf-717495945fc2", // Microsoft Azure PowerShell
"aebc6443-996d-45c2-90f0-388ff96faa56", // Visual Studio Code
"14d82eec-204b-4c2f-b7e8-296a70dab67e", // Microsoft Graph Command Line Tools
"1b730954-1685-4b74-9bfd-dac224a7b894", // Azure Active Directory PowerShell
"872cd9fa-d31f-45e0-9eab-6e460a02d1f1" // Visual Studio
)

// target resource are common adversary targets for access
and azure.signinlogs.properties.resource_id in (
"00000003-0000-0000-c000-000000000000", // Microsoft Graph
"00000003-0000-0ff1-ce00-000000000000", // Office 365 SharePoint Online
"6a9b9266-8161-4a7b-913a-a9eda19da220", // OneDrive for Business
"00000002-0000-0ff1-ce00-000000000000" // Office 365 Exchange Online
)
and azure.signinlogs.properties.incoming_token_type == "primaryRefreshToken"
and (
azure.signinlogs.properties.device_detail.is_compliant == true
or azure.signinlogs.properties.device_detail.is_managed == true
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| eval Esql.is_device_session = azure.signinlogs.properties.app_display_name == "Windows Sign In"
or user_agent.original == "Windows-AzureAD-Authentication-Provider/1.0"
// filter for tooling FOCI clients that can redeem a PRT (replay)
| eval Esql.is_prt_replay = azure.signinlogs.properties.app_id in (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46", // Microsoft Azure CLI
"1950a258-227b-4e31-a9cf-717495945fc2", // Microsoft Azure PowerShell
"aebc6443-996d-45c2-90f0-388ff96faa56", // Visual Studio Code
"14d82eec-204b-4c2f-b7e8-296a70dab67e", // Microsoft Graph Command Line Tools
"1b730954-1685-4b74-9bfd-dac224a7b894", // Azure Active Directory PowerShell
"872cd9fa-d31f-45e0-9eab-6e460a02d1f1" // Visual Studio
)
// target resource are common adversary targets for access
and azure.signinlogs.properties.resource_id in (
"00000003-0000-0000-c000-000000000000", // Microsoft Graph
"00000003-0000-0ff1-ce00-000000000000", // Office 365 SharePoint Online
"6a9b9266-8161-4a7b-913a-a9eda19da220", // OneDrive for Business
"00000002-0000-0ff1-ce00-000000000000" // Office 365 Exchange Online
)
and azure.signinlogs.properties.incoming_token_type == "primaryRefreshToken"
and (
azure.signinlogs.properties.device_detail.is_compliant == true
or azure.signinlogs.properties.device_detail.is_managed == true
)
// filter for tooling FOCI clients that can redeem a PRT (replay)
| eval Esql.is_prt_replay = azure.signinlogs.properties.app_id in (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46", // Microsoft Azure CLI
"1950a258-227b-4e31-a9cf-717495945fc2", // Microsoft Azure PowerShell
"aebc6443-996d-45c2-90f0-388ff96faa56", // Visual Studio Code
"14d82eec-204b-4c2f-b7e8-296a70dab67e", // Microsoft Graph Command Line Tools
"1b730954-1685-4b74-9bfd-dac224a7b894", // Azure Active Directory PowerShell
"872cd9fa-d31f-45e0-9eab-6e460a02d1f1" // Visual Studio
)
// target resource are common adversary targets for access
and azure.signinlogs.properties.resource_id in (
"00000003-0000-0000-c000-000000000000", // Microsoft Graph
"00000003-0000-0ff1-ce00-000000000000", // Office 365 SharePoint Online
"6a9b9266-8161-4a7b-913a-a9eda19da220", // OneDrive for Business
"00000002-0000-0ff1-ce00-000000000000" // Office 365 Exchange Online
)
and azure.signinlogs.properties.incoming_token_type == "primaryRefreshToken"
and (
azure.signinlogs.properties.device_detail.is_compliant == true
or azure.signinlogs.properties.device_detail.is_managed == true
)
// device session from Windows Sign-In or WAM, excluding tooling clients so a
// replay cannot vouch for its own source IP
| eval Esql.is_device_session = (
azure.signinlogs.properties.app_display_name == "Windows Sign In"
or user_agent.original == "Windows-AzureAD-Authentication-Provider/1.0"
) and not coalesce(Esql.is_prt_replay, false)

The device-session set doubles as an IP allowlist, and user_agent.original is attacker-controlled. Replaying the cookie with User-Agent: Windows-AzureAD-Authentication-Provider/1.0 makes the event match both is_device_session and is_prt_replay, so the attacker IP lands in source_ip_device_values and the final mv_contains filters it out. One header and the rule never fires. Moving the replay eval first and gating the device-session eval on it closes that, while keeping the on-box exclusion, since a real workstation still populates the device set from its genuine Windows Sign In event.

@bryans3c bryans3c left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One suggestion, LGTM!

@terrancedejesus
terrancedejesus merged commit 784f0c7 into main Sep 10, 2026
12 checks passed
@terrancedejesus
terrancedejesus deleted the rule-entra-prt-browsercore branch September 10, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants