How We Ran an SSH Command from Joomla

Note: This post is very advanced, and requires some Linux shell experience. If you feel that your experience is not up to the suggestions below, then we suggest that you ask some experts to do it for you.

Another note: Please read the post to the end before performing any work.

Recently, Apache‘s ModSecurity has become quite aggressive in blocking suspicious requests. Most of our major clients are finding its new behavior (ModSecurity‘s behavior) annoying, since it’s often blocking their IPs when they inadvertently trigger a security rule. Whenever that happens, they call us and we will need to unblock them by ssh’ing to the server and running the following commands:

csf -dr [our-client-ip]
csf -r

The first command drops (hence the dr) from the CSF database, and the second command refreshes CSF and is needed to re-allow access for the blocked IP.

But what is CSF?

CSF, in case you’re wondering, stands for ConfigServer Security & Firewall, and it’s the tool that effectively does the IP blocking (often at the request of ModSecurity, but it has its own blocking rules as well, such as when an IP tries to FTP with the wrong password, or tries to access an htpasswd protected area with the wrong password). CSF is installed by default on almost all Linux servers, as it is critical for any server’s security and stability.

But what is the problem with the above?

We typically process the unblock requests instantly, and by instantly we mean by the time we get the email, which can take anything between a minute and 15 minutes, and during those minutes the client can’t access their own website from their network. Not good!

So, while the above process works, it is not ideal for the client since it makes us the bottleneck, and clients aren’t very fond of that. We had to develop a method that allowed our major clients to unblock themselves from within the Joomla website. But there were 2 challenges:

  1. If they are blocked at the server level, then how can they access the Joomla backend to unblock themselves?
  2. csf unblocking commands require root access for successful execution, which means that we have to run the ssh2_exec PHP function, which means that we have to install the libssh2 PHP library, which may pose a major security threat to the server.

So, how did we overcome the issues above?

The first issue was easy to address – all that we needed to do was to ask the client to ask a team member to access the website using his mobile data connection, which typically uses a different, unblocked IP.

The second issue was trickier: first we needed to install the libssh2 on the server (and this is not a straightforward task, take our word for it), and then we had to create the following script:

$ourClientIP = $_POST['ourClientIP']; //The client IP to unblock is submitted using a simple form
if (!filter_var($ourClientIP, FILTER_VALIDATE_IP)) {
	die('Invalid IP');
}
$sshConnection = ssh2_connect('ourclientjoomlawebsite.com', 22);  //22 is the default ssh port, many servers elect to use a different port for security reasons
ssh2_auth_password($sshConnection , 'root', 'rootPassword');
ssh2_exec($sshConnection , 'csf -dr '.$ourClientIP);
ssh2_exec($sshConnection , 'csf -r');

The above code is fine and dandy, but there is one problem with it, one super-major problem: we are exposing the root password in a PHP script file, which means that any developer with FTP access to the Joomla website will be able to know what the root password is. Additionally, if the Joomla website has any exploit, then a malicious user will gain access to the script, and will be able to know what the root password is.

But, we are always ingenious (and humble!), and so we devised a way that allowed our client to unblock their IP without compromising server’s security. Here’s how:

  • We created a simple (htpasswd protected) form where the user enters the IP to unblock. Once the IP is entered, we save it in a text file called unblock.txt, which is located under the administrator folder.
  • In ssh, we ran the following command:

    crontab -e

    and then we added the following line to the very end (and then saved the cron):

    * * * * * if ls /home/[user]/public_html/administrator/unblock.txt > /dev/null 2>&1; then value=`cat /home/[user]/public_html/administrator/unblock.txt`;/usr/sbin/csf -g "$value";/usr/sbin/csf -dr "$value";/usr/sbin/csf -r;rm -f /home/[user]/public_html/administrator/unblock.txt; fi

The above 1-minute cron command does the following: 1) it grabs the IP to unblock from the blocked.txt file, 2) it checks if the IP already exists in the CSF database (unnecessary step), 3) it then removes the IP, and, 4) it finally refreshes the CSF database and removes the unblock.txt file. Of course, these steps are only performed when the unblock.txt file exists.

By implementing this simple logic in the cron, we avoided installing an additional PHP library and, much more importantly, we ensured that the root password remained “secret”.

Now, if you want to run a different ssh command from your Joomla website, then just follow the instructions above, it will work! If it doesn’t, then please contact us. We will help you do this in no time and for a super affordable fee!

No comments yet.

Leave a comment