APT28 spent three days at the end of January 2026 spear-phishing European defence ministries, transport operators and diplomatic missions, then routed every command-and-control session through filen.io — a German, end-to-end encrypted consumer cloud storage service. Trellix published the analysis in its September SecondSight threat hunting report.
The exploit is not the interesting part. The C2 choice is.
Filen is a real service with real paying customers, valid certificates and a clean reputation. Traffic to it looks like file sync because it is file sync. Your egress policy permits it, your proxy categorises it as cloud storage, your intelligence feed has nothing on the domain, and because the platform is zero-knowledge you cannot read the payloads even with full TLS interception. Every reputational control you own returns green.
What Trellix reported
According to Trellix, the actor weaponised CVE-2026-21509 — a Microsoft Office security feature bypass that Microsoft disclosed out of band on 26 January 2026 with a CVSS base score of 7.8 — within roughly 24 hours of publication. Exploitation was under way by 27 January. The concentrated phishing burst ran from 28 to 30 January.
Trellix counted at least 29 distinct emails across nine eastern European countries, sent from compromised government mailboxes in Romania, Bolivia and Ukraine. Its sector breakdown: defence ministries roughly 40 per cent, transport and logistics operators 35 per cent, diplomatic bodies 25 per cent. Observed targeting spanned Poland, Slovenia, Greece, Turkey, the UAE and Ukraine, with a pronounced lean towards maritime and transport agencies.
The chain Trellix describes runs like this. The document forces a WebDAV fetch, which pulls a shortcut carrying shellcode, which drops a lightweight loader and a DLL called EhStoreShell.dll posing as an Enhanced Storage shell extension. That component is BeardShell, a C++ implant CERT-UA first attributed to UAC-0001 in June 2025. A modified Covenant Grunt follows, alongside NotDoor, an Outlook VBA backdoor that persists through VbaProject.OTM. Loader persistence is COM hijacking of CLSID {D9144DCD-E998-4ECA-AB6A-DCD83CCBA16D} under InProcServer32, paired with a scheduled task named OneDriveHealth that bounces explorer.exe so the hijacked DLL loads.
CERT-UA tracked the Ukrainian half of the activity as CERT-UA#19542 and reported that one lure impersonating the Ukrhydrometeorological Center reached more than 60 addresses inside central executive authorities. Trellix sells the threat hunting service this report exists to promote, so read the framing accordingly — but the technical substance matches CERT-UA's independent advisory.
Why the usual controls miss it
Three assumptions break simultaneously.
Domain reputation assumes bad destinations are known bad. Filen is not bad. It is a GDPR-friendly storage provider that happens to publish SDKs in TypeScript, Rust and Go, ship a headless CLI, and let you self-host a WebDAV or S3-compatible gateway in front of it. Building a file-drop C2 on that stack is an afternoon's work.
Egress filtering assumes you can enumerate the blocklist. There are hundreds of sync services. Sekoia's earlier work on the same actor found Covenant delivered over the Koofr API and BeardShell polling an Icedrive directory every four hours, encrypting tasks with ChaCha20-Poly1305 and disguising them as image files with valid magic bytes. Block Filen and the next campaign uses pCloud, or Mega, or Zoho WorkDrive.
TLS inspection assumes payload visibility. Client-side encryption means the ciphertext you decrypt from the TLS session is still ciphertext.
You cannot block your way out of this one. The certificate is valid, the provider is legitimate, the payload is encrypted before it leaves the host, and the traffic shape is file sync. The only anomaly left is that nobody in your organisation has a business reason to be talking to it.
Baseline before you detect
Start with an inventory, not a rule. Pull 60 to 90 days of proxy or DNS logs and count distinct internal hosts per cloud-storage destination. You will get a short head — your sanctioned tenant, one or two shadow services with genuine departmental use — and a very long tail of destinations touched by one or two machines.
That tail is your hunting ground. Tag the head as sanctioned in your CASB or Defender for Cloud Apps catalogue, get the business owner's name recorded against each, and treat everything else as alertable by default.
Seed the watchlist with the endpoints published in APT28 reporting rather than the marketing domain, because the sync clients never touch the marketing domain.
| Service | Endpoints observed in APT28 reporting |
|---|---|
| Filen | gateway.filen.io, gateway.filen.net, gateway.filen-1.net, gateway.filen-6.net, egest.filen.io, egest.filen.net, ingest.filen.io, ingest.filen.net, and filen.dev subdomains |
| Koofr | app.koofr.net |
| Icedrive | api.icedrive.net |
CERT-UA's advisory also listed the ranges 146.0.41.204 to 146.0.41.208 and 146.0.41.231 to 146.0.41.234 against this activity.
Detection logic
Rarity, scored across the estate
The signal is not the destination. It is how few of your machines touch it. In Splunk:
index=proxy earliest=-90d
| lookup sync_services domain AS dest_domain OUTPUT service, sanctioned
| where isnotnull(service) AND sanctioned="false"
| stats dc(src_ip) AS hosts, min(_time) AS first_seen,
sum(bytes_out) AS out, sum(bytes_in) AS in
BY service, dest_domain
| where hosts <= 3
| eval ratio=round(out/(in+1),2)
| sort hosts, -ratio
Three hosts is a starting threshold. Tune it to your estate size — in a 40,000-seat organisation, five is still rare.
Bind the process to the destination
This is the rule that survives the actor changing providers. A sanctioned sync service should only ever be contacted by that vendor's own client binary. Anything else is worth a look, and a DLL loaded into explorer.exe reaching a storage API is worth a page.
DeviceNetworkEvents
| where RemoteUrl has_any ("filen.io","filen.net","filen.dev",
"koofr.net","icedrive.net")
| where InitiatingProcessFileName !in~ ("filen.exe","filen-cli.exe")
| summarize Hosts=dcount(DeviceId), Conns=count(),
First=min(Timestamp)
by InitiatingProcessFileName, InitiatingProcessFolderPath
| order by Hosts asc
Pay particular attention to explorer.exe, rundll32.exe, regsvr32.exe, taskhostw.exe and anything running out of C:\ProgramData or a user AppData path.
Beacon shape
File-drop C2 still beacons, it just beacons politely. Compute inter-arrival times per source-destination pair over a week and flag low variance. Historic BeardShell polled on a four-hour cycle; a human syncing documents does not produce a four-hour metronome with sub-minute jitter and near-identical request sizes. Add a second filter for sessions where upload volume dwarfs download and the total transferred is measured in kilobytes, not megabytes. Real sync is bursty and large. C2 is regular and small.
Host-side signals worth hunting now
- Registry writes to
InProcServer32underHKCU\Software\Classes\CLSID, especially the CLSID named above, pointing at a DLL outside System32. - A scheduled task called
OneDriveHealth, or any task whose name imitates a Microsoft service but was not created by a Microsoft installer. - Creation or modification of
VbaProject.OTMin the Outlook profile directory, and registry changes toVBAWarningsorAccessVBOMunder the Office security keys. OUTLOOK.EXEspawningpowershell.exeorcmd.exe.- Outbound WebDAV from Office processes, which is the entry point in this chain and rarely legitimate on an endpoint.
Do this in the next week
- Confirm the January out-of-band Office update is deployed everywhere, including LTSC estates and anything still on Office 2016. CVE-2026-21509 was exploited in the wild within days of disclosure.
- Run the rarity query above and hand the top 20 results to a human. Most will be someone's personal Dropbox. A few will not be.
- Publish the sanctioned sync list as policy, with named owners, and default-deny the rest at the proxy for high-risk user populations — diplomatic staff, defence programme teams, anyone with mailbox access to sensitive correspondence.
- Write the process-attribution rule before you write any more domain blocks. It is the one that keeps working after the actor moves.
- Check whether your DLP and CASB even see these endpoints. Many category lists know filen.io and none of the gateway or ingest subdomains that carry the actual traffic.
The wider point for anyone maintaining a blocklist: Filen is an indicator, not a technique. The technique is using somebody else's legitimate, encrypted, well-run infrastructure as a dead drop, and the supply of candidate services is effectively unlimited. Reputation systems are structurally incapable of catching that, because the reputation is accurate. What you are actually detecting is an unexplained relationship — this host, this process, this destination, no business reason — and that only works if you have done the boring work of writing down which relationships are explained.


