So, a couple of weeks ago, I got hit by every DevOps engineer's worst nightmare. Long story short: we were caught in the middle of a massive zero-day attack targeting VMmanager 6.
Now that the fire is out and everything is patched, I want to break down how this exploit actually worked. It’s a pretty wild architectural chain involving Nginx, WebSockets, and Docker internal networks.
But honestly, the biggest takeaway for me wasn't even the hack itself, but how the vendor handled the mess. Usually, when a major security incident happens, vendors go into radio silence or blame the user. These guys did the exact opposite.
The ISO Trick
The attack started with something super simple but nasty — custom user ISO images.
If you run a public cloud or hosting setup, you obviously let clients upload their own ISOs to install whatever OS they want. The attackers just bought a cheap VM in our cluster to get a standard user account, uploaded a weaponized ISO, and used a flaw in how the platform mounts these images to get initial access to the node.
As it turned out, the guys at ISPsystem had already caught this bug through their Bug Bounty a few days earlier. They were working on a major fix for it, but the hackers managed to strike right before the deployment window.
The WebSocket Request Smuggling
The vendor quickly rushed out an emergency hotfix to block the ISO vector, but the hackers didn’t care. They immediately switched to their second weapon, which was way more sophisticated — HTTP Request Smuggling (HRS) over WebSockets.
Here is how our network topology looks (and it’s pretty standard for microservices):
- Nginx sits on the frontend, faces the internet, and drops suspicious traffic.
- Clean requests go to internal microservices inside a private Docker bridge network.
- To authenticate internal communication, services look for a specific custom HTTP header. Nginx is set up to strip this header if it comes from the outside world.
The attackers found a zero-day in one of the backend services and abused Nginx's default behavior with WebSockets.
First, they sent a malicious HTTP request to upgrade the connection to a WebSocket, but they stuffed a hidden payload into the request body. According to RFC standards, you shouldn't send a body with a WebSocket upgrade, but Nginx just passes it through to the backend anyway.
The backend service saw the malformed request and rejected it. But here’s the catch — it didn't clear the request body from the buffer. Because the connection used keep-alive, the backend read those leftover bytes in the buffer as a completely new, separate HTTP request.
Since Nginx thought it was just tunneling a WebSocket connection, it never inspected that smuggled second request. The hackers forged the internal Docker security headers inside that smuggled body. The backend parsed the buffer, saw the trusted header, assumed it came from a safe peer inside the local Docker network, and executed admin commands. Boom, full RCE.
How the Vendor Handled the Fire
Look, zero-days happen to everyone. Linux, Microsoft, Nginx—everything gets popped eventually. For me, the real test of a vendor is how they act when the house is on fire.
Instead of hiding behind PR statements or burying their heads in the sand, ISPsystem basically set up a 24/7 war room.
Within hours of verifying the exploit, they started rolling out rapid-fire hotfixes. To buy us time, they deliberately locked down non-essential features in the UI—like running scripts or issuing SSH access. It temporarily broke some quality-of-life features, but it completely paralyzed the attacker's automated tools while the devs hunted the root cause.
They also did something I haven’t seen many vendors do — they deployed an open-network honeypot environment to test their patches under live fire. The hackers threw over 10,000 automated requests at the honeypots, and the patched nodes deflected every single one of them.
By October 23, they dropped a massive stable release that didn't just patch the proxy pipeline; it completely overhauled the core internal microservice framework. They added strict validation layers for internal Docker networking, so even if someone bypasses Nginx again, the internal services will still drop the request without a valid token.
cTakeaways for Your Own Setup
If you run microservices behind Nginx using WebSockets, you might want to double-check your configs:
- Check out client_body_early_read. Nginx added this directive in version 1.31.5 (Mainline). It lets Nginx block or handle early-read request bodies before proxying, which completely kills this specific Request Smuggling vector. If you are on the Stable branch (like 1.30.x), it’s not supported yet, so your backends must be coded to manually drain request buffers on rejection.
- Don’t rely only on edge proxies. Relying solely on Nginx to strip out sensitive headers is fine for defense-in-depth, but it shouldn't be your only line of defense. Microservices should use zero-trust validation (like mTLS or internal JWT tokens) rather than blindly trusting raw HTTP headers.
We’ve been running the patched version for a while now, and zero new anomalies have been detected. It sucks to go through a breach, but watching a vendor actually step up, work directly with infrastructure engineers in the tickets, and ship real fixes this fast was a breath of fresh air.
If you are running VMmanager, update to the October 23 release right now. The gap between a zero-day discovery and full automation is down to just a few hours.

Top comments (0)