↑↓ move ↵ open esc close Searches the full text of every issue.

SOC Weekly Brief The week in the Microsoft security stack, distilled

← Home

Week 40 · 17 min read

September 28 – October 5, 2026

Act by

  • 1 Nov 2026 — two Defender for Servers billing changes take effect, announced on 30 September. The first is good news if you have been paying for desktops: productivity and client devices such as Windows 10 and Windows 11 PCs are no longer billed as servers under Plan 1. The catch is in how classification works — Microsoft decides from operating-system and device information, not from how you use the machine, and anything it cannot clearly identify as a desktop or workstation is still classified as a server for billing. Ubuntu Desktop, Fedora Workstation, Mint and KDE neon count as desktops; Ubuntu Server, RHEL, SLES and the rest stay servers. The second change hits both Plan 1 and Plan 2: the service moves from checking for online machines once an hour to several times an hour, and counts each deployed machine separately, including machines cloned from a golden image that share an Azure Arc ID. That second one can push your billed server count up, so if you run image-based fleets, model the new count before the invoice arrives rather than after. (Microsoft Defender for Cloud release notes)

What changed

Microsoft Threat Intelligence published exploitation detail for CVE-2026-73570 on 30 September, and if you run Zimbra anywhere in your estate this is the week's priority. It is an unauthenticated OS command injection in the Zimbra Collaboration Suite SNMP notification path: a crafted SMTP request carries shell metacharacters into SNMP notification processing, and when a service-state change triggers health monitoring, swatchdog folds the attacker-controlled value into an snmptrap shell invocation. No authentication, no user interaction. Exploitation requires the optional zimbra-snmp package installed with SNMP notifications enabled, which is the one piece of luck here. The timeline is the uncomfortable part — Zimbra 10.1.20 shipped the fix on 20 July, public disclosure followed on 13 August, and Microsoft saw two distinct out-of-band scanning tools probing the exact injection path between 28 July and 7 August, in the gap between the two. Probes used the CVE-specific ZB73570 User-Agent over HTTP and randomised callback subdomains on oast[.]fun, oast[.]online, dnslog[.]pp[.]ua and requestrepo[.]com. Post-exploitation was hands-on: JSP webshells written into Jetty and mailboxd paths across multiple mailbox nodes, privilege escalation by symlinking the zmmailboxd log over /etc/pam.d/sudo and using pam_exec to write a NOPASSWD entry for the zimbra account, a systemd unit named zimlog.service timestomped to match rsync.service and sshd.service, and credential collection via zmlocalconfig -s followed by authenticated LDAP queries for zimbraPreAuthKey, zimbraAuthTokenKey and zimbraTwoFactorAuthSecret. Lateral movement reused the existing /opt/zimbra/.ssh/zimbra_identity to rsync payload fragments between cluster nodes. Three things to take from the guidance: patch to 10.1.20 or later, or uninstall zimbra-snmp and restrict SNMP and SMTP to trusted hosts; rotate every domain zimbraPreAuthKey, because token material was collected and a preauth key is a durable bypass; and treat a reverse-shell alert on an internet-facing mail server as a priority incident even when nothing was quarantined, since the worst outcome Microsoft saw — full mail-store staging for exfiltration — involved no malware family at all, just a plain interactive shell over openssl s_client through a named pipe at /tmp/s. (Microsoft Security Blog)

The 29 September write-up on RMM abuse is the one to send to anyone who still treats remote-support tooling as a low-risk category. Since July, Microsoft Defender Experts has tracked phishing campaigns distributing a legitimate, digitally signed MSP360 RMM v2.5.0.67 installer under filenames crafted to look like business content — VIP_ECARD_INVITATION_rmm_v2.5.0.67_oid[redacted].exe, ZoomSetup_Installation_v2.5.0.67, SSA.GOV_STATEMENT_rmm_v2.5.0.67 and similar, behind lures themed as meeting requests, Zoom and Google Meet installs, Adobe Acrobat updates, RSVPs, job offers, signature requests and DHL notices. Payloads were hosted on attacker infrastructure, compromised sites, and Amazon S3, Cloudflare R2, Dropbox, GitLab and Supabase, so the same installer rotated through many different-looking files. After UAC elevation the installer registers RMM.Agent.exe and RMM.Agent.Launcher.exe as services, adds Run-key autoruns, and opens an inbound UDP firewall rule on port 48678. Then the interesting bit: the RMM agent launches PowerShell, pulls ClientSetup.msi from actor infrastructure, and installs a ConnectWise ScreenConnect client silently via msiexec /qn — giving a second, independent remote-access channel. From there the operators used ScreenConnect's RunFile feature to stage tooling under Documents\ScreenConnect\Temp\ with names chosen to look like Windows and Defender components: DefenderControl.exe, DefenderDT.exe, WindowsSecurity_Password.exe, WebBrowserPassView.exe, SCHider.exe, HideCursor.exe and more. Microsoft was explicit that ScreenConnect itself was not exploited and that the activity is unattributed; it also saw FaronicsDeployAgent.exe used the same way as the first-stage RMM. The practical defence is inventory plus blocking: know which RMM products are legitimately in use, then use Application Control or AppLocker publisher rules — or Defender for Endpoint's block-certificate action — to stop the rest, and if you find an unapproved install, reset the account that installed it. The SHA-256 to hunt for is 108ef7e628d7a20bd6241a5b57149e27a6061f467123eb64061975559f8f73dc, whose signing certificate has since been revoked. (Microsoft Security Blog)

Star Blizzard got a refresh on 29 September, and the headline change is that the Russian FSB Centre 18 actor has stopped being purely a spear-phishing outfit. Since January, Microsoft has seen at least 13 distinct large-scale campaigns running tens to hundreds of messages each, affecting more than 100 organisations primarily in the US and UK — Ukrainian individuals and institutions first, then international NGOs, think tanks, governments and financial institutions with a Ukraine nexus. Lures impersonate closed-door roundtables and conferences from recognisable institutions. Two tradecraft shifts matter for detection. First, since March the actor has been creating accounts on compromised CPanel and WordPress sites to send the mail, reusing the same account name across domains, rather than the Protonmail and consumer accounts it used before — so sender-reputation heuristics built on free providers will miss these. Second is RedFlick, the new delivery technique: a password-protected RAR or ZIP, with the password supplied as an image in the follow-up email, carries an LNK disguised as a PDF. January campaigns used a VHDX container whose LNK ran conhost.exe and cmd.exe to execute a hidden BAT that invoked SSH.exe with PermitLocalCommand to fetch an MSI. By April the MSI was installing three scheduled tasks masquerading as network components — Internet Quality Test Connection for beaconing and remote DLL execution through Control_RunDLL, Network Configuration Manager to prime the WebDAV redirector, and System Health Monitor to pull the CosmicPulse downloader as a Control Panel applet over WebDAV. By July the chain hid the next stage inside a downloaded PDF, searching it for a cAB magic header and base64-decoding the following 208 bytes. The point of all of it is to cut user interaction down to a single click and get CosmicPulse, a Python backdoor also tracked publicly as YESROBOT, onto the host. Defender coverage includes the Star Blizzard Activity Group detection, Trojan:Script/RedFlick, Backdoor:Script/CosmicPulse and suspicious Control Panel item alerts; the hunting angle worth building yourself is scheduled tasks with plausible networking names whose actions reach a UNC-style path. (Microsoft Security Blog)

The quarter's Cyberattack Series report, published 29 September, is a short read with a specific lesson about where identity compromise actually ends up. Storm-3068 got into a tenant through a self-service password reset, then took permanent control of the account by registering its own authentication methods, and headed straight for Azure DevOps. Using legitimate administrative tooling and scripts it enumerated repositories, projects, pipelines and deployment environments, then built a malicious pipeline whose job was harvesting Kubernetes credentials at scale: it deployed a kube agent and ran jobs to collect kubeconfig files, with the compromised account's permissions letting that pipeline reach more than 50 resources. It also modified pipeline scripts to install the Atera RMM agent and download Chisel, then opened a reverse tunnel to expose the Kubernetes API server. Seven stolen kubeconfig files were committed into a repository, which is how investigators reconstructed the sequence from Azure DevOps audit logs and Git history. No malware and no software exploit anywhere in the chain. The recommendations are worth reading as a checklist rather than advice: monitor password-reset activity for repeated attempts or activity across multiple users, keep privileged accounts out of self-service password reset and on phishing-resistant MFA, require approvals and branch protection on code changes, restrict direct commits to critical branches, and control who can create, modify or execute pipelines. If your SOC has no visibility into Azure DevOps audit logs today, this is the case to use when you ask for it. (Microsoft Security Blog)

Carried over from the day before the window, because no prior issue picked it up: Microsoft documented NeedyMantis on 28 September, a modular post-compromise malware family seen in a limited set of targeted intrusions against telecommunications firms, universities, medical nonprofits, intergovernmental organisations and government contractors. Activity dates back to at least October 2025, and Microsoft found it by pivoting from indicators associated with the DAEMON Tools supply chain compromise that Kaspersky reported; it is tracked against Storm-3069, assessed as operating from China but not attributed to a nation-state actor, and Microsoft suspects more than one operator has access to it. The delivery mechanism is DLL sideloading alongside legitimate software, with the first-stage loader masquerading as a required DLL and a same-named encrypted archive next to it holding the second stage. Watch the paths: %ProgramFiles%\Poedit\WinSparkle.dll, %ProgramData%\USOShared\libcurl.dll, %ProgramData%\VIM\vim64.dll, %ProgramData%\TightVNC\VIM\vim64.dll, %ProgramData%\office\dbghelp.dll, %ProgramData%\broadcom\dbghelp.dll, %ProgramData%\Intel\jli.dll and %ProgramData%\ics\nvml.dll — legitimate open-source tools and spoofed Microsoft, Broadcom, Intel and NVIDIA components, in writable directories. The loader builds its strings on the stack and resolves Windows APIs at runtime, and the main component supports load, unload and dispatch commands for modules Microsoft has not yet recovered, so assume capability beyond what is documented. In one incident the operator used Impacket during hands-on-keyboard activity to copy the legitimate software, the malicious DLL and the archive from a network share and run them. Defender coverage spans TrojanDropper:Win64/NeedyMantis, Behavior:Win64/NeedyMantis, the Impacket detections and Suspicious DLL loaded. (Microsoft Security Blog)

The Sentinel monthly roundup on 30 September carried one item that had not already been covered by the 23 September announcements, and it is a real improvement if you work with an MSSP or run multiple tenants. Defender unified RBAC custom roles can now be assigned to granular delegated admin privileges remote tenant groups, in public preview. The split is clean: GDAP decides which partner groups can be delegated access to your tenant, and unified RBAC decides what they can actually see and do once delegated, scoped down to specific security products, data sources and data collections. Previously GDAP only supported Entra directory roles, which in practice meant handing a partner considerably more access than the job required. One detail to carry into the contract conversation — anyone who is a member of a remote tenant group inherits its permissions, and your partner controls group membership while you control the role and its scope, so the scoping work is where your leverage is. The same roundup notes Sentinel has passed 500 data connectors. (Microsoft Sentinel Blog)

Entra made browser authentication for external identity providers generally available on 29 September, which closes a gap that has quietly been pushing federated tenants back onto passwords. If you authenticate Microsoft 365 users through an external identity provider over WS-Fed or SAML 2.0, some Microsoft app sign-ins used an embedded web view that could not do WebAuthn — so a user with a passkey or FIDO2 security key registered at the identity provider either fell back to a password or could not sign in at all when the provider required passkeys or rejected embedded web views. Now only the external identity provider step opens in the system browser, the user returns through the Microsoft identity broker, and the originating app completes sign-in; Outlook, Teams, OneDrive, Word, Excel, PowerPoint and To Do are covered. Check the platform matrix before you promise anything: Android needs Chrome as default browser with a supported broker, Android shared device mode needs Chrome, iOS needs Safari with Microsoft Authenticator as broker, and managed macOS needs Safari with Intune Company Portal. Windows already does third-party FIDO natively and does not use this flow. Linux, unmanaged macOS and OAuth 2.0 or OIDC social identity provider flows are not supported, and direct sign-in to Company Portal on Android still uses an embedded WebView. Administrators enable it per platform in the federation configuration. (Microsoft Entra Blog)

Smaller, and only relevant if you run Azure Government: the enhanced agent for Defender for SQL Servers on Machines became fully available in that cloud on 29 September, for both resource-level and subscription-level enablement, matching the commercial cloud experience. The reason to care is that the enhanced agent drops the Azure Monitor Agent dependency and works through existing SQL infrastructure instead, which removes a long-standing onboarding headache. Two required actions come with it. Anyone who previously enabled the plan has to update their configuration for automatic registration, and you should then verify that your SQL Server instances actually show as protected rather than assume they did. Budget for a bill increase as well — the note is explicit that the enhanced agent may protect additional SQL Server instances that the old agent was missing, which is simultaneously the point and the cost. (Microsoft Defender for Cloud release notes)

KQL to try

A chain hunt published on 30 September that lines up almost exactly with the RMM campaign above, and the sequencing is what makes it useful: a mail bomb, then an external Teams message, then remote-access tooling on the endpoint. It flags a 15-minute bin as a mail bomb at 100 or more inbound messages from 20 or more distinct senders, looks in MessageEvents for a Teams message from an external domain arriving between the start of the flood and two hours after it ends, then searches DeviceProcessEvents in the following four hours for either a known remote-support tool or a script interpreter launched from explorer.exe using encoded or hidden execution or fetching remote content. Organisation domains are derived from inbound recipient domains rather than hardcoded, and the thresholds sit in let parameters at the top, which you will want to tune to your own mail volume before trusting the ChainConfidence column. Approved external helpdesk partners are the obvious false positive to allowlist. (Mail Bombing Followed by External Teams Contact and Remote Access Execution — Benjamin Zulliger)

let HuntLookback = 30d;
let MailBurstWindow = 15m;
let TeamsFollowupWindow = 2h;
let EndpointFollowupWindow = 4h;
let MinimumBurstMessages = 100;
let MinimumDistinctSenders = 20;
let OrgDomains = EmailEvents
 | where EmailDirection == "Inbound"
 | distinct RecipientDomain;
let MailBombs =
 EmailEvents
 | where Timestamp >= ago(HuntLookback)
 | where EmailDirection =~ "Inbound"
 | extend UserEmail = tolower(RecipientEmailAddress)
 | summarize
  FloodStart = min(Timestamp),
  FloodEnd = max(Timestamp),
  BurstMessageCount = count(),
  DistinctSenders = dcount(SenderFromAddress),
  DistinctSubjects = dcount(Subject)
  by UserEmail, FloodBin = bin(Timestamp, MailBurstWindow)
 | where BurstMessageCount >= MinimumBurstMessages
  and DistinctSenders >= MinimumDistinctSenders;
let ExternalTeamsMessages =
 MessageEvents
 | where Timestamp >= ago(HuntLookback)
 | mv-expand RecipientDetails
 | extend
  SenderEmail = tolower(SenderEmailAddress),
  RecipientEmail = tolower(tostring(RecipientDetails.RecipientSmtpAddress))
 | extend
  SenderDomain = tolower(extract(@"@([^@]+)$", 1, SenderEmail)),
  RecipientDomain = tolower(extract(@"@([^@]+)$", 1, RecipientEmail))
 | where isnotempty(SenderDomain) and isnotempty(RecipientDomain)
 | where SenderDomain !in (OrgDomains) and RecipientDomain in (OrgDomains)
 | project
  UserEmail = RecipientEmail,
  TeamsTime = Timestamp,
  ExternalSender = SenderEmail,
  ExternalSenderDomain = SenderDomain,
  TeamsMessageId;
let MailThenTeams =
 MailBombs
 | join kind=inner ExternalTeamsMessages on UserEmail
 | where TeamsTime >= FloodStart and TeamsTime <= FloodEnd + TeamsFollowupWindow
 | summarize
  TeamsTime = min(TeamsTime),
  ExternalSender = take_any(ExternalSender),
  ExternalSenderDomain = take_any(ExternalSenderDomain),
  TeamsMessageId = take_any(TeamsMessageId)
  by UserEmail, FloodBin, FloodStart, FloodEnd, BurstMessageCount, DistinctSenders, DistinctSubjects;
let SuspiciousEndpointActivity =
 DeviceProcessEvents
 | where Timestamp >= ago(HuntLookback)
 | where isnotempty(AccountUpn)
 | extend
  UserEmail = tolower(AccountUpn),
  CommandLine = tolower(ProcessCommandLine),
  ProcessName = tolower(FileName),
  ParentName = tolower(InitiatingProcessFileName),
  GrandparentName = tolower(InitiatingProcessParentFileName)
 | extend
  LaunchedFromExplorer = ParentName == "explorer.exe" or GrandparentName == "explorer.exe",
  HasEncodedOrHiddenExecution = CommandLine matches regex @"(?i)(\s-enc(odedcommand)?\b|\s-w(indowstyle)?\s+hidden\b|frombase64string)",
  HasRemoteFetch = CommandLine matches regex @"(?i)(https?://|downloadstring|invoke-webrequest|\biwr\b|\b(curl|wget|bitsadmin|certutil)\b)",
  IsScriptOrShell = ProcessName in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "mshta.exe", "wscript.exe", "cscript.exe", "curl.exe"),
  IsRemoteSupportTool = ProcessName in~ (
   "quickassist.exe", "anydesk.exe", "teamviewer.exe", "screenconnect.client.exe",
   "rustdesk.exe", "ateraagent.exe", "splashtop.exe", "bomgar-scc.exe", "logmein.exe"
  )
 | where IsRemoteSupportTool
  or (LaunchedFromExplorer and IsScriptOrShell and (HasEncodedOrHiddenExecution or HasRemoteFetch))
 | project
  UserEmail,
  EndpointTime = Timestamp,
  DeviceName,
  DeviceId,
  ProcessFileName = FileName,
  ProcessCommandLine,
  InitiatingProcessFileName,
  InitiatingProcessParentFileName,
  IsRemoteSupportTool,
  HasEncodedOrHiddenExecution,
  HasRemoteFetch;
MailThenTeams
| join kind=inner SuspiciousEndpointActivity on UserEmail
| where EndpointTime >= TeamsTime and EndpointTime <= TeamsTime + EndpointFollowupWindow
| extend ChainConfidence = case(
 IsRemoteSupportTool and (HasEncodedOrHiddenExecution or HasRemoteFetch), "High",
 IsRemoteSupportTool or (HasEncodedOrHiddenExecution and HasRemoteFetch), "High",
 "Elevated")
| project
 ChainConfidence,
 UserEmail,
 FloodStart,
 FloodEnd,
 BurstMessageCount,
 DistinctSenders,
 DistinctSubjects,
 TeamsTime,
 ExternalSender,
 ExternalSenderDomain,
 TeamsMessageId,
 EndpointTime,
 DeviceName,
 DeviceId,
 ProcessFileName,
 ProcessCommandLine,
 InitiatingProcessFileName,
 InitiatingProcessParentFileName,
 IsRemoteSupportTool,
 HasEncodedOrHiddenExecution,
 HasRemoteFetch
| order by iff(ChainConfidence == "High", 0, 1) asc, FloodStart desc, EndpointTime desc

Published on 2 October, and a good companion to the Azure DevOps case above: it watches for app instance property locks being weakened in Entra. An app instance property lock stops a tenant from modifying sensitive properties on a multi-tenant application's service principal — credentials, identifier URIs, token encryption key. Turning one off is a prerequisite step for an attacker who wants to add their own credential to an existing service principal, and it is a configuration change nobody normally makes twice, so the signal is clean. The query walks modifiedProperties in ApplicationManagement audit logs for the ServicePrincipalLockConfiguration property and alerts only on a true-to-false transition across any of the lock's individual flags, which keeps the enable direction and the no-op writes out of the results. (Entra app instance property lock tampering (ServicePrincipalLockConfiguration) — Jay Kerai)

//https://learn.microsoft.com/en-us/entra/identity-platform/howto-configure-app-instance-property-locks
AuditLogs
| where Category == "ApplicationManagement"
| mv-expand TargetResource = TargetResources
| mv-expand Property = TargetResource.modifiedProperties
| where tostring(Property.displayName) == "ServicePrincipalLockConfiguration" //| where TargetResources[0].modifiedProperties[0].displayName == "ServicePrincipalLockConfiguration"
| extend Old = parse_json(tostring(Property.oldValue))
| extend New = parse_json(tostring(Property.newValue))
| extend
Old_IsEnabled = tobool(Old[0].IsEnabled),
New_IsEnabled = tobool(New[0].IsEnabled),
Old_AllProperties = tobool(Old[0].AllProperties),
New_AllProperties = tobool(New[0].AllProperties),
Old_CredentialsWithUsageVerify = tobool(Old[0].CredentialsWithUsageVerify),
New_CredentialsWithUsageVerify = tobool(New[0].CredentialsWithUsageVerify),
Old_CredentialsWithUsageSign = tobool(Old[0].CredentialsWithUsageSign),
New_CredentialsWithUsageSign = tobool(New[0].CredentialsWithUsageSign),
Old_IdentifierUris = tobool(Old[0].IdentifierUris),
New_IdentifierUris = tobool(New[0].IdentifierUris),
Old_TokenEncryptionKeyId = tobool(Old[0].TokenEncryptionKeyId),
New_TokenEncryptionKeyId = tobool(New[0].TokenEncryptionKeyId)
| where
(Old_IsEnabled == true and New_IsEnabled == false) or
(Old_AllProperties == true and New_AllProperties == false) or
(Old_CredentialsWithUsageVerify == true and New_CredentialsWithUsageVerify == false) or
(Old_CredentialsWithUsageSign == true and New_CredentialsWithUsageSign == false) or
(Old_IdentifierUris == true and New_IdentifierUris == false) or
(Old_TokenEncryptionKeyId == true and New_TokenEncryptionKeyId == false)
| project TimeGenerated,OperationName,AppName = tostring(TargetResource.displayName),InitiatedBy,Old,New

Worth knowing

The 2026 Microsoft Digital Defense Report landed on 1 October. The framing this year is interconnectedness — threat activity spanning infrastructure, identities, applications, cloud and software supply chains, and AI systems and agents now sitting in the middle of data, tools and business systems. On attacker use of AI, the assessment is measured rather than alarming: actors are folding AI into reconnaissance, social engineering, malware and exploit development and post-compromise work, but mostly inside specific steps of existing workflows, with the underlying methods unchanged. The report also covers agent identity, authentication between agents, attribution and revocation, plus prompt injection, memory, model and data integrity, and it is candid that AI-assisted code analysis cuts both ways on vulnerability discovery. The sections most worth an hour are the ones on relating signals across systems and on red teaming, where the argument is that connecting known information and running established techniques is increasingly automatable while finding an undocumented attack path still needs an experienced operator close to the work. Executive summary first if you are short on time. (Microsoft Security Blog)

Ignite dates and structure were confirmed on 30 September: 17 to 20 November 2026 at Moscone Center in San Francisco, with an online option, and a Security Pre-Day on Monday 16 November from 1pm to 5pm Pacific that you have to select during registration rather than add later. The opening keynote is Tuesday 17 November, with a Security Innovation Session later in the week carrying the executive-led demos. This matters for planning because several things announced in September were explicitly deferred to Ignite for detail — most of the Integrated Security Operations Center story included — so if you are holding a decision on ISOC or on the Defender portal migration, mid-November is when you get the rest of the picture. (Microsoft Security Blog)

Jussi Metso published a practitioner digest of the September Defender for Endpoint and Defender XDR what's-new on 3 October, and it is a useful second opinion on which of last month's items deserve effort. His MDE read is that WSL container protection going GA is the one to deploy now, since developers' Linux containers on Windows laptops were a visibility gap that now shows up in the same alerts and incidents as everything else, while Linux desktop support and Linux memory scanning stay pilots until licensing is confirmed. On XDR he argues the Identity Security dashboard with Coverage and Maturity reaching general availability is more immediately actionable than ISOC, on the grounds that it produces a single score and maturity tier across on-premises, cloud and SaaS identity sources with a prioritised fix list, needs only a Defender for Identity or Defender for Cloud Apps licence, and does not depend on preview eligibility. If you need a number to take to a steering group this quarter, that is the one he suggests adopting. (Jussi Metso)