Archive

Archive for the ‘Life’ Category

How to deal with a WordPress wp-comments-post.php SPAM attack

May 9th, 2013

This morning I woke up to several website monitoring alarms going off.  My websites were becoming intermittently unavailable due to extremely high server load (>190).  It appears nicj.net had been under a WordPress comment-SPAM attack from thousands of IP addresses overnight.  After a few hours of investigation, configuration changes and cleanup, I think I’ve resolved the issue.  I’m still under attack, but the changes I’ve made have removed all of the comment SPAM and have reduced the server load back to normal.

Below is a chronicle of how I investigated the problem, how I cleaned up the SPAM, and how I’m preventing it from happening again.

Investigation

The first thing I do when website monitoring alarms are going off (I use Pingdom and Cacti) is to log into the server and check its load.  Load is an indicator of how busy your server is.  Anything greater than the number of CPUs on your server is cause for alarm.  My load is usually around 2.0 — when I logged in, it was 196:

[nicjansma@server3 ~]$ uptime
06:09:48 up 104 days, 11:25,  1 user,  load average: 196.32, 167.75, 156.40

Next, I checked top and found that mysqld was likely the cause of the high load because it was using 200-1000% of the CPU:

top - 06:16:45 up 104 days, 11:32, 2 users, load average: 97.69, 162.31, 161.74
Tasks: 597 total, 1 running, 596 sleeping, 0 stopped, 0 zombie
Cpu(s): 3.8%us, 19.1%sy, 0.0%ni, 10.7%id, 66.2%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 12186928k total, 12069408k used, 117520k free, 5868k buffers
Swap: 4194296k total, 2691868k used, 1502428k free, 3894808k cached

PID   USER  PR NI VIRT RES  SHR  S %CPU  %MEM TIME+ COMMAND
24846 mysql 20 0 26.6g 6.0g 2.6g S 260.6 51.8 18285:17 mysqld

Using SHOW PROCESSLIST in MySQL (via phpMyAdmin), I saw about 100 processes working on the wp_comments table in the nicj.net WordPress database.

I was already starting to guess that I was under some sort of WordPress comment SPAM attack, so I checked out my Apache access_log and found nearly 800,000 POSTS to wp-comments-post.php since yesterday.  They all look a bit like this:

[nicjansma@server3 ~]$ grep POST access_log
36.248.44.7 - - [09/May/2013:06:07:29 -0700] "POST /wp-comments-post.php HTTP/1.1" 302 20 "http://nicj.net/2009/04/01/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)"

What’s worse, the SPAMs were coming from over 3,000 unique IP addresses.  Essentially, it was a distributed denial of service (DDoS) attack:

[nicjansma@server3 ~]$ grep POST access_log | awk '{print $1}' | sort | uniq -c | wc -l
3105

NicJ.net was getting hundreds of thousands of POSTS to wp-comments-post.php, which was causing Apache and MySQL to do a whole lot of work checking them against Akismet for SPAM and saving in the WordPress database.  I logged into the WordPress Admin interface, which verified the problem as well:

There are 809,345 comments in your spam queue right now.

Yikes!

Stopping the Attack

First things first, if you’re under an attack like this, the quickest thing you can do to stop the attack is by disabling comments on your WordPress site.  There are a few ways of doing this.

One way is to go into Settings > Discussion > and un-check Allow people to post comments on new articles.

The second way is to rename wp-comments-post.php, which is what spammers use directly to add comments to your blog.  I renamed my file wp-comments-post.php.bak temporarily, so I could change it back later.  In addition, I created a 0-byte placeholder file called wp-comments-post.php so the POSTS will look to the spammers like they succeeded, but the 0-byte file takes up less server resources than a 404 page:

[nicjansma@server3 ~]$ mv wp-comments-post.php wp-comments-post.php.bak && touch wp-comments-post.php

Either of these methods should stop the SPAM attack immediately.  5 minutes after I did this, my server load was back down to ~2.0.

Now that the spammers are essentially POSTing data to your blank wp-comments-post.php file, new comments shouldn’t be appearing in your blog.  While this will reduce the overhead of the SPAM attack, they are still consuming your bandwidth and web server connections with their POSTs.  To stop the spammers from even sending a single packet to your webserver, you can create a small script that automatically drops packets from IPs that are posting several times to wp-comments-post.php.  This is easily done via a simple script like my Autoban Website Spammers via the Apache Access log post.  Change THRESHOLD to something small like 10, and SEARCHTERM to wp-comments-post.php and you will be automatically dropping packets from IPs that try to post more than 10 comments a day.

Cleaning up the Mess

At this point, I still had 800,000+ SPAMs in my WordPress moderation queue.  I feel bad for Akismet, they actually classified them all!

I tried removing the SPAM comments by going to Comments > Spam > Empty Spam, but I think it was too much for Apache to handle and it crashed.  Time to remove them from MySQL instead!

Via phpMyAdmin, I found that not only were there 800,000+ SPAMs in the database, the wp_comments table was over 3.6 GB and the wp_commentmeta was at 8.1 GB!

Here’s how to clean out the wp_comments table from any comments marked as SPAM:

DELETE FROM wp_comments WHERE comment_approved = 'spam';

OPTIMIZE TABLE wp_comments

In addition to the wp_comments table, the wp_commentmeta table has metadata about all of the comments. You can safely remove any comment metadata for comments that are no longer there:

DELETE FROM wp_commentmeta WHERE comment_id NOT IN (SELECT comment_id FROM wp_comments)

OPTIMIZE TABLE wp_commentmeta

For me, this removed 800,000+ rows of wp_comments (bringing it down from 3.6 GB to just 207 KB) and 2,395,512 rows of wp_commentmeta (bringing it down from 8.1 GB to just 136 KB).

Preventing Future Attacks

There are a few preventative measures you can take to stop SPAM attacks like these.

NOTE: Remember to rename your wp-comments-post.php.bak (or turn Comments back on) after you’re happy with the prevention techniques you’re using.

  1. Disable Comments on your blog entirely (Settings > Discussion > Allow people to post comments on new articles.) (probably not desirable for most people)
  2. Turn off Comments for older posts (spammers seem to target older posts that rank higher in search results). Here’s a way to disable comments automatically after 30 days.
  3. Rename wp-comments-post.php to something else, such as my-comments-post.php. Comment spammers often just assume your code is at the wp-comments-post.php URL and won’t check your site’s HTML to verify this is the case. If you rename wp-comments-post.php and change all occurrences of that URL in your theme, your site should continue to work while the spammers hit a bogus URL. You can follow this renaming guide for more details.
  4. Enable a Captcha for your comments so automated bots are less likely to be able to SPAM your blog. I’ve had great success with Are You A Human.
  5. The Autoban Website Spammers via the Apache Access log post describes my method for automatically dropping packets from bad citizen IP addresses.

After all of these changes, my server load is back to normal and I’m not getting any new SPAM comments.  The DDoS is still hitting my server, but their IP addresses are slowly getting packets dropped via my script every 10 minutes.

Hopefully these steps can help others out there.  Good luck! Fighting spammers is a never-ending battle!

2012 Minifigures Available

April 17th, 2013

Thanks to Christoph‘s hard work taking photos of all 529 minifigures released in 2012, the 2012 minifigs are now available for purchase in the Unofficial Minifigure Catalog app.

To purchase the update, first update the database to the latest version (Settings > Database) and then go to Settings > Collections and look for the purchase button.

UserTiming.js

April 15th, 2013

UserTiming is one of the W3C specs that I helped design while working at Microsoft through the W3C WebPerf working group.  It helps developers measure the performance of their web applications by giving them access to high precision timestamps. It also provides a standardized API that analytics scripts and developer tools can use to display performance metrics.

UserTiming is natively supported in IE 10 and prefixed in Chrome 25+.  I wanted to use the interface for a few of my projects so I created a small polyfill to help patch other browsers that don’t support it natively. Luckily, a JavaScript version of UserTiming can be implemented and be 100% API functional — you just lose some precision and performance vs. native browser support.

So here it is: UserTiming.js

README:

UserTiming.js is a polyfill that adds UserTiming support to browsers that do not natively support it.

UserTiming is accessed via the PerformanceTimeline, and requires window.performance.now() support, so UserTiming.js adds a limited version of these interfaces if the browser does not support them (which is likely the case if the browser does not natively support UserTiming).

As of 2013-04-15, UserTiming is natively supported by the following browsers:

  • IE 10+
  • Chrome 25+ (prefixed)

UserTiming.js has been verified to add UserTiming support to the following browsers:

  • IE 6-9
  • Firefox 3.6+ (previous versions not tested)
  • Safari 4.0.5+ (previous versions not tested)
  • Opera 10.50+ (previous versions not tested)

UserTiming.js will detect native implementations of UserTiming, window.performance.now() and the PerformanceTimeline and will not make any changes if those interfaces already exist.  When a prefixed version is found, it is copied over to the unprefixed name.

UserTiming.js can be found on GitHub and as the npm usertiming module.

New Adventures: Why I’m Leaving Microsoft and What’s Next

September 14th, 2011

Six years ago, fresh out of college, I packed up my life into a couple of moving boxes and headed out to the Pacific Northwest to take a job at Microsoft.  Since then, I’ve been lucky enough to work on some amazing projects – a large scale performance validation infrastructure for Windows 7, a world-class browser, and have helped shape the future of the web by collaborating in the W3C webperf working group.  It’s been a great place to work – I’ve made some amazing friends, learned more than I ever would have imagined, and have been often humbled by how amazing my coworkers are.

This Friday will be my last day at Microsoft.  It was a tough decision to leave, and there are many things I will miss about the company, my work, and my coworkers.  Microsoft is a great company, the benefits are amazing, and you get to work with a ton of awesome people.  I’ve grown in so many ways by just being able to interact with and learn from my coworkers.  I’ll miss those interactions.

On the other hand, for the past fifteen years, I have been building software, websites, and now mobile apps in my spare time.  I’ve always used these side projects to satisfy a need to be creative, to learn and explore new technologies, and to have fun.  Some of these projects have grown beyond what I would have ever expected them to be.  It’s been tough finding time to work on them – after a long day of mind-bending work, staring at a monitor for another couple hours isn’t always at the top of my list of things to do.  But I get a lot of pleasure out of being creative, so I’ll often stay up late working on this or that.

And so, I’ve always wondered what I could accomplish if those projects were my only job?

Starting Monday, I am taking the big, scary step of becoming my own boss.  I’m still not 100% sure what that means, and I’ll let you know a year from now how it has worked out.  I’m excited to build, to be creative, to learn, and to share.  It’s time for me to get serious about some of the projects I’ve already put hundreds of hours into and to take them to the next level.

In addition to those projects, one of my passions is performance, on both the desktop and the web.  My focus at Microsoft was on perf features and analysis, where I developed a massive performance regression testing system for Windows 7.  I built performance features for Internet Explorer 9, and collaborated in the W3C webperf working group.  I hope to continue learning, exploring and even teaching others about performance in the future, through research and experimentation with my own projects.

There are a ton of things I want to accomplish, and I know I’ll have to work hard to provide for my family.  It’s not easy walking away from a comfy salary and great benefits, with the knowledge that you have to make up for all of it on your own.  Thankfully I have a head start with some successful websites and apps, but I know I’m going to have to put a lot of hard work into taking them to the next level.

Wish me luck.

My attempt at being environmentally friendly, day 2

January 3rd, 2007

So after being inspired to reduce my energy usage, I took a look at buying Compact Fluorescent Light bulbs (CFLs) for my apartment.

CFL

CFLs are recently becoming popular in home lighting, and can provide substantial energy savings over their lifetime. They can replace almost all of your existing light bulbs in your house.

CFLs:

  • Use 2/3 the energy of normal bulbs
  • Last up to 10 times longer
  • Generate up to 70% less heat

They do come at a higher initial cost. However, as I was shopping for CFLs at Home Depot, I noticed coupons from Puget Sound Energy for $2 off (small) and $3 off (large) per bulb, limit of 8 of each size. That saved me (8 * $2 + 8 * $3) = $40 in bulbs, so I retrofitted my entire apartment, 16 bulbs for $32!

After replacing all of the bulbs in my apartment, I am quite happy. Their lighting output is the same (to the naked eye) as the old bulbs. The energy savings are substantial. Before and after wattages (verified with the Kill-A-Watt):

  • 1x floor lamp – 140W before, 21W with CFLs
  • 1x night stand lamp – 90W before, 14W with CFLs (60W equivalent)
  • 3x bathroom mirror lights – 60W before, 14W with CFLs
  • 4x dome lights – 60W before, 14W with CFLs
  • 6x track lights – 60W before, 14W with CFLs
  • Total: 1010W before, 217W with CFLs

PSE charges me about $0.06841 per kWh. (not that I do), but if I ran all of these lights 24/7, I would be spending (1010W * 24 h * 30 days * 0.06841) = $49.73 / mo. With CFLs, this is reduced to (216 W * 24 h * 30 days * 0.06841) = $10.63 / mo. So while that isn’t realistic, as I don’t have all my lights on all of the time, I’m probably saving a few dollars a month.

Cool stuff!

My attempt at being environmentally friendly, day 1

January 3rd, 2007

An Inconvenient Truth

I had been meaning to check it out for a while, so I finally watched An Inconvenient Truth (on my Zune! great for a coast to coast flight) on the way back to Michigan before Christmas. I would definitely recommend watching it, then doing some research on your own afterwards. There is a Wikipedia article with some good references for further information as well.

ClimateCrisis.net has an interesting calculator to determine how much CO2 emissions you produce annually (I’m estimated at about 10.2 tons of CO2 per year, mostly due to flying every month). In an attempt to lower my impact on the environment, I’ve dug out my P3 Kill-A-Watt I bought last year after reading about it on Coding Horror.

P3 Kill-a-Watt
The $25 Kill A Watt is a sweet little device that you can use to measure the energy consumption of various things in your house. You just plug this into your wall first, then your appliance into it. It shows current volts, amps, watts, kWh, etc.

I went on an energy census of my various electrical devices, and found some interesting things:

Appliances
* Mini refrigerator (average): 20W
* Coffee grinder: 67W
* Toaster oven: 1470W

Fans
* Bedroom tower fan: 25W low, 38W high
* Living room tower fan: 30W low, 37W high, 37W high+oscillation

Lighting
* Bedroom tower light: 140W, 21W w/ CFL
* Bedroom desk lamp: 90W, 13W w/ CFL
* CPU desk lamp: 20W
* Living room tower light: 165W low, 300W high
* Bathroom mirror (3x): 60W, 14W w/ CFL
* Dome lights (4x): 60W, 14W w/ CFL
* Kitchen, living room track lights (6x): 60W, 14W w/ CFL

Misc
* Zune charging w/ iPod adapter: 2W
* Jabra (headset) charging: 0W
* MotoQ (cellphone) charging: 2W
* Alarm clock: 0W

Electronics
* Main computer: 190W
* Shuttle (Media Center) computer: 140W
* 17″ LCD: 45W
* 21″ LCD: 40W

* Comcast DVR: 43W off, recording, or playing
* Xbox 360: 275W @ dashboard, +4W if a 1-4 wireless controllers active
* TV: 87W
* Amp: 72W idle or playing content
* Playstation 2: 29W

Interesting stuff! I was surprised that my 21″ LCD took less energy than the 17″ LCD. The 17″ LCD is older (a year or two), and is also running VGA (instead of DVI on the 21″). Would that be why?

There are other devices that I didn’t quite measure that I’m sure account for a good percentage lot of my electrical usage (refrigerators, microwave, washer, dryer, dish washer) as well. Here‘s a good estimator for those appliances.

Tomorrow’s adventure is converting my apartment to Compact Fluorescent Lights (CFLs).