What not to do when you’ve installed sshdfilter

sshdfilter is a great tool which monitors system logs for repetitive failed login attempts and actively updates iptables to block offending ip addresses. However, there is a slight shortfall it its design as there are no exceptions to its blocking rules as I found this morning:

Subject: sshdfilter event for 127.0.0.1, Too many password guesses, blocking
Date: Fri, 3 Mar 2006 11:04:02 +0000 (GMT)
From: root@lobstertechnology.com (root)

IP 127.0.0.1 was blocked, Too many password guesses, blocking.
Will remove block at Fri Mar 3 12:04:02 2006.

I almost cried, this one is worthy of being framed and put on the wall.

Firewalling against 127.0.0.1 is very very bad news on a unix system where there is a lot of loopback activity to run core services such as databases, x servers etc. I had a root shell open at the time and could flush the iptable rules to get back to some kind of normality.

Thankfully, Gerry has produced a patch allowing you to configure ‘trusted’ addresses which will never be blocked in this way. Hopefully it will make it to the core sshdfilter code in the near future.

Wordpress 2.0.3 ‘Bug Fix & Security Release’

Matt announced a release for Wordpress today on the Wordpress Development Blog. This release addresses several bugs and a security issue raised on Bugtraq.

Files changed in this release:

wp-admin/admin-db.php
wp-admin/admin-functions.php
wp-admin/admin.php
wp-admin/categories.php
wp-admin/cat-js.php
wp-admin/edit-comments.php
wp-admin/edit-form-advanced.php
wp-admin/edit-form-ajax-cat.php
wp-admin/edit-form-comment.php
wp-admin/edit-link-form.php
wp-admin/edit-page-form.php
wp-admin/edit-pages.php
wp-admin/edit.php
wp-admin/import/mt.php
wp-admin/inline-uploading.php
wp-admin/link-categories.php
wp-admin/link-import.php
wp-admin/link-manager.php
wp-admin/list-manipulation.js
wp-admin/list-manipulation.php
wp-admin/moderation.php
wp-admin/options-discussion.php
wp-admin/options-general.php
wp-admin/options-misc.php
wp-admin/options-permalink.php
wp-admin/options.php
wp-admin/options-reading.php
wp-admin/options-writing.php
wp-admin/page-new.php
wp-admin/plugin-editor.php
wp-admin/plugins.php
wp-admin/post.php
wp-admin/profile.php
wp-admin/profile-update.php
wp-admin/templates.php
wp-admin/theme-editor.php
wp-admin/themes.php
wp-admin/upgrade.php
wp-admin/upgrade-schema.php
wp-admin/user-edit.php
wp-admin/users.php
wp-comments-post.php
wp-content/plugins/akismet/akismet.php
wp-content/plugins/wp-db-backup.php
wp-includes/cache.php
wp-includes/capabilities.php
wp-includes/classes.php
wp-includes/comment-functions.php
wp-includes/default-filters.php
wp-includes/functions-compat.php
wp-includes/functions-formatting.php
wp-includes/functions.php
wp-includes/functions-post.php
wp-includes/kses.php
wp-includes/links.php
wp-includes/pluggable-functions.php
wp-includes/registration-functions.php
wp-includes/template-functions-general.php
wp-includes/template-functions-links.php
wp-includes/vars.php
wp-includes/version.php
wp-login.php

Unfortunately I havent had time to look into the security issue itself and detail its effects / how it has been patched, the post by Matt details the changes pretty comprehensively. I have however created a diff/patch from 2.0.2 to 2.0.3 and checked it into my SVN repository:

http://svn.lobstertechnology.com/wordpress-patches/wordpress-2.0.2-2.0.3.patch

You can apply this patch from the top directory of your Wordpress installation using the ‘patch’ program from a UNIX shell.

patch -p1 < wordpress-2.0.2-2.0.3.patch

However I haven’t yet personally tested patching up to 2.0.3 yet, I would suggest taking a backup first.

Patch to mod_evasive to enhance reporting

This morning I took the opportunity to install mod_evasive on my Apache Web Server after being hammered by zombies last night. Quote from [www.nuclearelephant.com]:

mod_evasive is an evasive maneuvers module for Apache to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack. It is also designed to be a detection and network management tool, and can be easily configured to talk to ipchains, firewalls, routers, and etcetera. mod_evasive presently reports abuses via email and syslog facilities.

It appears to work well, I tested it out by loading it up with small scale DoS attacks. It blocked the offending addresses as expected and produced the relevant syslog entires & triggered my external reporting script. I was however a little disappointed with its script execution functionality, it basically did a "system" call allowing you to pass only one argument - the offending IP address.

I already have mod_security installed which also executes an external reporting script. However mod_security has a neat little feature which I took for granted, it passes all the 'environment' variables from the request to the script allowing you to see the request itself & any headers passed.

For example, a typical mod_security email alert for me would contain:

DOCUMENT_ROOT=/usr/local/apache/vhosts/www.domain.com
GATEWAY_INTERFACE=CGI/1.1
HTTP_ACCEPT=*/*
HTTP_ACCEPT_ENCODING=gzip, x-gzip
HTTP_CONNECTION=close
HTTP_HOST=www.domain.com
HTTP_MOD_SECURITY_ACTION=500
HTTP_MOD_SECURITY_EXECUTED=/usr/local/scripts/modsec_alert.pl
HTTP_MOD_SECURITY_MESSAGE=Access denied with code 500. Error normalizing REQUEST_URI: Invalid URL encoding detected: not enough characters
HTTP_USER_AGENT=Mozilla/4.0
PATH=/bin:/sbin...
PATH_INFO=/search.cgi
PATH_TRANSLATED=/usr/local/scripts/modsec_alert.pl
QUERY_STRING=q='object+levels%
REDIRECT_STATUS=302
REMOTE_ADDR=XXX.XXX.XXX.XXX
REMOTE_PORT=45852
REQUEST_METHOD=GET
REQUEST_URI=/cgi-bin/search.cgi?q='object+levels%
SCRIPT_FILENAME=/usr/local/apache/vhosts/www.domain.com/cgi-bin
SCRIPT_NAME=/cgi-bin
SERVER_ADDR=XXX.XXX.XXX.XXX
SERVER_ADMIN=foo@bar
SERVER_NAME=www.domain.com
SERVER_PORT=80
SERVER_PROTOCOL=HTTP/1.1
SERVER_SIGNATURE=
SERVER_SOFTWARE=Apache

This shows me detailed information about the request which was declined and why. I wanted to get similar functionality out of mod_evasive and I achieved this with the following additional code (butchered from mod_security).

C++:
  1. if (sys_command != NULL) {
  2.   char **env = NULL;
  3.   const char *args[5];
  4.  
  5.   ap_add_cgi_vars(r);
  6.   ap_add_common_vars(r);
  7.  
  8.   env = (char **)ap_create_environment(r->pool, r->subprocess_env);
  9.  
  10.   ap_cleanup_for_exec();
  11.  
  12.   args[0] = filename;
  13.   args[1] = text_add;
  14.   args[2] = NULL;
  15.   execve(sys_command, (char ** const)&args, env);
  16. }

The original mod_evasive code is expecting a sprintf format string as the parameter 'sys_command' allowing you to define a position with '%s' where the IP address should be inserted. My code above does not to this, it expects 'sys_command' to be the path to the executable which takes a single argument of the IP address.

This change can be applied automagically - to the Apache 1.3.x version of mod_evasive.c only - with the following patch: mod_evasive_execve.patch

Assuming mod_evasive_1.10.1.tar.gz & mod_evasive_execve.patch have already been downloaded to the same directory:

[foo@bar ~]$ tar zxf mod_evasive_1.10.1.tar.gz
[foo@bar ~]$ cd mod_evasive
[foo@bar mod_evasive]$ patch -p1 < ../mod_evasive_execve.patch
patching file mod_evasive.c
[foo@bar mod_evasive]$ $APACHE_ROOT/bin/apxs -iac mod_evasive.c
gcc -DLINUX=22 -DEAPI -I/usr/include/gdbm -DUSE_HSREGEX -fpic -DEAPI -DSHARED_MODULE -I/usr/local/apache/include -c mod_evasive.c
gcc -shared -o mod_evasive.so mod_evasive.o
[activating module `evasive' in /usr/local/apache/conf/httpd.conf]
cp mod_evasive.so /usr/local/apache/libexec/mod_evasive.so
chmod 755 /usr/local/apache/libexec/mod_evasive.so
cp /usr/local/apache/conf/httpd.conf /usr/local/apache/conf/httpd.conf.bak
cp /usr/local/apache/conf/httpd.conf.new /usr/local/apache/conf/httpd.conf
rm /usr/local/apache/conf/httpd.conf.new
[foo@bar mod_evasive]$

Now create a simple shell/perl/something script to use this info. My example emails myself and the address listed as the SERVER_ADMIN, because each VirtualHost on my server has a 'ServerAdmin' entry with the owners email address, my customers get a copy of the email too.

PERL:
  1. #!/usr/bin/perl
  2. # /usr/local/scripts/mod_evasive_alert.pl
  3. $IP=$ARGV[0];
  4. $MSG="mod_evasive has blacklisted the IP $IP.\n\n";
  5.  
  6. foreach $key ( sort keys %ENV ) {
  7.    $MSG .= $key . "=" . $ENV{$key} . "\n";
  8. }
  9.  
  10. open(SENDMAIL, "|/usr/sbin/sendmail -t") or die "Cannot open sendmail: $!";
  11. print SENDMAIL "Reply-To: foo\@bar\n";
  12. print SENDMAIL "Subject: [lobstertechnology.com] mod_evasive alert $IP\n";
  13. print SENDMAIL "To: " . $ENV{'SERVER_ADMIN'} . "\n";
  14. print SENDMAIL "Cc: foo\@bar\n";
  15. print SENDMAIL "Content-type: text/plain\n\n";
  16. print SENDMAIL $MSG;
  17. close(SENDMAIL);

Now configure mod_evasive to execute your script when it is triggered, add the following to your $APACHE_ROOT/conf/httpd.conf:

CODE:
  1. <ifmodule mod_evasive.c>
  2.     DOSSystemCommand    "/usr/local/scripts/mod_evasive_alert.pl"
  3. </ifmodule>

Now restart Apache:

[foo@bar mod_evasive]$ $APACHE_ROOT/bin/apachectl restart
/usr/local/apache/bin/apachectl restart: httpd restarted

Tada! You're done. Use the 'test.pl' script provided by mod_evasive to trigger a blocking of your IP and see the email generated.

Wordpress 2.0.2 ‘Security Release’

Matt announced a security release for Wordpress today on the Wordpress Development Blog. This release addresses unannounced XSS problems apparently with comment posting & registration. The files affected by this release are:

wp-admin/admin-functions.php
wp-admin/admin-header.php
wp-admin/admin.php
wp-admin/edit-pages.php
wp-admin/import/blogger.php
wp-admin/list-manipulation.php
wp-admin/menu-header.php
wp-admin/post.php
wp-admin/user-edit.php
wp-comments-post.php
wp-includes/classes.php
wp-includes/comment-functions.php
wp-includes/functions.php
wp-includes/js/tinymce/langs/en.js
wp-includes/js/tinymce/plugins/wordpress/langs/en.js
wp-includes/js/tinymce/tiny_mce_gzip.php
wp-includes/template-functions-general.php
wp-includes/template-functions-links.php
wp-includes/version.php
wp-register.php
wp-settings.php

Here is a short summary of some of the notable changes:

wp-admin/admin-functions.php

- Forced default values of $_POST['comment_status'] = 'closed' & $_POST['ping_status'] = 'closed' when they are not set.
- Added escaping of attachment data-objects.
- Added escaping of posts data-objects.

wp-admin/admin-header.php

- Added check for 'manage_categories' privileges before showing the "Add" option to the category list while writing a post.

wp-admin/list-manipulation.php

- Abstracted deletion of links from direct SQL to a wp_delete_link method.

wp-admin/menu-header.php

- New 'admin_notices' Action allowing plugins to insert HTML immediately after the 'adminmenu' and 'submenu' <ul>'s. I think I'll be using that for my "New version of SpamKit available" messages.

wp-admin/post.php

- Additional HTTP Referrer checks using the 'check_admin_referer' method when submitting a new post, editing an attachment and editing a post.

wp-admin/user-edit.php

- Additional HTTP Referrer checks using the 'check_admin_referer' method when updating a User.

wp-includes/comment-functions.php

- Sanitising of user-submitted Name, Email & URL from cookies.

wp-register.php

- Forced blank default value of user-submitted email address & login name.
- Sanitising of the display of user-submitted email address & login.

I have created a patch to take 2.0.1 installations of Wordpress up to version 2.0.2 without having to reinstall and possibly loose customisations.

http://svn.lobstertechnology.com/wordpress-patches/wordpress-2.0.1-2.0.2.patch

You can apply this patch from the top directory of your Wordpress installation using the 'patch' program from a UNIX shell.

patch -p1 < wordpress-2.0.1-2.0.2.patch

Full Example Usage:

[michael@lobstertechnology ~] $ cd blog.lobstertechnology.com
[michael@lobstertechnology blog.lob...] $ patch -p1 < wordpress-2.0.1-2.0.2.patch
patching file wp-admin/admin-functions.php
patching file wp-admin/admin-header.php
patching file wp-admin/admin.php
patching file wp-admin/edit-pages.php
patching file wp-admin/import/blogger.php
patching file wp-admin/list-manipulation.php
patching file wp-admin/menu-header.php
patching file wp-admin/post.php
patching file wp-admin/user-edit.php
patching file wp-comments-post.php
patching file wp-includes/classes.php
...
[michael@lobstertechnology blog.lob...] $

Alternatively, you can simply replace only the files which have changed - listed above.

;)

Using sshdfilter to secure an SSH server

Since moving my OpenSSH server down to its standard port number I have been hit daily by service scanning software and brute force password attacks. Gerry pointed out that sshdfilter can help.

sshdfilter blocks the frequent brute force attacks on ssh daemons, it does this by directly reading the sshd logging output and generating iptables rules, the process can be quick enough to block an attack before they get a chance to enter any password at all.

It's quick and simple to setup, I enabled email alerts to see what it gets upto and can report it is all working fine on my servers (Red Hat 9 customised).

It will block when triggered by:

  • An attempt to login as a user which doesn't exist
  • After N failed attempts to login to an existing user account
  • If the incoming connection fails to provide an SSH version banner which is part of the SSH protocol, it's most likely a port scanner or dumb client
  • The length of time the block remains in place is all configurable.

    Brute force password attacks on Linux over SSH

    This is one of the main reasons I hate running SSH on the standard port numbers, every day I get log-alerts like these. As per usual I notify the originating ISP, at least I have an email template for it.

    Failed logins from these:
    invalid user abdul (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user abort (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user abs (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user adam (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user admin (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user admin (password) from 203.98.XXX.XXX: 14 Time(s)
    invalid user advertise (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user alan (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user alcatel (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user alex (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user alex (password) from 203.98.XXX.XXX: 6 Time(s)
    invalid user allan (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user aloha (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user alpha (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user alter (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user ameno (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user amman (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user andy (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user angel (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user antidot (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user apache (password) from 125.240.XXX.XXX: 30 Time(s)
    invalid user apache (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user ariane (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user aron (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user art (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user artificial (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user asahi (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user aspect (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user aspidistra (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user atempt (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user atilla (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user atom (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user aurel (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user avsadmin (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user azazel (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user backup (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user base (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user bash (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user beast (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user berg (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user beta (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user binary (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user black (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user bobo (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user bogdan (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user book (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user bourn (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user brett (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user brian (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user buche (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cable (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cache (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cain (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cambera (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user camelia (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cesna (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user chat (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user chris (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user church (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user clark (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user client (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user coffee (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user common (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user costel (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user costi (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user crack (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user cristina (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user cyclon (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dalton (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user danny (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user darling (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dasilva (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user data (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dave (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user david (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user david (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user davod (password) from 125.240.XXX.XXX: 2 Time(s)
    invalid user deserve (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user desire (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dns (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user domain (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user donna (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user dool (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user down (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dragon (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user dudu (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user earth (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user elixir (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user elvis (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user epsilon (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user eric (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user example (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user fadeh (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user fatih (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user fax (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user felix (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user fiat (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user filter (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user finale (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user fire (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user foon (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user ford (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user found (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user frank (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user freddy (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user ftpuser (password) from 125.240.XXX.XXX: 30 Time(s)
    invalid user gamma (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user ganja (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user gaspar (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user george (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user gerhard (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user ghost (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user gone (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user grand (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user granicus (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user gregory (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user grims (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user guest (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user guest (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user gushi (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user hang (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user hassan (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user health (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user helen (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user hell (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user helmut (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user heracle (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user honour (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user host (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user http (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user httpd (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user iarin (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user ident (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user include (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user info (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user info (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user iolanda (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user ion (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user ionut (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user irina (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jack (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user jamal (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user james (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user jasmina (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jason (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user java (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jeffrey (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jelem (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jenny (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user jerry (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user jessica (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user jessie (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user jhony (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user jiang (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jihad (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user jim (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user joe (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user john (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user john (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user jupiter (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user just (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user justice (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user justin (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user kadir (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user kain (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user kaleb (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user kelly (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user kevin (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user kevin (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user kline (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user koln (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user kondor (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user lampard (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user larry (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user laura (password) from 125.240.XXX.XXX: 16 Time(s)
    invalid user laura (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user law (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user lawyer (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user leroi (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user leslie (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user lex (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user library (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user library (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user light (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user lincoln (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user linda (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user linux (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user lisa (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user locco (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user lost (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user louis (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user louise (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user lucky (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user mailtest (password) from 125.240.XXX.XXX: 24 Time(s)
    invalid user malaga (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mano (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user maria (password) from 203.98.XXX.XXX: 6 Time(s)
    invalid user mariana (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mark (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user mark (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user marte (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user marty (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user mary (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user master (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user matt (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user media (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mercur (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mercury (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user michael (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mike (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user mike (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user mind (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user minerva (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mister (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mistero (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mobifon (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user mohamed (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mona (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user monaco (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user monica (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mooka (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user moon (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mount (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mrdev (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mumu (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user munis (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user mysql (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user mysql (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user nancy (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user neptun (password) from 203.98.XXX.XXX: 3 Time(s)
    invalid user nino (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user noise (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user nokia (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user office (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user okubo (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user omega (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user oracle (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user oracle (password) from 203.98.XXX.XXX: 10 Time(s)
    invalid user oracle1 (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user osama (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user osiris (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user osman (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user palm (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user panama (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user pascal (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user patricia (password) from 125.240.XXX.XXX: 12 Time(s)
    invalid user patrick (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user paul (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user paul (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user peter (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user pgsql (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user port (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user portal (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user postfix (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user postgres (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user public (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user quarter (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user rajev (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user read (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user rehash (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user relay (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user remove (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user rename (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user repection (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user request (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user resin (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user restore (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user richard (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user richard (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user road (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user robert (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user robin (password) from 125.240.XXX.XXX: 14 Time(s)
    invalid user roger (password) from 125.240.XXX.XXX: 18 Time(s)
    invalid user sales (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user sales (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user sam (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user samba (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user same (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sandy (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user sarah (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user saturn (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user scott (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user script (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user search (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user send (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user serafim (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user server (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user service (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user shadow (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user shake (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sharon (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user sharon (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user shell (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user shoot (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user shop (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user shrike (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sigmund (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user siliciu (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user silla (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user silva (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user silvia (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sirg (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user smash (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user smell (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user smuf (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user snake (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sole (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sombrero (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sorina (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sound (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user space (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sparc (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user spool (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sport (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user squad (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user staff (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user stanley (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user start (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user stealth (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user steel (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user stepfen (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user stephen (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user steve (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user steven (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user stick (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user storm (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user stream (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user student (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user student (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user sun (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user support (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user support (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user susan (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user susan (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user system (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user target (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user tay (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user temp (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user temp (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user tener (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user test (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user test (password) from 203.98.XXX.XXX: 14 Time(s)
    invalid user testuser (password) from 125.240.XXX.XXX: 26 Time(s)
    invalid user tetra (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user thanatos (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user thoor (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user tony (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user tony (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user torpe (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user track (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user travel (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user tristan (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user truth (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user unix (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user user (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user user (password) from 203.98.XXX.XXX: 16 Time(s)
    invalid user username (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user venus (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user verset (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user video (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user vincent (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user virtual (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user vision (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user visual (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user warez (password) from 203.98.XXX.XXX: 1 Time(s)
    invalid user web (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user webadmin (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user webadmin (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user webmaster (password) from 125.240.XXX.XXX: 28 Time(s)
    invalid user webmaster (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user while (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user white (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user william (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user willy (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user wish (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user write (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user www (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user www-data (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user wwwrun (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user yarrow (password) from 203.98.XXX.XXX: 2 Time(s)
    invalid user zed (password) from 203.98.XXX.XXX: 4 Time(s)
    invalid user zoom (password) from 203.98.XXX.XXX: 2 Time(s)
    root/password from 125.240.XXX.XXX: 30 Time(s)
    root/password from 203.98.XXX.XXX: 36 Time(s)

    Locked account login attempts:
    apache : 32 Time(s)
    mysql : 30 Time(s)
    postfix : 26 Time(s)

    However, my favourite ones are still the bots that try talking HTTP to my SMTP server:

    unknown[61.128.XXX.XXX] sent non-SMTP command: POST / HTTP/1.1 : 1 Time(s)