Another day, another VPS breach

I woke up to two emails that immediately caught my attention.

One was from my website monitoring service (I use UptimeRobot, no affiliation) reporting that a client’s website was down. The other was from my VPS provider informing me that they had suspended my VPS due to abuse.

I logged into the control panel and immediately noticed a massive CPU spike. The server had gone from its usual 15–20% CPU usage to a sustained 100% for nearly four hours before the provider shut it down under their fair usage policy.

My first clue was xmlrpc.php. It was consuming a significant amount of resources, so I started researching it. I’m not primarily a WordPress/PHP developer, and I was surprised to learn that XML-RPC exposes functionality for remote management of WordPress.

I disabled XML-RPC, brought the VPS back online, and thought the problem was solved.

It wasn’t.

The next day I woke up to the exact same two emails.

This time my VPS provider had already imposed CPU limits on the server. I noticed a few kernel-looking processes consuming CPU, assumed they were related to the throttling, and restarted the VPS.

A few hours later, it was offline again.

At that point I knew I was dealing with a compromise rather than a performance issue.

I began investigating the WordPress installation and immediately found obvious signs of infection. There were numerous malicious PHP files (index.php, cache.php, etc.) buried inside recursively nested directories such as:

image/image/image/image/cache.php

The deeper I looked, the worse it became.

The attackers had created:

  • A rogue WordPress administrator account
  • An unauthorized SSH key
  • A root-level user on the VPS
  • An administrator account inside CyberPanel

This wasn’t just a compromised website anymore.

It was a full VPS compromise.

My working theory was that the attackers exploited a vulnerable WordPress component (likely allowing arbitrary PHP upload or remote code execution), established persistence, and pivoted into the operating system.

Then I found a suspicious process called libnet-cache.

At first glance it looked like a legitimate kernel process, but it wasn’t.

Every time I killed it:

kill -9 

it immediately reappeared.

Something else was respawning it.

I started tracing persistence mechanisms.

Systemd? Found one malicious service.

Cron? Found multiple malicious cron jobs.

I tried deleting them.

Permission denied.

That made no sense.

I was root.

After some research I discovered the files had the immutable (i) attribute set.

Normally you remove it with:

chattr -i 

Except…

that also returned permission denied.

Even the chattr binary itself had been tampered with. Fortunately its permissions were recoverable, allowing me to restore it and finally remove the immutable attribute.

From there the cleanup became much more methodical:

  • Removed immutable attributes
  • Deleted malicious services
  • Removed malicious cron jobs
  • Deleted unauthorized users
  • Removed rogue SSH keys
  • Reinstalled WordPress core using WP-CLI
  • Deleted every malicious PHP file from wp-content/uploads
  • Rotated credentials
  • Reviewed the rest of the server for persistence

The root cause appeared to be a compromised WordPress site that allowed the attackers to gain remote code execution, escalate their foothold, establish persistence, and eventually deploy a cryptocurrency miner.

My VPS had become someone else’s mining rig.

One compromised website was all it took to lose an entire VPS.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

How I Built a Peptide Dosage Calculator with Next.js — and Why SSR Matters More Than You Think

Next Post

From Transition to Compliance: Navigating QMSR Implementation and Inspection Readiness

Related Posts