Hi!

How can I secure cron.php from remote invocation by malicious users?
If cron.php is publicly available, anobody can run it. Is it secure?

Thanks!

Comments

markus_petrux’s picture

I did the following:

  1. In my .htaccess file I entered the following command:
    <Files  "cron.php">
    	Order deny,allow
    	Deny from all
    </Files>
    

  2. Setup the cron as follows:
    cd /path-to-my-drupal-directory; /path-to-php/php cron.php
    

So, it is not possible to invoke the cron from the browser, it is executed via command line (ie. using PHP itself not via wget).

HTH+

Doubt is the beginning, not the end of wisdom.

el777’s picture

I guess there's sme difference between runing php via apache and via commnad line interface. In the latter case script dooesn't have any HTTP settings (for example domain or all features in settings.php file tied to domain), so it has no all information about the drupal instance. Or cron.php doesn't rquire them in any way?

Thank you!

markus_petrux’s picture

All I can say is I'm using the above mentioned method in 2 different sites w/o problems. Probably, cron.php does not need anything dependent on base_url. It seems to me all output (if any) goes to the log.

If there was a problem, it would still be possible to use wget and still protect cron.php against foreign access by adding "allow from 127.0.0.1" to the .htccess block described above.

Doubt is the beginning, not the end of wisdom.

mooffie’s picture

cron.php does not need anything dependent on base_url.

Without a correct $base_url, the url() function will fail to generate absolute URLs. This should especially concern you if some subscription module sends emails in hook_cron()... the URLs in the emails will faulty.

zakmck’s picture

I prefer to invoke it via http, so I am using this variant:

<Files "cron.php">
  Order deny,allow
  Allow from name.of.this.machine
  Allow from another.authorized.name.net
  Allow from 127.0.0.1
  Deny from all
</Files>

Now cron.php is run only if requested from the server.

MarcoR’s picture

This is a very fine solution! The alternative (renaming cron.php) prevents cron to be used from Drupal's user interface. Additionally, "security by obscurity" should be kept outside of Open Source projects, think of our reputation! ;)

The only disadvantage I see is that it is a little harder to upgrade Drupal, because the changes in .htaccess are lost.
How could one put this into apache's httpd.conf? Or will this be ignored due to the .htaccess file?

mooffie’s picture

The alternative (renaming cron.php) prevents cron to be used from Drupal's user interface.

That was the case in D 4.7.
In D 5.0 you can safely rename cron.php.

(but, yes, access control is a nicer soluiton.)

How could one put this into apache's httpd.conf?

As is.

Daniel Norton’s picture

But that allows it to be used by any user on the server.

zakmck’s picture

yes, that opens up the access to cron.php to all users coming from an assigned IP. I trust the users I have on Drupal servers, simply because these are either me or a few trusted developers working with me. However, if I had the problem of authorising specific users, Apache directives allows one to do that too (http://www.addedbytes.com/lab/password-protect-a-directory-with-htaccess/).

steff2009’s picture

Hi, I want to protect my cron.php from unauthorized access. I placed "cron" in filesmatch line of .htaccess as suggested by video http://drupal.org/node/347981. But it doesn't work as still I am getting cron jobs run anonymously very often.

I now want to implement your suggestion given at http://drupal.org/cron to protect the file by adding the following lines in .htaccess:

<Files "cron.php">
        Order Deny,Allow
        Deny from all
        Allow from localhost
        Allow from 127.0.0.1
</Files>

Now when I try to visit page www.example.com/cron.php, I get a 403 message directly from the server (not from my Drupal site), so this means that it works and blocks cron access from other IPs.

However I'm wondering if this creates conflicts with Poormanscron, as the module uses random page requests from site users to launch cron job. As all those IP addresses will not be authorized to run cron, will users receive a 403 or will cron be run normally via Poormanscron?

Thank you for your opinion and support.

macgirvin’s picture

The cron module does not do anything that can be easily mis-used. It merely invokes module methods to see if anything is scheduled for updates and processes them. The most serious side effect is that some information might be updated in advance of your normally scheduled cron run, but only those updates which were already pending and ready to happen.

The only potential I can see for abuse is if any modules aren't prepared for race conditions and more than one cron is running simultaneously. This 'shouldn't happen' if the modules have been written correctly but is entirely possible given the large number of not-quite-stable modules and development projects going on.

Protecting it completely would involve configuration of your web server to disallow access to this page from any site but your own (the one running the cron daemon). If memory serves, this would require allow,deny rules if using Apache.

zakmck’s picture

I am afraid of DoS attacks. tasks in cron.php should be time consuming, at least potentially, so it would be easy to slow down a server by calling it repeatedly. Not sure I am correct, however another point is that in principle I don't like the idea that the world can run my administration routines...

pamphile’s picture

Warning: This is not elegant or upgradeable...

You could also edit the cron.php so that a password is required for it to execute.

http://example.com/cron.php?password=mypassword

Then you use simple PHP to restrict or allow access to the rest of cron.php

Marcel
http://drupalhacks.com
http://drupalthemes.com - soon

andre75’s picture

I have set up cron like this:
19 */8 * * * /usr/local/bin/php pathtomysite/cron.php

Since this does not involve a browser (lynx, wget, curl ...) I should be able to set the permissions to 600. I am not sure if this will actually prevent it from being accessed through a webbrowser.

Andre

mgifford’s picture

This won't work with a mult-site install unfortunately.

Wouldn't the concerns about cron.php file be resolved if an administrator could just set how often they wanted cron to run and if the default config were set to return null if cron.php was loaded more than once a minute? That would both be a reasonable amount of time for most hyper active webhosts, but would also close down this concern about cron.php being used to DOS a site.

--

OpenConcept | WLP | FVC | OX | OO

venkat-rk’s picture

I have read suggestions in the forums of my hosting company about simply renaming cron.php to something else to avoid security issues.

wellsy’s picture

It also works.

Upgrading issues also would not be a problem for a user who knew enough to change the name in the first place.

wellsy

orchidsonline.com.au

ideviate’s picture

hehe, i renamed and got rid of the cron.php problem,thanx :D

powered by Drupal www.universideliyiz.biz

alihammad’s picture

I use a $_GET value, In the cron I use an if statement followed to check if the provided get value equals my code. On success it runs the cron else it doesn't. With my host config I enter the cron path with the get value attached. So, nobody except me or the host knows that it requires a get value. Works for me!

Ali Hammad Raza
WordsValley

codenamerhubarb’s picture

Could you just move your cron.php file/s from the public_html folder of your server to another folder, e.g. go up one level from pubic_html and make a new folder called cron then place all your cron php files in there.
-------------------------------
My Drupal site: Download a Book.

-------------------------------
My Drupal site: Download a Book.

xgretsch’s picture

I went for putting some code in the cron file that allows it to be run from the server the site is on, or from the webmaster's account:

include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
if($_SERVER[REMOTE_ADDR]!=$_SERVER[SERVER_ADDR] && $user->uid!=1){
  watchdog("Security alert","Attempt to run cron by user ".$user->uid." from IP address ".$_SERVER[REMOTE_ADDR],
  	WATCHDOG_WARNING);
  exit;	
}
drupal_cron_run();

And yes, it did happen: someone external was running my cron file. I have some stuff in custom modules that was sending out alert e-mails, supposedly on a daily basis, and it was doing quite a lot of database access, so I didn't want it running at random times!

xgretsch (my website: www.bachtrack.com)

ShaunDychko’s picture

The edit that works for me in the .htaccess file is:


Order deny,allow
Allow from THE_IP_ADDRESS_OF_MY_SERVER
Deny from all

The IP_ADDRESS_OF_MY_SERVER is not the usual localhost IP of 127.0.0.1, but rather the IP of my web hosting account. In cPanel this is shown in the left column titled "stats" in the row titled "Shared Ip Address:"

The command I use in cron is:

wget http://MY_DOMAIN_NAME/cron.php

silkogelman’s picture

Elysia cron has a very nice option to avoid external cron calling.
It allows you to setup a cron key and allowed hosts from within a nice Drupal module.
http://drupal.org/project/elysia_cron

sucka666’s picture

Put in htaccess

<Files  "cron.php">
Order deny,allow
Deny from all
Allow from 127.0.0.1
Allow from localhost
</Files>

And in cpanel or what you are using put the cron command like this:

php /home/username/public_html/cron.php
Codenext’s picture

Hi, is this code valid for drupal 8 also? Thanks