Brickstorm persistence in Microsoft 365

Brickstorm persistence in Microsoft 365

Brickstorm gave attackers a way to stay inside Microsoft 365 tenants without relying on one clean, obvious control path. In the cases tracked under UNC5221, access lasted for at least 18 months in one victim before detection, which is a long time for anything meant to be watched. The awkward part is that the Microsoft 365 side was only one piece of the problem.

How Brickstorm keeps a foothold inside Microsoft 365 tenants

The access pattern was built around stolen credentials and proxying, not loud repeated password guessing. Brickstorm acted as a bridge into Microsoft 365, with traffic made to look close enough to normal network activity that Conditional Access policies could be sidestepped. That matters because controls that depend on location, device state, or expected sign-in patterns can look fine right up until someone routes through a trusted-looking path.

The operator also did not treat Microsoft 365 as a single point of entry or exit. Other footholds sat beside it, including an Egnyte Storage Sync system and a web SSL VPN path. That gives the attacker more than one way back in when one route gets closed. It also means a clean Microsoft 365 password reset can still leave the wider access structure intact.

Where the access path slips past normal controls

Stolen credentials and proxying into the tenant

Stolen credentials were the obvious starting point, but the useful part was what happened next. Brickstorm proxied traffic into Microsoft 365, so the sign-in trail could blend with legitimate traffic rather than stand out as an isolated, suspicious source. That sort of reuse is ugly because it turns a valid account into transport for an already trusted-looking session.

Once that happens, tenant controls that assume a clean separation between internal and external access stop being much help on their own. If the login appears to come from the expected route, a policy can pass traffic that would otherwise be blocked. A control gap like that usually shows up only after the attacker has already settled in.

Why Conditional Access can miss the traffic pattern

Conditional Access does not fix a bad identity state by itself. If the actor can present the right credentials and route the session through infrastructure that resembles normal access, the policy may never see a reason to object. Volexity assessed that the traffic was blended in to evade Conditional Access policies that would have blocked access otherwise.

The failure here is not that the policy was absent. It is that the access path had enough cover to look routine. That is where Microsoft 365 persistence becomes more annoying than a one-time breach. The attacker is not just logging in, they are building a path that keeps fitting inside the shape of normal use.

What the wider foothold buys the operator after entry

Firewall, VPN and storage systems as backup persistence

Brickstorm was not the only layer in play. The actor also deployed malware to a Synology NAS, a pfSense firewall, and a retired Linux GroupWise archive server. Those systems are interesting because they are not where people usually spend their monitoring time. They are also the sort of devices that can sit outside tighter endpoint coverage.

In the same intrusion, SSL VPN access was enabled and configured on the victim firewall. That gives a clean route for re-entry if Microsoft 365 access gets interrupted. It also creates another dependency: if your remote access stack is part of the intrusion, the usual separation between perimeter and internal account recovery is already broken.

Regaining access after remediation

One of the sharper details is that the actor regained access after remediation efforts had finished. That is the sort of thing that happens when the removal work focuses on the last visible foothold and leaves the supporting paths in place. If the managed services provider is also compromised, the attacker does not need to start from scratch.

This is why post-compromise persistence is not just about one implant surviving a reboot. It is about keeping enough linked access alive across identity, VPN, storage and network devices that a cleanup only clears the most obvious layer. In one case, the victim and its managed services provider both ended up in the same mess.

What to watch for when you try to catch this earlier

The strongest warning sign is not a single alert. It is a chain of small failures that line up: unusual Microsoft 365 sign-ins that still satisfy policy, proxy behaviour that looks like ordinary traffic, and remote access changes on devices that should not be touched during an incident. If a firewall, NAS or storage sync system starts acting like an access broker, treat it that way.

Port 443 traffic is worth more attention when the same infrastructure is being used as C2 or proxying. In the Brickstorm case, infrastructure later stopped serving on port 443, which cut visibility for investigators. That is a reminder that external hostnames and live services disappear fast, while the access they supported may still be active somewhere inside the tenant.

The practical control is to treat Microsoft 365 persistence as a multi-system problem. Recheck authentication tokens, VPN configuration, appliance admin access, and any device that can proxy into cloud services. A clean password reset is useful, but it is not a full eviction notice.

Tags:

Related posts

Brickstorm persistence in Microsoft 365

Brickstorm showed how Microsoft 365 persistence can survive a tidy password reset and a few blocked logins. I keep coming back to the same point, if identity, VPN and odd little appliances all line up...

Gitea | v1.27.1

Gitea v1271: Security, Actions, API, UI and data fixes improving OAuth2 2FA enforcement, OIDC behavior, workflow reliability, UX polish and repo cleanup

Gitea | v1.27.1

Gitea v1 27 1: mandatory 2FA for OAuth2, OAuth and OIDC auth hardening, Actions and workflow stability, UI and API fixes, repo and data integrity fixes