WordPress: large scale brute force attack

A brute force attack started last week and is targeting WordPress installations around the globe. The attack is not only performed by a few hosts but by a network of over 90,000 IP addresses.

A brute force attack is a method to gain login information. In this type of attack, discretion and efficiency plays no role at all. It involves going through a sequential search for login information. Through all these login attempts, the attack also increases the resource usage of the website. Once the login information have been acquired, a backdoor is usually installed and the host is then used as one more point from which brute force attacks can be carried out (the backdoor lets the attackers control the site remotely). Sometimes the backdoor is kept in there for a while without any other noticeable activities waiting for a larger attack to be launched.

In this concrete case, the attackers try to gain access using the default WordPress administrator account “admin” and try thousands of passwords. CloudFlare and HostGator reported a large scale attack. ClouFlare claims to have blocked 60 million requests just in an hour.

If you have a WordPress site, I’d suggest to:

  1. make sure both you Operating System and WordPress installations are up-to-date.
  2. not use “admin” as you administrator user name. Both the username and the password protect your site. If an attacker can easily find the username (because it’s ‘admin’ or ‘root’), then half the job is already done.
  3. make sure the password is strong enough.

Additional security measures can include:

  1. use some a Content Delivery Network with built-in security (like CloudFlare) or a security proxy (like Sucuri).
  2. use Two-Factor Authentication.
  3. limit the IP addresses which can access the login page.

Securely connect to a Linux server with putty and ssh key

First you need to download PuTTY and PuTTYgen from the PuTTY Download Page.

Then start puttygen:

Open puttygen

Make sure the type of key to generate is SSH-2 RSA and click on the Generate button:

puttygen generate key

As instructed, you’ll have to move the mouse randomly over the grey area. After some moving around, the key will be generated:

puttygen key generated

Now copy the key from the "Public key for pasting into OpenSSH authorized_keys file" text area. We’ll add it as an authorized key for the user on the Linux machine.

Now login to the Linux server (e.g. using putty) and type the following:

cd $HOME/.ssh
vi authorized_keys

If there are no keys defined for this user yet, the file will be created, otherwise there will already be entries in this file.
Press I to enter insert mode, if it’s not the first key you’ll have to add a newline here, then paste the copied key. Press :wq for saving and exiting.

If the file was newly created, we’ll need to make sure that only the current user can write in this file:

chmod g-w $HOME $HOME/.ssh $HOME/.ssh/authorized_keys

Now, in case it’s not already done, we’ll need to allow public keys as an authentication mechanism for ssh:

vi /etc/ssh/sshd_config

There make sure the lines are in there:

  • PubkeyAuthentication yes
  • AuthorizedKeysFile .ssh/authorized_keys

These lines are most probably in there but commented out. In this case just remove the hash sign before them.

If you also want to completely disable password based authentication (e.g. only use public keys), you can also set the following:

  • ChallengeResponseAuthentication no
  • PasswordAuthentication no
  • UsePAM no

If you’re afraid to do something wrong, you can also set these 3 parameters later on.
Then press :wq to save.

Then restart your ssh daemon to activate the new settings using one of the following commands (depending on your system):

rcsshd restart

service sshd restart

service ssh restart

/etc/rc.d/sshd restart

/etc/init.d/sshd restart

We’re done on the linux side. Let’s go back to puttygen. You can define now a passphrase if you want (it’s optional). Then press "Save private key" and choose an appropriate location on the disk. Now you can open putty:

putty

Type in the user name and host name or the IP address of the Linux server (e.g. root@192.168.190.157), then open the SSH node in the tree on the left hand side, then click on Auth:

putty ssh auth

Click on Browse and choose the private key file you’ve saved using puttygen.
Then click again on Session (at the top of the tree on the left hand side). Give the connection a name (in Saved Sessions) and press Save:

putty session saved

Now you can press Open and will be automatically logged in !

Linux: ssh – update your public key

If you need to update the public key you use for logging in to a server using ssh, you can do the following:

Just in case it’s a good idea to have a first shell open in parallel with a connection to the remote server:

ssh root@YOUR_SERVER_NAME

Replace YOUR_SERVER_NAME by the hostname or IP address of the remote server. If you login with another user than root, replace root by the appropriate user name.

Then open a new shell and go to the subdirectory where your keys are stored:

cd ~/.ssh

First you should first backup the existing keys in case you run into problems:

cp id_dsa id_dsa.OLD
cp id_dsa.pub id_dsa.pub.OLD

Then you can generate new keys. For this, you need to generate them using new files since you still need the old key in order to copy the new key to the server:

ssh-keygen -t dsa -f ~/.ssh/MY_NEW_KEY

Press Enter for each question asked.

This will create two files MY_NEW_KEY and MY_NEW_KEY.pub.

Now you need to copy the new public key to your server:

cat ~/.ssh/MY_NEW_KEY.pub | ssh root@YOUR_SERVER_NAME "cat >> ~/.ssh/authorized_keys" 

Now you have both public keys in the authorized_keys file on the server and you need to delete the old key from the file:

ssh root@YOUR_SERVER_NAME
vi ~/.ssh/authorized_keys

Then go to the line with the old key, press “dd” to delete the line and “ZZ” to save the file.

Then go back to your local shell:

exit

Now you can replace your old public key by the new one and test whether it still works:

mv MY_NEW_KEY id_dsa
mv MY_NEW_KEY.pub id_dsa.pub
ssh root@YOUR_SERVER_NAME

If nothing works anymore and you want to roll it all back, you can do the following:

In the second shell:

cat ~/.ssh/id_dsa.pub.OLD

Copy the output of “cat” and in the first shell:

vi ~/.ssh/authorized_keys

Then delete the new key (with “dd”) and paste the old key back in there (press “i” before pasting to get in insert mode and escape after pasting to exit insert mode, and then “ZZ” to save).

Intrusion Detection and Prevention Systems

IDS

An Intrusion Detection System (IDS) is a system for detection of attacks against a computer or a network. The IDS can complement a firewall complement or run directly on the monitored computer system.

There are two main types of IDS:

Host-based IDS: HIDS are installed on each system to be monitored. They thus have to support the given host operating system. They get information from log files, kernel data,…

Network-based IDS: NIDS try to capture all packets on the network, analyze them and report suspicious activities. These systems also try to recognize attack patterns in the network traffic.

Here are a few open source IDS:

Prelude : Linux

Samhain : Unix, Linux, Windows

Snort : Linux, Mac OS X, Windows

 

IPS

Intrusion Prevention Systems (IPS) are Intrusion Detection Systems (IDS) that can also defend against a specific attack.

 

HIPS

The acronym HIPS stands for “Host-based Intrusion Prevention System”. HIPS are IPS running on the computer on which intrusion is to be prevented.

HIPS hook themselves directly into the communication system and decide whether a packet should be forwarded or not (i.e. they can interrupt or pause data streams). They can also check the transferred data and block possibly harmful content.

Here’s a short list of open source HIPS:

Core Force (http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=project&name=Core_Force): it is not technically open source but the license allows it to be reverse engineered, disassembled or decompiled: Windows

DenyHOSTS : Linux, Mac OS X

Fail2ban : Linux, Mac OS X

OSSEC : Linux, Windows, FreeBSD, OpenBSD, NetBSD, Solaris, AIX, HP-UX, Mac OS X.

 

NIPS

NIPS (Network IPS) monitor the network traffic in order to protect the connected computer from intruders. They investigate either the content of the transmitted data, the transmissions at the protocol level and/or the type and amount of data traffic in order to indentify possible attack patterns and/or initiate network-related countermeasures.

Snort is the most well-known open source NIPS.

 

Using iptables to block brute force SSH scanning attacks

We saw everyday (and often multiple times a day) traces of brute force attacks on our server: many failed attempts to log into our server with SSH using the same or different usernames. Very often the username used were parts of domains hosted on our server. Only once did it succeed (on an old server we were about to get rid of and only had a few private domains) but even when they fail it’s just disturbing to have auth.log filled with thousands of message a day related to such attacks.

Of course in the beginning, we just started adding an iptables rule to drop packets from the IP address which kept coming up in auth.log:

# iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

It basically means  that all packets with the specified IP addressed will be dropped.

It is OK if it just happens once in a while but if have to do it for multiple IP addresses a day, it really calls for an automated solution. So we then introduced a script running as a cron job:

#!/bin/bash

IPLIST="/tmp/hack.ips.log"
ALREADYDENIED="/tmp/denied.ips.log"

MAIL="/usr/bin/mail"
EMAILS="henri.benoit@gmail.com xxx.xxx@googlemail.com"
TEMPLOG="/root/deny.ips.$$.log"

/sbin/iptables -n -L | /bin/grep DROP | awk '{ print $4; }' > $ALREADYDENIED

rm /tmp/hack.ip.*.log
grep -I "Invalid user " /var/log/auth.log* | awk '{ print $10; }' | sed '/^$/d' | awk '{ print $0 > "/tmp/hack.ip."$1".log" }'
wc -l /tmp/hack.ip.*.log | /bin/grep -v " total" | /bin/grep -v " insgesamt" | sed 's,/tmp/,,g' | sed 's/hack.ip.//g' | sed 's/.log//g' | awk '{ print $2" : "$1; }' | sort -k3 -n -r | /bin/grep " : [0-9][0-9]" | awk '{ print $1; }' > $IPLIST

while read line
do

if /bin/grep -Fxq "$line" $ALREADYDENIED
then
echo "Access already denied to IP address: $line"
else
echo "Denying access to IP address: $line" | tee -a $TEMPLOG
/sbin/iptables -A INPUT -s $line -j DROP | tee -a $TEMPLOG
fi

done < $IPLIST
echo "-------------------------------------------------------------"

if [ -s $TEMPLOG ] ; then
for EMAIL in $EMAILS
do
$MAIL -s "Denied access to some IP addresses" $EMAIL < $TEMPLOG
done
fi
rm -f $TEMPLOG

It basically goes through all auth.log* log files and looks for failed ssh login attempts and if an IP address is found at least 10 times (i.e. a two digits number of time), it will add an iptables rule. It also checks before that which DROP rules already exist so that we don’t add duplicate rules. In the end it sends me an email with the list of affected IP addresses.

This worked great. The only problem is that it adds quite a lot of rules to our firewall configuration. It has 2 main disadvantages:

  • At some point in time, the firewall will start needed much more time to start because of the thousands of rules.
  • When I list all rules, I get a huge list and need much more time to actually find what I need (and if I forget the -n argument and it start resolving IP addresses, it can last forever…).

So we decided to implement a few iptables rules to get rid of these guys temporarily and hope they’ll give up and it will save us a a permanent iptables rule. In order to do it , you need to be able to temporarily store who opened a connection to port 22 so that we can figure out whether it’s opening to many connections or not. This can be done using the iptables module “recent”. So for the following rules, you’ll need this module installed:

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 -j DROP

The first rule writes with the –set option the IP address of a new connection on port 22 and a time stamp in the proc file /proc/net/ipt_recent/DEFAULT.
The second rule adds with –update  another timestamp to the file and checks whether there were 5 timestamps within the last 60 seconds. If it is the case, the connection is dropped. These rules only affect SSH access, so other services might still be vulnerable.

Note that on the iptables level, we do not know whether the login with ssh failed or not so you might also sometimes temporarily lock out a user who just happened to need 5 connections and opened them all within 1 minute. But then he just needs to wait for a minute and things are fine again.

Using the combination of both the script above and the iptables rules above proved to work quite fine.

rkhunter: Warning: The file properties have changed

I’ve got a script running on a regular basis and executing rkhunter. After I finally got to installing all security updates on our new server, I started getting emails saying:

From: root
Subject: [rkhunter] Warnings found for …
Date: …
To: …

Please inspect this machine, because it may be infected.
And I found the following in /var/log/rkhunter.log: 

Warning: The file properties have changed:
File: /usr/bin/ldd
Current inode: xxx Stored inode: xxx
Current file modification time: xxx
Stored file modification time : xxx
(as well as for a few other files).
Now I didn’t really check in details which files were all changed by these security updates, so I had to check…

# dpkg -S /usr/bin/ldd
libc-bin: /usr/bin/ldd
OK, so ldd is the package: libc-bin
Now checking whether it was updated on that day

# grep libc-bin /var/log/dpkg.log | grep 2012-04-20
2012-04-20 21:08:43 upgrade libc-bin 2.11.3-2 2.11.3-3
2012-04-20 21:08:43 status half-configured libc-bin 2.11.3-2
2012-04-20 21:08:43 status unpacked libc-bin 2.11.3-2
2012-04-20 21:08:43 status half-installed libc-bin 2.11.3-2
2012-04-20 21:08:44 status half-installed libc-bin 2.11.3-2
2012-04-20 21:08:44 status half-installed libc-bin 2.11.3-2
2012-04-20 21:08:44 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:44 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:44 configure libc-bin 2.11.3-3 2.11.3-3
2012-04-20 21:08:44 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:44 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:44 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:45 status unpacked libc-bin 2.11.3-3
2012-04-20 21:08:45 status half-configured libc-bin 2.11.3-3
2012-04-20 21:08:45 status installed libc-bin 2.11.3-3
Yes, it was ! So everything is fine. I just need to let rkhunter know, that it should update its data regarding the files it monitors:

rkhunter –propupd
And the warnings were gone !

Root kit check as cron job and email notification

First, it’s always recommended to not use only one tool checking for root kits but multiples. Here is how to configure cron jobs to check the system everyday and email you the findings (only if something was found).

First rkhunter:

00 23 * * * (/usr/bin/rkhunter –versioncheck; /usr/bin/rkhunter –update; /usr/bin/rkhunter –cronjob –report-warnings-only)
This will first check for latest version of rkhunter (–versioncheck), check for updates to database files (–update) and then run rkhunter.

You can enter email address which should receive a message if something was found in /etc/rkhunter.conf:

MAIL-ON-WARNING=henri.benoit@gmail.com xxx.xxx@googlemail.com

00 23 * * * /usr/sbin/chkrootkit -q | grep -v “bindshell.*465)” > /tmp/chkrootkit.log && [ -s /tmp/chkrootkit.log ] && mail -s ‘chkrootkit findings’ henri.benoit@gmail.com xxx.xxx@googlemail.com < /tmp/chkrootkit.log


The grep -v part is only there because chkrootkit keep reporting that port 465 is infected when it is actually just postfix running… Other than that, the crontab line above will scan the system, write a log file and mail the contents of the log file if not empty.

chkrootkit: false positive, bindshell INFECTED Port 465

Just installed chkrootkit on our (relatively) new Debian Squeeze server and run it. Wasn’t expecting anything sind rkhunter reported everything was fine. But it did indeed report something:

# chkrootkit

Checking `bindshell’… INFECTED (PORTS: 465)



So checking what’s running on port 465:

# netstat -pan | grep “:465 ”
tcp 0 0 0.0.0.0:465 0.0.0.0:* LISTEN 8325/master
tcp6 0 0 :::465 :::* LISTEN 8325/master



Since I wasn’t too sure what this master was:

# ps -F -p 8325
UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
root 8325 1 0 9292 2404 6 Apr14 ? 00:00:17 /usr/lib/postfix/master



There it is, it’s nothing to worry about, just postfix…

So if a mailserver is running tls on port 465, chkrootkit wrongfully identifies bindshell.

If you stop postfix and rerun chkrootkit, nothing is reported:

# service postfix stop
Stopping Postfix Mail Transport Agent: postfix.
# chkrootkit | grep INFECTED
# service postfix start
Starting Postfix Mail Transport Agent: postfix.