# Key Eater: Stolen Microsoft Entra ID Application Credentials Used to Breach 27 Organizations

> A campaign tracked as 'Key Eater' by Todyl MXDR uses stolen Microsoft Entra ID application (service principal) secrets, an Azure DevOps federated workload identity and replayed session tokens to access Microsoft 365 and Azure resources of MSPs and their downstream customers, reaching 27 organizations. No Microsoft vulnerability is exploited; the operator is unattributed and the original credential-theft mechanism is unknown.

- **Published:** 2026-11-04T20:08:18Z
- **Last reviewed:** 2026-11-04T20:08:18Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5264
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5264.png
- **ID:** TL-2026-5264
- **Severity:** HIGH
- **Category:** CLOUD
- **Status:** ACTIVE
- **Detections:** 9 (1 shown free below) · **IOCs:** 11 (3 shown free below)

## Description

Todyl's MXDR team identified the Key Eater campaign on 2026-11-03 after first observing a compromised application credential being used on 2026-11-01 (08:45 UTC). The operator authenticated directly as service principals using stolen application secrets, which bypasses user-scoped controls such as user-focused Conditional Access, MFA and device checks. Roughly 45 app registrations across about 18 organizations were targeted, with more than 33 successful authentications. Because several applications belonged to MSPs (multi-tenant apps, delegated admin/GDAP and Partner Center access), the blast radius extended to 27 organizations including downstream customers. One multi-tenant MSP application was used to sweep 15 customer tenants in roughly 10-second loops.

Observed tradecraft: for nearly every credential the actor requested an Azure Resource Manager token, then a Key Vault token, frequently followed within seconds by Microsoft Graph, Storage and Cognitive Services tokens. The actor also abused an Azure DevOps federated workload identity (2026-11-01 14:39 UTC) and replayed an Azure DevOps user session token (2026-11-02 10:39 UTC). After establishing access the actor ran 29 single-asterisk (*) wildcard Microsoft Graph searches across about 25 tenants, then downloaded SharePoint files at roughly one per second (81 files) and accessed about 2,279 mailbox items. Targeted content was credential and configuration material: password lists, private keys, VPN profiles, MFA and RMM API keys, backup credentials, firewall configurations, Azure inventories and service-account maps. Four AI-service tokens (3 Cognitive Services, 1 Azure ML) were issued at two MSPs; Todyl assesses possible LLM-jacking with low confidence on mechanism.

Sign-ins were 95% scripted clients (curl, python-requests, Python-urllib) with distinctive user agents task177-f2267/1.0 and sait-tenant-deep/37346, bursts of up to 24 sign-ins in 10 seconds, fixed ~11-second retry loops against disabled or rotated apps, and multi-hour idle gaps. After detection on 2026-11-03 07:57 UTC the actor switched to spoofed (intentionally malformed) browser user agents. Refresh-token replay attempts for multiple users on 2026-11-03 were blocked by Conditional Access. No persistence was observed (no new consents, credentials, roles or users). The primary operator IP 199.19.77.84 (AS203662, Poland-geolocated VPS hosting) made 412 sign-in attempts over 7 days; related IPs show password-spray activity.

Attribution is unresolved. Todyl evaluated and could not confirm links to Storm-0940/ConnectWise Cloud Backup activity (October 2026) or to a trojanized Claude Code extension (2026-10-29); a single operator using scripted, possibly AI-assisted tooling from a VPS is indicated. Activity is not a worm, and additional victims may exist outside monitored environments.

## MITRE ATT&CK

- T1078.004 Cloud Accounts
- T1550.001 Application Access Token
- T1550.004 Web Session Cookie
- T1110.003 Password Spraying
- T1552.001 Credentials In Files
- T1555.006 Cloud Secrets Management Stores
- T1213.002 Sharepoint
- T1114.002 Remote Email Collection
- T1119 Automated Collection
- T1583.003 Virtual Private Server

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**Key Eater — Service Principal Sign-In from Operator IPs, Actor User Agents or Scripted Clients** (`TL-2026-5264-SPL-001`)

Detects Entra ID service principal sign-ins that match Key Eater tradecraft: the actor-unique user agents task177-f2267/1.0 and sait-tenant-deep/37346, the operator IP 199.19.77.84 (AS203662) and related spray IPs 199.19.77.18 and 65.87.223.26, or scripted clients (curl, python-requests, Python-urllib) authenticating as an application with a stolen secret. Direct app-only authentication bypasses user-scoped Conditional Access, MFA and device checks, so the sign-in log is the first place the intrusion is visible.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1078.004, T1583.003
- **Data sources:** azure:monitor:aad ServicePrincipalSignInLogs, AADServicePrincipalSignInLogs, Entra ID sign-in logs
- **Severity:** high
- **Confidence:** high

### Splunk SPL

````spl
index=azure sourcetype="azure:monitor:aad" category=ServicePrincipalSignInLogs
| eval ua='properties.userAgent', src_ip='properties.ipAddress', app_id='properties.appId', app_name='properties.servicePrincipalName', err='properties.status.errorCode' ```Key Eater TL-2026-5264 - flag actor user agents, operator and spray IPs, and scripted clients signing in as service principals```
| eval actor_ua=if(match(ua,"(?i)task177-f2267/1[.]0|sait-tenant-deep/37346"),1,0), ioc_ip=if(match(src_ip,"^(199[.]19[.]77[.]84|199[.]19[.]77[.]18|65[.]87[.]223[.]26)$"),1,0), scripted=if(match(ua,"(?i)^(curl|python-requests|python-urllib)/"),1,0)
| where actor_ua=1 OR ioc_ip=1 OR scripted=1
| stats count AS signins, dc(app_id) AS distinct_apps, values(app_name) AS app_names, values(ua) AS user_agents, values(err) AS error_codes, sum(actor_ua) AS actor_ua_hits, sum(ioc_ip) AS ioc_ip_hits, min(_time) AS first_seen, max(_time) AS last_seen BY src_ip
| where actor_ua_hits>0 OR ioc_ip_hits>0 OR signins>=5
| convert ctime(first_seen) ctime(last_seen)
| sort - signins
````

### Microsoft KQL

```kql
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(24h)
| extend UA = tostring(column_ifexists('UserAgent', ''))
| extend ActorUA = UA contains 'task177-f2267' or UA contains 'sait-tenant-deep',
         IocIP = IPAddress in ('199.19.77.84', '199.19.77.18', '65.87.223.26'),
         ScriptedClient = UA matches regex '(?i)^(curl|python-requests|python-urllib)/'
| where ActorUA or IocIP or ScriptedClient
| summarize SignIns = count(), DistinctApps = dcount(AppId), Apps = make_set(ServicePrincipalName, 20), UserAgents = make_set(UA, 10), ResultTypes = make_set(ResultType, 10), ActorUAHits = countif(ActorUA), IocIPHits = countif(IocIP), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by IPAddress
| where ActorUAHits > 0 or IocIPHits > 0 or SignIns >= 5
| order by SignIns desc
```

### Sigma

```yaml
title: Entra ID Sign-In from Key Eater Operator Infrastructure or Actor User Agent
id: 7b3e1c52-9a4d-4f0e-8c6a-2d1f5e9b3a10
status: experimental
description: Detects Entra ID sign-ins using the Key Eater actor user agents task177-f2267/1.0 or sait-tenant-deep/37346, or originating from the operator IP 199.19.77.84 and related spray IPs 199.19.77.18 and 65.87.223.26
references:
  - https://www.todyl.com/blog/stolen-app-credentials-real-access-an-actor-is-signing-into-entra-id-and-azure-devops-as-your-workloads
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-11-04
tags:
  - attack.initial-access
  - attack.t1078.004
  - attack.resource-development
  - attack.t1583.003
logsource:
  product: azure
  service: signinlogs
detection:
  selection_ua:
    UserAgent|contains:
      - 'task177-f2267/1.0'
      - 'sait-tenant-deep/37346'
  selection_ip:
    IPAddress:
      - '199.19.77.84'
      - '199.19.77.18'
      - '65.87.223.26'
  condition: selection_ua or selection_ip
falsepositives:
  - Shared VPS hosting address space later reassigned to a legitimate tenant
level: high
```

**Known false positives:**

- Legitimate automation or CI/CD jobs that authenticate a service principal with curl or python-requests
- Security scanners or approved red-team activity from hosting IP space

**Tuning notes:** Ship the service principal sign-in log category to Splunk (Splunk Add-on for Microsoft Cloud Services) and adjust index and field names to your ingestion. Allowlist known automation by app_id and egress IP, then raise the signins>=5 threshold if scripted-client noise is high. The actor user agent and IP hits are the high-fidelity signals; curl/8.5.0, python-requests/2.34.2 and Python-urllib/3.12 are low-distinctiveness and should only be paired with hosting-provider IPs or AS203662.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Key Eater — Invalid Secret Failures Followed by Success and Azure CLI Password Spray (locked: unlock with TL Creds)
- Key Eater — Bulk Mailbox Access and Wildcard Microsoft Graph Search (locked: unlock with TL Creds)
- Key Eater — Key Vault Secret and Key Enumeration by Scripted or Operator Source (locked: unlock with TL Creds)
- Key Eater — Refresh-Token Replay with Scripted Client User Agents (locked: unlock with TL Creds)
- Key Eater — Spoofed Malformed Browser User Agent on Entra ID Sign-In (locked: unlock with TL Creds)
- Key Eater — Microsoft 365 Data Access from Operator or Spray IP Addresses (locked: unlock with TL Creds)
- Key Eater — Bulk SharePoint Download Burst of Credential and Configuration Files (locked: unlock with TL Creds)
- Key Eater — Service Principal Token Chain ARM, Key Vault, Graph, Storage and AI Services (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 11)

Defanged, TLP:CLEAR.

- IP address: `199.19.77[.]84`
- IP address: `199.19.77[.]18`
- IP address: `65.87.223[.]26`

Full set of 11 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [Hackers Use Stolen Microsoft Entra ID App Credentials to Breach 27 Organizations and Steal Sensitive Data](https://gbhackers.com/hackers-use-stolen-microsoft-entra-id-app-credentials/)
- [Todyl: Stolen app credentials, real access - an actor is signing into Entra ID and Azure DevOps as your workloads](https://www.todyl.com/blog/stolen-app-credentials-real-access-an-actor-is-signing-into-entra-id-and-azure-devops-as-your-workloads)
- [Microsoft Learn: Security best practices for application registration](https://learn.microsoft.com/en-us/entra/identity-platform/security-best-practices-for-app-registration)
- [Microsoft Learn: Migrate applications from secrets to certificates/federation](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/migrate-applications-from-secrets)
- [Tenable: Application Allowing Multi-Tenant Authentication (Entra indicator of exposure)](https://tenable.com/indicators/ioe/entra/APPLICATION-ALLOWING-MULTI-TENANT-AUTHENTICATION)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5264
