0

Locking Down WordPress WP-Admin

I’m pretty sure every WordPress [1] user out there has read much about different ways to limit access to the WordPress administration back-end (WP-Admin), and many of them are certainly good. My way is quite simple, although it most likely has a couple of penalties and some pitfalls I’m not yet aware of, but I can live with it.

My procedure of locking down the WP-Admin area consists of running Nginx [2] on a dedicated port (whichever port you prefer) bound to a internal/private/local IP address (i.e 127.0.0.1, 192.168.0.1 et cetera), configured with PHP-FPM, coupled with Apache2 as the front-end (with mod_proxy [3] enabled) to serve and process all requests to the WordPress administrative back-end. The requests are proxied to the Nginx instance via Apache. This configuration effectively translates to the following: I only keep Nginx running whenever I access the administration back-end of WordPress (WP-Admin), and when I’m done, I simply shutdown Nginx. Simple. The end result is that nobody will be able to access the WP-Admin area if Nginx isn’t running.

The only issues I have run into so far is that static resources are not being served properly, but that should be easy a fix. I’m looking into it.

Try accessing the WP-Admin area of k0nsl.org and see the result:
https://k0nsl.org/blog/wp-admin/

k0nsl-backend-down01

Everything in “/blog/wp-admin” results in a 503 ‘Service Temporarily Unavailable’ (check the headers with “curl -I https://k0nsl.org/wp-admin”) because Nginx is shutdown. It certainly is a simple solution; but it works

This configuration above coupled with various other tweaks (such as the CloudFlare-Country-Login [4]) makes WordPress a bit more secure to use.

Update: 11.21.13

I solved the assets issue not being served properly JS too; Earlier, I had accidentally forgot to enable Javascript concatenation by commenting out CONCATENATE_SCRIPTS define in wp-config.php. Everything works perfectly right now.

Notes

1. WordPress: Blog Tool, Publishing Platform, and CMS -> http://wordpress.org/
2. Nginx: The High Performance Reverse Proxy, Load Balancer, Edge Cache, Origin Server -> http://nginx.com/products/
3. Apache Module mod_proxy -> http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
4. WordPress: CloudFlare-Country-Login -> https://k0nsl.org/blog/wordpress-cloudflare-country-login/

2

Update on k0nsl.org

I wiped the entire server and relocated k0nsl.org onto a container because I realized that I did not need all the resources of ‘Eicke’ allocated soley for k0nsl.org. I ran Centos on it earlier, but now it runs a Debianesque fork as the base system and nginx+fastcgi for web without a proxied stack. I just didn’t need all the fancy pantsy extra bits and pieces, maybe in the future if there is a huge increase of daily visitors. However, to my surprise I discovered that my database repository was outdated by a few hours so I lost a bit of information in the process, other than that not much was lost, and most things appear to be working fine — except for the ServerStatus page, it needs attention (borked). All in all it was another more or less perfect migration. I’m happy with it.
The container which k0nsl is on is codnamed ‘gl0bocnik’ with regards to the limited resources:
gl0bocnik01_k0nsl
Quite restrained! However, I can always increase it when it needs more.
(PS: the memory output is incorrect – in reality only 397.31 MB is currently being used.)

Update 11/18/13

I got rid of php-fastcgi and replaced it with Dotdeb’s php5-fpm:
k0nsl-org-php5-fpm01_k0nsl
And I also upgraded nginx:
k0nsl-org-nginx01_k0nsl

Update 11/19/13

Temporarily switched to Apache2. Took awhile to figure out the issue I had (permissions and latent cache can be tricky sometimes ).
Oh well, it’s all good. Any issues? Send me an e-mail: i.am@k0nsl.org

0

Stack changes for k0nsl

I am again experimenting with the Cherokee [1] web server in my stack for k0nsl.org — it currently handles the PHP backend of it all, which so far seems to be working quite nice. Nginx is used as frontend and for most static files, finally Apache2 is used for miscellaneous tasks. The last time I used Cherokee for my projects was briefly in October of last year (2012).

I will investigate more as time goes on, but it looks as if I will be using Cherokee permanently in the stack.

Notes

1. Cherokee is a flexible, very fast, lightweight Web server. It is implemented entirely in C, and has no dependencies beyond a standard C library. It is embeddable and extensible with plug-ins. It supports on-the-fly configuration, TLS/SSL, virtual hosts, authentication, cache friendly features, PHP, custom error management, several load balancing policies, database balancing, and much more. Check out their Github for more information: https://github.com/cherokee/webserver/

1

Cdorked.A Inspector

Below is a tool written by Marc-Etienne M.Léveillé of ESET to check for the existence of Linux/Cdorked.A [1]

// This program dumps the content of a shared memory block
// used by Linux/Cdorked.A into a file named httpd_cdorked_config.bin
// when the machine is infected.
//
// Some of the data is encrypted. If your server is infected and you
// would like to help, please send the httpd_cdorked_config.bin
// and your httpd executable to our lab for analysis. Thanks!
//
// Build with gcc -o dump_cdorked_config dump_cdorked_config.c
//
// Marc-Etienne M.Léveillé
//

#include <stdio.h>
#include <sys/shm.h>

#define CDORKED_SHM_SIZE (6118512)
#define CDORKED_OUTFILE "httpd_cdorked_config.bin"

int main (int argc, char *argv[]) {
    int maxkey, id, shmid, infected = 0;
    struct shm_info shm_info;
    struct shmid_ds shmds;
    void * cdorked_data;
    FILE * outfile;
    
    maxkey = shmctl(0, SHM_INFO, (void *) &shm_info);
    for(id = 0; id <= maxkey; id++) {
        shmid = shmctl(id, SHM_STAT, &shmds);
        if (shmid < 0)
            continue;
        
        if(shmds.shm_segsz == CDORKED_SHM_SIZE) {
            // We have a matching Cdorked memory segment
            infected++;
            printf("A shared memory matching Cdorked signature was found.\n");
            printf("You should check your HTTP server's executable file integrity.\n");
            
            cdorked_data = shmat(shmid, NULL, 0666);
            if(cdorked_data != NULL) {
                outfile = fopen(CDORKED_OUTFILE, "wb");
                if(outfile == NULL) {
                    printf("Could not open file %s for writing.", CDORKED_OUTFILE);
                }
                else {
                    fwrite(cdorked_data, CDORKED_SHM_SIZE, 1, outfile);
                    fclose(outfile);
                    
                    printf("The Cdorked configuration was dumped in the %s file.\n\n", CDORKED_OUTFILE);
                }
            }
        }
    }
    if(infected == 0) {
        printf("No shared memory matching Cdorked signature was found.\n");
        printf("To further verify your server, run \"ipcs -m -p\" and look");
        printf(" for a memory segments created by your http server.\n");
    }
    else {
        printf("If you would like to help us in our research on Cdorked, ");
        printf("please send the httpd_cdorked_config.bin and your httpd executable file ");
        printf("to our lab for analysis at eset.com. Thanks!\n");
    }
    return infected;
}
Notes

1. Linux/Cdorked.A: New Apache backdoor being used in the wild to serve Blackhole

5

phpBB3 Pretty URLs & nginx

So I was working with a client who needed human-readable URLs (or SEO URLs, clean URLs, or whatever you like to call it) for his forum which is running phpBB3 coupled with nginx as the webserver. He didn’t know of any easy way to deal with that. I knew of pre-existing modifications and one in particular that works very well and which has a minimal footprint, it is called “Pretty URLs” by Sam and it uses hooks to do the magic.

The only thing I really had to do was to create the rewrite rules for nginx because it had only been tested with Apache, so here are the rewrites for nginx:

I guess that’s about it.

0

Proxy Configuration for k0nsl.org

NGINX Web server NGINX Web server

Here’s my very simple proxy configuration for k0nsl.org with an upstream declared which contains one additional server for backup. This configuration only shows parts of the entire nginx configuration, here’s the gist of it:

 

 

I know the timeout is a bit high, but it was necessary for something specific I did – will lower it later.