Do you know Murphy’s law? It says that Anything that can go wrong will go wrong. The last week wasn’t different when every website located on the same server stopped responding. That was a precisely planned DDOS attack, created by myself and pointed at me.

Regular Thursday

What bad can happen on Thursday? On the morning, on the WordPress.org support forums of one of our plugins I noticed new thread. Someone posted a message that our documentation website is not responding. Or rather it’s responding with a 508 Resource Limit Is Reached error.

How 2 years ago I created DDOS attack pointed at myself which fired now 1

Quick look on the resource usage of my hosting panel showed the 100% CPU usage and almost constant 15 active processes (account limit).

How 2 years ago I created DDOS attack pointed at myself which fired now 2

I logged in to the server via SSH and confirmed, htop showed constantly refreshing processes with index.php as the entry point.

The usage didn’t grow rapidly, though. It was growing bigger and bigger over a few days to exceed all the server resources last week.

But what is this DDOS anyway?

DDOS stands for Distributed Denial Of Service. It’s when many sources pings the very same address over and over again, until the server is down.

Debug

I turned off all the plugins.

I turned off all the themes.

Nothing, the processes are still coming in.

I commented out the whole WordPress loader. Ha! It seems like it helped… a bit.

I switched back to WordPress 4.9.9, no effect.

I commented the whole plugin loader in WordPress, including the Must Use plugins. Usage went down for a moment,

Also, I checked the access_log and all looked good. Once in a while new bot requests whas popping out, nothing unusual during the last few hours. It cannot be anything from out side, can it?

January 2017

On the WPART, my small polish blog about WordPress I created my first plugin store where I sell Advanced Cron Manager PRO. I implemented the licenses which are refreshed yearly. I do implement a class in the plugin which updates it when the license is active. All thanks to the Easy Digital Downloads plugin with Software Licensing add-on. It works like a charm.

January 2018

The WPART store evolves to BracketSpace. Because of difficulties and the plugin architecture I decide to not migrate the orders nor licenses. It stayed on WPART, the old store and I thought I’ll clean everything up in a year when the last licenses expire.

January 2019

I decided to clean up WPART. Most of the plugins has been removed, including EDD and Software Licensing. The new theme is released (Twenty Nineteen FTW!), website performance looks very good and I’m more than happy.

It’s a DDOS

None of my efford give any result. Only switching off the whole WordPress works, but I’m not going to close down my website?

Then, out of the blue I get an idea… I dump the $_REQUEST array in the index.php. Bingo!

In a few second the log is becoming longer and longer. And after a first look I could tell what’s going on.

Array
(
    [edd_action] => check_license
    [license] => 331ad0b05f22df5454dxxxxxxxxxx
    [item_name] => advanced-cron-manager-pro
    [url] => https://xxxxxxxxxxxxx.com
)

A dozen websites are pinging my website to check if the plugin license is active. The website doesn’t know what these requests are, because there’s no EDD anymore, so it displays just the Homepage.

When I counted, the website was visited 10-15 times per second.

Plan of auto-destruction

Why the website kept pinging my blog and didn’t stop? Because the code responsible for checking the license was wrote to keep asking the API until the valid response comes back. No valid response? Try again, and again, and again.

Some weird HTML is certainly not a valid response. The plugin expected JSON encoded answer and info that the license is not active.

At first, it looked like a very resource-hungry Cron is working on the server but the requests became more frequent.

Solution

To resolve this issue I created simple Must Use plugin, which answers the question:

if ( isset( $_REQUEST['edd_action'] ) ) {
	header( 'Content-type: application/json' );
	die( '{"success":false,"license":"invalid","item_id":false,"item_name":"","checksum":"none"}' );
}

In a few minutes the CPU usage went down to 0. The plugin got the answer he was waiting for.

Summary

I know, I’m the guilty one. My own irresponsible coding lead to this situation. I didn’t anticipated that API just won’t exist at some point and it will be a trouble.

The weirdest thing about this whole situation was the lack of logs in the access_log. If the logs were saved I’d come to the solution within the minutes, not 8 hours. But why did it happened? Because the store was working on two domains before. The log was just saved on the other one.

Looking on the charts after the successful action was a huge relief.

How 2 years ago I created DDOS attack pointed at myself which fired now 3

Published by Kuba Mikita

Leave a Reply

avatar
  Subscribe  
Notify of