• If you are still using CentOS 7.9, it's time to convert to Alma 8 with the free centos2alma tool by Plesk or Plesk Migrator. Please let us know your experiences or concerns in this thread:
    CentOS2Alma discussion

Issue How can a PHP script in a chrooted, shell_exec/exec/system disabled environment create a crontab job in Plesk?

Bitpalast

Plesk addicted!
Plesk Guru
Server operating system version
CentOS 7.9
Plesk version and microupdate number
Obsidian 18.0.43
This morning we've seen three cases in different machines and customer subscriptions where a script running in a customer website has uploaded an executable to /var/tmp and then created a cron job in Plesk to execute the file (as exec, shell_exec, system etc. commands in PHP are disabled here). The purpose of the execution was to run a stand-alone sendmail instance. Not only the PHP execution commands are blocked, but the customers are chrooted, too.

How is this possible and how can we prevent scripts from creating crontab jobs in Plesk?
 
and then created a cron job in Plesk to execute the file
Peter, there is no such thing as a ‘cronjob in Plesk’ - Plesk works with what is in the system. And Plesk works through crontab -u xxxx
Or do you mean that the script created it through Plesk API?
In addition, scripts that are executed via the web are not executed in a chroot.
So, I think that you need to look at exactly how PHP is configured in order to understand how it was possible to exploit.
 
That is what I thought, too. For some reason in the cron job page in Plesk these jobs showed up

Task type "Run a command"
Command "/var/tmp/HMsAVVEzi >/dev/null 2>&1"
every 8 minutes

(with a variation of the temporary file name on different subscriptions)

which results in commands in the system like

*/8 * * * * perl /var/tmp/HMsAVVEzi >/dev/null 2>&1

We do not understand how these jobs are being created. The Plesk API (the one from panel.ini) is disabled on our servers for security reasons. It is not possible that a customer has installed it, because this has happend within 1 hour on three different servers in 3 different subscriptions of different persons. It is not possible to run crontab through the chrooted SSH either. Our general /tmp partition on the servers is execution-protected, so it cannot be the culprit either. I do not see an xferlog entry of the affected accounts, so the file has not been uploaded through FTP, but must have been uploaded through a website script/POST. The temporary file is long gone, so we cannot look into that what it is doing.

The big question remains: How were these cron jobs created?

Currently - if this cannot be done by for example writing a file through PHP to a specific location in a user subscription or creating something through a port - the only explanation I can find is that the customer has lost his web space panel data to a hacker and either the hacker logged in manually (very unlikely) or a script is doing a login and creating the job as if it was a human who is interacting with Plesk.
 
P.S.: The program that was executed was run under the subscription user who is chrooted, so this cannot be a root level issue.
 
Peter, I afraid that deep investigation directly on server is required. So, ticket shoud be submitted.
 
Thank you @IgorG for your tireless effort here on the forum. I have opened a ticket now, but only a general description as for the affected servers I don't have support contracts. Maybe they have someone in their group who knows the trick.
 
Well, I assume that the crons got created with a simple PHP script that writes a file to /var/spool/cron/crontabs/XXXX
If you think that open_basedir should prevent that, then you are wrong, as that directive can be circumvented easily by some "malicious" code lines in a php script.

So, once an attacker can upload and execute it's own php script on your server, he can then create such cronjobs, despite any open_basedir directives or disabled commands.
 
Well, I assume that the crons got created with a simple PHP script that writes a file to /var/spool/cron/crontabs/XXXX
If you think that open_basedir should prevent that, then you are wrong, as that directive can be circumvented easily by some "malicious" code lines in a php script.

So, once an attacker can upload and execute it's own php script on your server, he can then create such cronjobs, despite any open_basedir directives or disabled commands.
I want to learn how to do it. Can you point me into the right direction? So far I have not been able to create files outside the subscription when open_basedir is in effect.
 
If you don't need to allow your customers to use cronjobs at all, you can remove all permissions (chmod 000) on the /var/spool/cron/crontabs directory

We use that ourselves on some specific servers, but it will force you to manually create/edit/manage/delete all required cronjobs in /etc/cron.d/xxx files
 
Yes, indeed. I just tested it here through all versions. Only PHP versions <7.4 are affected.
The fix for earlier versions is to disable ini_set.
 
uhhh, I don't wanna know, how many scripts and cms software no longer run properly, when ini_set is disabled :D
Though maybe in combination with display_errors=off, it may not be that bad
 
Further analysis has shown that the /var/spool/cron directory is only accessible for root and that in one case with PHP version 7.4 the issue re-occured. So while the ini_set() bug vor versions <7.4 is one security gap, there is probably another one through which a cron job can be created without having root privileges or API access.
 
Maybe there is a way to circumvent the (exec/shell_exec) function restriction of PHP and then using /usr/bin/crontab to create these files?

There are/were several ways to bypass PHP's disable_function() as well, though I have no idea how many of them are still working with recent PHP versions.
 
It's a frequently overlooked issue -- shell, jailing, and PHP. Ultimately, disable_func + open_basedir isn't really sufficient security, because of exploits above, but also complete isolation not being its intended purpose.

Are you using CL by chance? "CageFS"'s underlying implementation is running PHP synthetically rooted, and therefore you can disable bash, revoke certain directory perms/make them ro.

In doing so, open_basedir and disable_func become obsolete so you no longer have to deal with those issues. I'd strongly consider CL if not using it, or a custom implementation. open_basedir comes with a performance penalty too.
 
Back
Top