Identity
Storm-3068 used Azure DevOps to steal Kubernetes keys
One self-service password reset gave Storm-3068 an Azure DevOps account, a pipeline that reached 50+ resources and seven kubeconfigs. What to check.
On September 29, Microsoft's incident response team published an intrusion by a group it tracks as Storm-3068. The attacker took over one user account through self-service password reset (SSPR), swapped the account's MFA for its own, and then used that account's Azure DevOps access to run a pipeline that collected Kubernetes credentials. Seven stolen kubeconfig files ended up committed to a repository, and pipelines were changed to install the Atera remote management agent and the Chisel tunnelling tool.
Microsoft notes the attacker modified development pipelines instead of deploying malware, and no software vulnerability was involved. If your teams deploy to Kubernetes from Azure DevOps, the same path exists in your tenant: an identity that can reset its own password, a pipeline platform that holds deployment rights, and clusters that trust whatever credentials that platform hands out. Microsoft did not name the victim, say when the intrusion took place or describe the attacker's motive.
How it works
SSPR lets a user who forgot their password prove who they are with registered methods, such as an authenticator app, a phone number or an email address, and set a new password without the help desk. If an attacker can pass that check, they own the password. Microsoft does not say how Storm-3068 passed it. After the reset, the attacker registered its own authentication methods, removed the user's legitimate MFA methods, and enrolled a device it controlled in Microsoft Intune. From then on, the real user could not get back in on their own, and the attacker's sign-ins would look like a user with a managed device and working MFA.
Azure DevOps is where that one account became a path into production. A pipeline runs with the rights of its project and of the resources it is authorised to use: service connections (stored credentials for Azure, Kubernetes or other targets), variable groups, secure files, agent pools and environments. Anyone who can create or edit a pipeline, and whose pipeline is allowed to use those resources, can make them do something new. Storm-3068 enumerated repositories, projects, pipelines and deployment environments with legitimate administrative tools and scripts, then ran a pipeline authorised to access more than 50 resources.
A kubeconfig file is what kubectl reads to talk to a cluster. It holds the API server address, the cluster's certificate authority data and the user credential, which can be a client certificate or a ServiceAccount token. Whoever holds a working kubeconfig has whatever rights that credential has in the cluster, from any network that can reach the API server. Long-lived credentials in those files stay valid after the pipeline run ends.
What Storm-3068 did
After the takeover, according to Microsoft and the reporting on its write-up:
- The malicious pipeline deployed a kube agent and added jobs named in the pattern
DUMP_CLUSTER_<NAME>, each pulling a cluster's kubeconfig. - The files were saved and then added to a folder named
kubeconfigsin an existing repository. Investigators counted seven kubeconfig files, found by reading Azure DevOps audit logs and the Git history. - Pipeline scripts were modified to install the Atera remote management agent and to download Chisel, an open-source tool that tunnels TCP over HTTP.
- Chisel was run to open a reverse tunnel to an external IP address, which could expose the Kubernetes API server to the attacker from outside.
The reporting says the Chisel commands ran, but nothing published so far says how much sustained access to the clusters the attacker gained. Treat any cluster whose kubeconfig was in that folder as exposed until its credentials are rotated.
What to do
1. Look for reset followed by method changes. In Microsoft Sentinel or a Log Analytics workspace that receives Entra audit logs, find accounts where a self-service reset and a security info change happened close together:
AuditLogs
| where TimeGenerated > ago(90d)
| where OperationName == "Reset password (self-service)" or OperationName contains "security info"
| extend UPN = tostring(TargetResources[0].userPrincipalName)
| summarize Ops = make_set(OperationName), First = min(TimeGenerated), Last = max(TimeGenerated) by UPN
| where Ops has "Reset password (self-service)" and array_length(Ops) > 1
Any account that reset its password and then deleted a security info method deserves a call to the person who owns it. Check the same account's Intune enrolments around that time.
2. Check Azure DevOps for new or edited pipelines. If you stream Azure DevOps auditing to Azure Monitor, the events land in the AzureDevOpsAuditing table. Look at who created or modified pipelines, which resources were authorised to them, and which service connections ran:
AzureDevOpsAuditing
| where TimeGenerated > ago(90d)
| where OperationName in ("Pipelines.PipelineCreated", "Pipelines.PipelineModified", "Pipelines.ResourceAuthorizedForPipeline", "Library.ServiceConnectionExecuted", "Git.RefUpdatePoliciesBypassed")
| summarize Events = count(), Ops = make_set(OperationName) by ActorUPN, ProjectName
| order by Events desc
Without a stream, the same events are under Organization settings, Auditing, and can be pulled with the Audit Log Query API. An account that has never touched pipelines before and suddenly authorises dozens of resources is the pattern here.
3. Search Git and pipeline definitions. Kubeconfig files normally carry a certificate-authority-data field, so git log --all -S "certificate-authority-data" --name-only in each repo lists every commit that added or removed one. Also search YAML and scripts for DUMP_CLUSTER, atera and chisel, and check build agents for an Atera agent install or a chisel binary.
4. Narrow what pipelines can reach. On every Kubernetes and Azure service connection, turn off "Grant access permission to all pipelines" and authorise pipelines one by one; Microsoft's own documentation advises against the all-pipelines option. Add an Approvals and checks gate to production connections and environments, with approvers who cannot approve their own runs. Apply branch policies so pipeline YAML on protected branches only changes through a reviewed pull request, and limit who holds the Edit build pipeline permission.
5. Harden SSPR. Accounts with Entra administrator roles get a separate SSPR policy that is on by default and requires two methods. If your admins can get a reset from another admin instead, set AllowedToUseSspr to false on the tenant authorization policy (Update-MgPolicyAuthorizationPolicy -AllowedToUseSspr:$false). For everyone else, require two methods to reset and protect method registration with a Conditional Access policy on the "Register security information" user action, for example requiring a trusted location or phishing-resistant MFA. Storm-3068 enrolled its own device in Intune, so a policy that only requires a compliant device may not stop an attacker who has already enrolled one.
6. Rotate every credential a kubeconfig in the repo could carry. Deleting the files from Git does not invalidate them. On AKS, az aks rotate-certs rotates the cluster CA, the API server certificates and ServiceAccount tokens; it recreates the nodes and can cause up to 30 minutes of downtime, so plan a window. If the clusters use Entra ID for sign-in, disable local accounts with az aks update --disable-local-accounts and then rotate certificates, because existing local certificates stay valid until you do. On other clusters, delete and recreate the ServiceAccount token Secrets the files used and reissue client certificates. Also rotate the secrets behind any service connection the malicious pipeline was authorised to use.
Where pipelines fit in identity reviews
Most access reviews look at who holds Owner or Contributor in Azure. A user who can edit a pipeline that is authorised to a production service connection effectively holds that connection's rights, and a role-based review will not list them. Treating pipeline edit rights and service connection authorisations as privileged access, and putting them in the same review, would have made this account an obvious one to protect.
We review Azure DevOps pipelines, service connections and AKS access as part of our cloud and Kubernetes security work, and hunt for this kind of activity in security operations. If you want someone to run the checks above against your tenant, open the chat and Yaali, our AI agent, will pass your question to an engineer.
Sources: Microsoft Security Blog, GBHackers, Cyberpress, DEV Community, Microsoft Learn: SSPR policies, Microsoft Learn: Azure DevOps auditing events, Microsoft Learn: Service connections, Microsoft Learn: Rotate AKS certificates.