Week 38 · 13 min read
September 14 – September 21, 2026
What changed
Ron Pessner's 17 September post is framed as a fundamentals lecture, but the three case studies in the middle are the reason to read it. The first is CaptiveCrunch, a campaign Microsoft attributes to Storm-2945, which it describes as a subcluster of Midnight Blizzard. The actor manipulated DNS and HTTP traffic across hospitality networks — hotel Wi-Fi, in other words — and redirected travellers either into device code phishing served through legitimate Microsoft sign-in pages, or into fake software updates that dropped malware. What the malware took is the part worth noting: credentials, session tokens, security configuration details and remote-access history, which is a shopping list for a follow-on intrusion rather than an opportunistic credential grab. The second case is IT support impersonation over Microsoft Teams, and the chain is mundane and effective — the user is talked into granting control through remote-support software, PowerShell pulls down a malicious Windows Installer package, a portable Node.js runtime gets staged for command and control, and the operator then maps Active Directory and attempts WinRM lateral movement toward domain controllers and certificate authorities. The third is AI agent boundary testing, citing incidents disclosed by OpenAI and Anthropic in which agents reached production systems through SQL injection, exposed credentials, weak passwords and malicious PyPI packages. The controls Microsoft lists against these are unglamorous and mostly things you already own: phishing-resistant authentication expanded, device code flow blocked where there is no business need, sign-in risk policies in Conditional Access, endpoint attack surface reduction rules on, remote-support tooling and WinRM restricted, and agent identities governed with isolated execution and constrained outbound connectivity. The post also points at Secure Now in Microsoft Security Exposure Management, introduced in May, as the place to see which of those you are actually missing. If you brief one thing to travelling staff this quarter, make it the hotel network scenario. (Microsoft Security Blog)
The quarterly email security benchmark, also published 17 September, covers May through July 2026 and is useful mainly because of what it measures. Rather than counting threats caught, it counts threats missed, normalised per thousand protected users, which is the only way to compare vendors without the denominator games. Defender missed 221 high-severity threats per thousand users over the period, which Microsoft puts at roughly 55 percent fewer than the next closest secure email gateway vendor, and caught 92 percent of malicious messages that had already been delivered. The integrated cloud email security vendors in the comparison improved on their own numbers, with malicious catch rising to 0.30 percent from 0.13 percent and spam to 0.52 percent from 0.28 percent, which is the figure to have to hand the next time someone proposes bolting an ICES product on top. Three Defender for Office 365 changes are credited: the Promotions folder in Outlook, a rebuilt machine learning and AI model stack using natural language processing signals that Microsoft says cut false negatives by about two thirds and false positives by nearly a fifth, and prompt injection protection that detects and isolates malicious AI instructions before delivery. Vendor-published benchmarks deserve the usual scepticism, but the methodology is documented and the post-delivery number is the one to argue with your own data about — if your ZAP and post-delivery detection is doing less than that, the gap is worth chasing. (Microsoft Security Blog)
Microsoft Purview network data security is now generally available with the Microsoft Entra Global Secure Access integration, listed as a September general availability item and with the concept documentation refreshed on 16 September. This is the wire-level enforcement layer that was described in the layered data protection material a fortnight ago, now shipping rather than described. It reuses the sensitive information types and classifiers you already have, and you point either a collection policy at it for discovery or a data loss prevention policy at it for enforcement. Four activities are supported — text sent to a cloud or AI app, file uploaded, text received, file downloaded — and note that the inbound two are the interesting ones, because nothing else in the Purview stack classifies what comes back from a generative AI service. Actions are audit only or block. Data sources are the whole Defender for Cloud Apps catalogue, over 35,000 apps, or adaptive app scopes covering categories like generative AI, cloud storage and webmail. Licensing is the thing to check before you plan anything: with Global Secure Access it needs either Microsoft 365 E7 per seat, or Purview E5 plus Entra Internet Access, and a non-Microsoft SASE integration additionally requires the Purview pay-as-you-go billing model. Two operational caveats are documented and easy to trip over — the policies do not apply to B2B guest users, and inline evaluation stops at 4 MB for text and 3 MB for files, so a large upload is not inspected. Matches land in activity explorer with the enforcement plane filter set to network, and in DLP alerts. Allow a day for policy distribution before you conclude it is not working. (Microsoft Purview what's new)
Defender for Endpoint's September notes add a Secure Score recommendation set tagged AI-Readiness, generally available, and the tag is doing marketing work that the recommendations themselves do not need. Four are new — establish a hardware root of trust with TPM 2.0, isolate critical security functions with VBS, enforce kernel code integrity with HVCI, and limit lateral movement with Windows LAPS — and two existing ones join the collection, reduce unnecessary internet exposure on internet-facing devices and protect the startup process with Secure Boot. Strip the AI framing and this is a competent Windows platform hardening baseline with per-device visibility, remediation ownership and exception tracking attached, which is more than most organisations have for these four settings. Find it under Exposure Management, Recommendations, Devices, Misconfigurations, filtered by the AI-Readiness tag. Two previews land alongside it: memory scan for Linux, which inspects process memory for memory-resident threats that leave nothing on disk, available in version 101.26071.0005 or later on the Insiders-slow channel, and Defender for Endpoint plug-in support for WSL containers, which brings WSL container activity into device inventory, alerts, incidents, timeline and advanced hunting. The WSL one closes a real blind spot on developer workstations, though it needs a registration form to enrol. (Microsoft Defender for Endpoint what's new)
A community piece published on 15 September introduces Data Security Workbench, an open-source tool built on the newly released Microsoft Purview DLP API, and it is worth a look for anyone drowning in DLP alert volume. The premise is that the work of connecting an alert to its evidence, working out why a sensitive information type fired, finding the business owner and deciding what to tune is currently spread across scripts, exports, spreadsheets and analyst memory. The workbench turns that into a four-step loop — observe the SIT boundary and tuning profile, explain detections to separate signal from systemic noise, generate a reviewable Purview implementation plan, then compare post-change results against the original baseline. The output that matters operationally is the implementation plan: prioritised P0 to P2 actions, each naming the target SIT, the exact portal path, the current problem, the configuration change, why it is safe, the expected false-positive reduction and the associated risks. Triage verdicts can be written back in bulk to Purview incidents as comments and tags, which surface in the Microsoft Defender incident activity timeline. The data handling is the reason it is safe to pilot: evidence is redacted by default, detected values and identities are excluded from the AI payload, departments are resolved locally before identity redaction, and live Graph writes are disabled unless explicitly enabled with a confirmation phrase, bounded targets and an execution ledger, with dry run always the first gate. This is community content rather than a Microsoft product, so treat it as a starting point you own, not a supported tool. (Microsoft Security Community Blog)
Self-service onboarding for new Microsoft Entra App Gallery applications went to public preview on 17 September. The audience is software vendors rather than SOC analysts, but the second-order effect is worth knowing. Publishers can now test an integration against gallery requirements before submitting it — the Microsoft Entra App Validator browser extension walks OIDC and SAML single sign-on through the required scenarios and generates the test ID needed for submission, and user provisioning is validated through a Microsoft-provided Logic Apps flow or the SCIM onboarding agent. The submission itself moves into a guided workflow in the Entra admin center with draft saving, status tracking and feedback. Microsoft still reviews every submission before an app appears, so this is not a shortcut past review; it moves the configuration failures earlier. The preview covers new applications only — updates to and removals of existing listings still go through the old process, and creating a new submission to replace an existing listing is explicitly the wrong move. Practically, expect gallery entries to arrive with cleaner single sign-on and provisioning configurations, which is a small reduction in the volume of half-broken enterprise app integrations that land in an identity team's queue. (Microsoft Entra Blog)
Carrying one item from 14 September that missed last week's issue: multi-account support for Sentinel codeless connectors is in public preview as a framework capability, not just for the individual connectors announced in late August. A single connector built on the Codeless Connector Framework can now hold multiple independently deployable connections in one workspace, each shown as its own row labelled with account name, tenant ID or environment, each deployed, edited and deleted on its own so removing one leaves the rest alone. Under the hood the connector definition, the data collection rule, the data collection endpoint and the destination table are all shared; what gets created per connection is a single lightweight data connector resource with a unique name carrying the labelling metadata, which is what stops connections overwriting one another. The practical read for an analyst is that ingestion plumbing does not multiply as you add accounts, and everything still lands in one table, so existing analytics rules and hunting queries cover the new sources without edits. Microsoft now recommends that all new CCF connectors support the pattern where it makes sense, and Semperis shipped the first one with its Lightning connector. If you have a subsidiary or a non-production account you skipped because a duplicate connector was too awkward, check whether your connector has an Add connection action yet. (Microsoft Sentinel Blog)
KQL to try
A scheduled analytics rule published on 17 September that looks for Microsoft 365 Copilot interactions where a user asks for the system or developer instructions and the response comes back carrying instruction, guardrail, persona or tool-architecture markers. It matches on both sides of the exchange — phrases like repeat the words above or everything above this line in the prompt, and phrases like you are an or you have access to the following tools in the response — and deliberately does not return the prompt or response text in the alert, so the detection does not become its own disclosure channel. The author is careful about what it proves: this is possible prompt-disclosure evidence, not proof that every returned phrase was confidential, so treat a hit as a lead rather than a finding. It needs the CopilotActivity table through the Microsoft Copilot connector. (Microsoft 365 Copilot - System prompt disclosure — David Alonso)
CopilotActivity
| where RecordType == "CopilotInteraction"
| extend Prompt=tolower(tostring(LLMEventData.Prompt)), Response=tolower(tostring(LLMEventData.Response)), ConversationId=tostring(LLMEventData.ConversationId)
| where isnotempty(Prompt) and isnotempty(Response)
| extend AskedForPrompt=Prompt has_any ("system prompt", "developer message", "hidden instructions", "initial instructions", "reveal your prompt", "repeat the words above", "show me your prompt", "print your system", "everything above this line", "verbatim instructions")
| extend LeakMarker=Response has_any ("you are an", "your role is", "# system", "system prompt", "you must never", "do not reveal", "your instructions are", "you have access to the following tools", "your available tools", "you should always", "never disclose")
| where AskedForPrompt and LeakMarker
| extend Signal="POSSIBLE SYSTEM PROMPT DISCLOSURE"
| project TimeGenerated, Signal, AgentId, AgentName, ActorName, ActorUserId, ConversationId, SrcIpAddr, TenantId
| order by TimeGenerated desc
From the same 17 September batch, a rule that flags a Microsoft Foundry agent invoking an MCP tool whose server URL, label or dependency target is not on an approved list — unauthorised server drift, a compromised project connection, or an agent reaching a server from the wrong environment. It reads AppDependencies from Application Insights and coalesces several property names for the server identity, because the preview SDKs emit it under gen_ai.tool fields, mcp.server fields, generic server fields or the dependency Target depending on version. Two things to do before you deploy it: populate a watchlist named FoundryMcpApprovedServers with at least one row where Approved is true and ServerIdentifier holds the exact normalised value your telemetry emits, and then enable the rule, because it ships disabled on purpose and no-ops while the watchlist is empty. Rows with no server metadata at all are excluded rather than alerted on, so pair it with an inventory hunt over the same data. (Foundry - Unapproved MCP server executed — David Alonso)
let approved =
_GetWatchlist('FoundryMcpApprovedServers')
| where tolower(tostring(column_ifexists('Approved', 'false'))) in ('true', '1', 'yes')
| extend ApprovedServer = tolower(trim(' ', tostring(column_ifexists('ServerIdentifier', ''))))
| where isnotempty(ApprovedServer)
| distinct ApprovedServer;
let ApprovedCount = toscalar(approved | count);
AppDependencies
| where isnotempty(tostring(Properties["gen_ai.tool.name"]))
| extend
Agent = tostring(Properties["gen_ai.agent.name"]),
Model = tostring(Properties["gen_ai.request.model"]),
ConvId = tostring(Properties["gen_ai.conversation.id"]),
ToolName = tostring(Properties["gen_ai.tool.name"]),
ToolType = tostring(Properties["gen_ai.tool.type"]),
ToolDescription = tostring(Properties["gen_ai.tool.description"]),
ServerLabel = coalesce(tostring(Properties["gen_ai.tool.server_label"]), tostring(Properties["mcp.server.label"]), tostring(Properties["server_label"])),
ServerUrl = coalesce(tostring(Properties["gen_ai.tool.server_url"]), tostring(Properties["mcp.server.url"]), tostring(Properties["server_url"])),
Operation = tostring(Properties["gen_ai.operation.name"])
| extend McpServer = coalesce(ServerUrl, ServerLabel, tostring(Target))
| where ToolType has "mcp" or Operation has "mcp" or ToolName has "mcp" or ToolDescription has "mcp" or McpServer has "mcp"
| where ApprovedCount > 0 and isnotempty(McpServer)
| extend NormalizedServer = tolower(trim(' ', McpServer))
| join kind=leftanti approved on $left.NormalizedServer == $right.ApprovedServer
| summarize
Calls = count(),
Failures = countif(Success == false),
Tools = make_set(ToolName, 20),
Conversations = dcountif(ConvId, isnotempty(ConvId)),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Model = take_any(Model)
by Agent, McpServer
| extend
AccountName = iff(isempty(Agent), "unknown-agent", Agent),
McpServerUrl = iff(McpServer startswith "http://" or McpServer startswith "https://", McpServer, "")
| project LastSeen, AccountName, Agent, Model, McpServer, McpServerUrl,
Calls, Failures, Conversations, Tools, FirstSeen
| order by Calls desc
Worth knowing
The Entra blog published a phased guide to replacing VPN access with Microsoft Entra Private Access on 16 September. There is no new feature in it, but it is the most coherent sequencing of that migration Microsoft has put out, and the framing is right: Global Secure Access is the broader security service edge, Private Access is the component that actually replaces VPN for private applications. The five steps run from inventorying private applications, file shares and internal web resources and who reaches them from where, through identity and Conditional Access controls, to automated monitoring and risk response, and finally retiring VPN incrementally with documented fallback procedures. The step that concerns a SOC is the fourth — the guide's advice is to pipe identity and session telemetry into Microsoft Sentinel so that the detections you have for MFA fatigue, unusual sign-in patterns and other identity-driven attacks keep working when the network perimeter stops being the control point. Worth reading before someone hands your team a per-app access model and assumes the existing analytics rules still apply. The operations guide and the VPN replacement checklist it points at are at aka.ms/GSAOpsGuide. (Microsoft Entra Blog)