Mitigating CVE-2018-6389 WordPress DoS attack with lighttpd

Early in 2018, Barak Tawily published a possible DoS attack for WordPress, that basically works by requesting all possible scripts on the /wp-admin/load-scripts.php, a script that fetches and concatenates javascript files — there’s also a load-styles.php file that does the same for styles.

His vulnerability report was rejected by the WordPress team, on the account that this type of attack should be mitigated at the server or network level… so how do you do that using lighttpd?

Actually it’s pretty easy using mod_evasive, a “very simplistic module to limit connections per IP”, as advertised on the lighttpd docs.

First, you must make sure that mod_evasive it’s enabled on the server.modules block:

server.modules = (
  "mod_access",
  "mod_alias",
  "mod_compress",
  "mod_redirect",
  "mod_rewrite",
  "mod_accesslog",
  "mod_evasive"
)

Then, on the main lighttpd config file you can add the following:

$HTTP["url"] =~ "/wp-admin/load-(styles|scripts).php(.*)" {
  evasive.max-conns-per-ip = 8
}

This will effectively limit the amount of allowed connections to 8 by IP. Of course, you can adjust that value to whatever you need; 8 connections by IP it’s plenty enough for a “normal” editor use.

You can test if it’s working by “attacking” your server with siege or ab or your favourite benchmarking/load testing tool and checking your lighttpd error log, where this should appear:

2018-03-22 21:05:53: (mod_evasive.c.183) 192.168.33.1 turned away. Too many connections.

After testing, you might also want to add this to the lighttpd config:

evasive.silent = "enabled"

… that way, blocked IPs won’t be logged on the errors.log (which, on its own could trigger a DoS by repeatedly writing to the log file)

If you’re using nginx with HTTP/2, there’s an even better way.

Filtering active menu element class on WordPress

When using a navigation menu on WordPress, you’ve probably seen the various HTML classes that are added on active elements, such as current-menu-item, current-menu-parent, current-menu-ancestor

While that kind of classes are fine if you must fully reflect the navigation hierarchy on the menu element, there are some times that you just need a more simple approach, such as just knowing when a certain menu element must look like the active item —for instance, when using Bootstrap.

For these kind of situations, you can use a simple filter to add such a class; something like:

<?php

add_filter('nav_menu_css_class', function ($classes, $item, $args, $depth) {
    // filter by some condition... for instance, only on the "main" menu
    if ( $args->theme_location !== 'main' ) {
        return $classes;
    }
    // all the different "active" classes added by WordPress
    $active = [
        'current-menu-item', 
        'current-menu-parent', 
        'current-menu-ancestor', 
        'current_page_item'
    ];
    // if anything matches, add the "active" class
    if ( array_intersect( $active, $classes ) ) {
        $classes[] = 'active';
    }
    return $classes;
}, 10, 4);