Detecting Azure Lighthouse Delegation Tampering with Microsoft Sentinel

Detecting Azure Lighthouse Delegation Tampering with Microsoft Sentinel

When Your Window Into the Environment Gets Bricked

Category Azure Lighthouse · Microsoft Sentinel · KQL · MSSP Security

Azure Lighthouse is the backbone of many managed security service providers (MSSPs). It's what lets your SOC team monitor, investigate, and respond across dozens of customer tenants without juggling separate credentials for each one. But that same delegation mechanism is also a quiet, high-impact attack surface, and one that's frequently overlooked in detection engineering.

This post walks through a threat scenario we see in practice, and the two Analytic Rules we built in Microsoft Sentinel to catch it.

Goal: Detect when Azure Lighthouse delegations are created, modified, or deleted in your monitored environment, distinguishing between expected MSP activity and unknown third-party delegation changes, before they become a blind spot.

The Threat Scenario

Imagine this: your team manages security operations for a customer via Azure Lighthouse. Your delegated access covers their Sentinel workspace, their Log Analytics tables, their incident queue. Everything runs through that Lighthouse registration.

Now imagine someone, a rogue admin, a misconfigured automation, a threat actor who's already inside, or even a well-meaning but uninformed customer, modifies or removes that delegation. Your monitoring keeps running, your dashboards stay green, but your service is quietly degraded. You're no longer seeing what you think you're seeing. Alerts aren't firing. Incident response is impaired. And you may not know until something goes badly wrong.

The three actors most likely to trigger this (intentionally or not):

All three scenarios produce the same type of activity in the Azure control plane: a write or delete operation against Microsoft.ManagedServices resources. And all three show up in the AzureActivity table in Microsoft Sentinel.


Detection Architecture

We built two complementary Analytic Rules to cover this threat. They share the same foundation but split on a single key variable: does the change originate from your known Sentinel resource group (your MSP's scope), or from somewhere else?

The Core Technique: Identifying Your Own Sentinel Resource Group

Both rules use a dynamic lookup to identify the resource group containing your Sentinel workspace, rather than hardcoding it. This makes the rules portable and maintenance-free:

let SentinelRG = toscalar(
    Usage
    | where TimeGenerated > ago(1d)
    | where Solution == "LogManagement" and DataType == "SigninLogs"
    | extend ResourceGroup = tolower(split(split(ResourceUri, "/resourcegroups/")[1], "/")[0])
    | where isnotempty(ResourceGroup)
    | summarize any(ResourceGroup)
);

This query looks at recent Usage table entries for your Log Analytics workspace and extracts the resource group name from the ResourceUri. The result (SentinelRG) is then used as a filter in the main query, either to match changes within your scope, or to catch changes outside it.

AzureActivity Usage Microsoft.ManagedServices toscalar()

Detection 1: MSP Delegation Change Detected

What It Detects

Changes to Microsoft.ManagedServices resources (registration definitions and assignments) where the affected resource group matches your known Sentinel resource group. In other words: someone touched your delegation.

This covers both expected changes (your own team onboarding or offboarding a customer) and unexpected ones (a customer admin making unauthorised modifications). The rule fires on both write and delete operations with a successful status.

Why Both Expected and Unexpected?

Even authorised changes from your own MSP should generate an alert, you want a record. Onboarding and offboarding operations should be pre-announced and reconciled against the alert. Anything that doesn't match a known change window is an immediate investigation trigger.

The Query

The full detection query is available to download here.

let SentinelRG = toscalar(
    Usage
    | where TimeGenerated > ago(1d)
    | where Solution == "LogManagement" and DataType == "SigninLogs"
    | extend ResourceGroup = tolower(split(split(ResourceUri, "/resourcegroups/")[1], "/")[0])
    | where isnotempty(ResourceGroup)
    | summarize any(ResourceGroup)
);
AzureActivity
| where TimeGenerated > ago(1h)
| where CategoryValue == "Administrative"
| where ResourceProviderValue =~ "MICROSOFT.MANAGEDSERVICES"
| where isnotempty(ResourceGroup) and
    isnotempty(SentinelRG) and
    tolower(ResourceGroup) == SentinelRG
| extend
    CallerType = tostring(parse_json(Authorization).evidence.principalType),
    Registration = tostring(parse_json(Properties).resource),
    UserName = iff(Caller contains "@", tostring(split(Caller, "@", 0)[0]), Caller),
    UPNSuffix = iff(Caller contains "@", tostring(split(Caller, "@", 1)[0]), Caller)
| project TimeGenerated, OperationNameValue, Status=ActivityStatusValue, Caller, UserName,
    UPNSuffix, CallerIpAddress, CallerType, Registration, ResourceGroup
| sort by TimeGenerated desc

Key Fields in the Output

Field What to Look At
Caller Full UPN or service principal ID, is this your team?
CallerIpAddress Does this IP belong to your management infrastructure?
CallerType Is this a user, service principal, or managed identity?
Registration Which Lighthouse offer / registration was touched?
OperationNameValue Write vs. Delete, deletion is higher severity

Triage Guidance

  1. Cross-reference with your change management process. Was this change scheduled?
  2. Validate the caller identity. A service principal making this change is unusual unless it's part of your automation pipeline.
  3. Check the source IP. Changes from unknown or residential IPs are a red flag.
  4. If the change was a deletion, act immediately. Your delegation may be gone.

Detection 2: Non-MSP Delegation Change Detected

What It Detects

Changes to Microsoft.ManagedServices resources where the resource group does not match your known Sentinel resource group. This means a Lighthouse registration you don't own was created, modified, or deleted, in a subscription you monitor.

This is the higher-severity of the two detections. Legitimate Lighthouse delegations from unknown providers should be rare and always pre-approved. In practice, this fires when:

Why This Is High-Fidelity

Unlike Detection 1, which includes routine MSP activity, Detection 2 has very few legitimate triggers. An unknown delegation appearing in your monitored subscription is almost always either a coordination failure (fixable quickly) or a security incident (act now).

The Query

The full detection query is available to download here.

let SentinelRG = toscalar(
    Usage
    | where TimeGenerated > ago(1d)
    | where Solution == "LogManagement" and DataType == "SigninLogs"
    | extend ResourceGroup = tolower(split(split(ResourceUri, "/resourcegroups/")[1], "/")[0])
    | where isnotempty(ResourceGroup)
    | summarize any(ResourceGroup)
);
AzureActivity
| where TimeGenerated > ago(1h)
| where CategoryValue == "Administrative"
| where ResourceProviderValue =~ "MICROSOFT.MANAGEDSERVICES"
| where isnotempty(ResourceGroup) and
    isnotempty(SentinelRG) and
    tolower(ResourceGroup) != SentinelRG
| extend
    CallerType = tostring(parse_json(Authorization).evidence.principalType),
    Registration = tostring(parse_json(Properties).resource),
    UserName = iff(Caller contains "@", tostring(split(Caller, "@", 0)[0]), Caller),
    UPNSuffix = iff(Caller contains "@", tostring(split(Caller, "@", 1)[0]), "")
| project TimeGenerated, OperationNameValue, Status=ActivityStatusValue, Caller, UserName,
    UPNSuffix, CallerIpAddress, CallerType, Registration, ResourceGroup
| sort by TimeGenerated desc

Triage Guidance

  1. Identify the registration name in the Registration field, does this correspond to a known provider?
  2. Contact the customer immediately. Ask whether they authorised a new Lighthouse delegation.
  3. Review the caller and source IP. If neither is recognisable, escalate to an incident.
  4. Do not wait for confirmation before checking for lateral movement. If this is an attacker establishing a backdoor, they may already be active.

Deployment Notes

Rule Configuration Recommendations

Setting Detection 1 (MSP Change) Detection 2 (Non-MSP Change)
Severity Medium High
Query Frequency Every 1 hour Every 1 hour
Lookup Period Last 1 hour Last 1 hour
MITRE ATT&CK T1078.004 (Cloud Accounts) T1098 (Account Manipulation)
Incident Creation Yes Yes

Prerequisites

Limitations to Be Aware Of


Broader Context: Lighthouse as an Attack Surface

Azure Lighthouse is fundamentally a trust relationship expressed as a set of ARM resources. Like any trust relationship, its integrity depends on both parties maintaining control. From a threat modelling perspective:

Pairing these detections with a documented response procedure, and a clear communication path to the customer when an alert fires, turns a detection gap into a managed risk.


Summary

Detection 1 Detection 2
Trigger Change to your MSP's Lighthouse delegation Change to an unknown/third-party Lighthouse delegation
Fidelity Medium (includes expected MSP activity) High (unexpected delegations are rare)
Immediate Action Validate against change management Treat as potential incident; contact customer
Primary Risk Unplanned access scope change Backdoor delegation / unauthorised third party

Both rules are lightweight, rely only on AzureActivity and Usage (standard tables in any Sentinel deployment), and require no additional data connectors. They can be deployed directly as Scheduled Query Rules via the Sentinel Analytics blade or through ARM/Bicep templates as part of your standard rule deployment pipeline.

If Lighthouse is part of your operational model, these detections should be part of your baseline ruleset.