PHP: Protection public cron jobs
Programmers often forget to protect cron jobs that are executed in public addresses. Especially if you have shared hosting, it is usually difficult to secure run cron tasks.
However, if the cron is on publicly url, can this cron job starts anyone. If this one know which URL address enter into browser.
1. Secret variable
“Emergency measure” to secure calls is to use a secret variables that will never be known. This solution is not very good, but sometimes there is no alternative. Especially on shared hosting.
Simply create a cron job in crontab them to add your own variables:
1 |
* * * * * cron.php?phrase=YOURKEYHERE |
In PHP file we can now simply check, if this variable agree with our value:
1 |
if( $_GET['phrase'] !== 'YOURKEYHERE') die('access is not permitted'); |
This solution is not very secure. Anyone can find the value of variables and cron job run from browser.
2. Environment variable
Similar solution like secret variable is enviroment variable. This variable is set directly in crontab:
1 2 3 |
SCRIPT_RUN_ENV=cronjob * * * * * cron.php |
Now you can easily check if a variable exists:
1 2 3 |
if (get_env('SCRIPT_RUN_ENV') != 'cron') { die('access is not permitted'); } |
This solution is slightly better, but again, it is possible that someone find out the value. Problem may be that not everywhere have access directly to the crontab.
3. Checking IP addresses
Another possible solution is to check whether cron is run from a server enviroment. In this case we distinguish two different options:
- Script is running from localhost (127.0.0.1)
- Script is running from public url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//from public url if( $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR'] ){ die('access is not permitted'); } //from localhost if( $_SERVER['REMOTE_ADDR'] != "127.0.0.1" ){ die('access is not permitted'); } //together if( $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR'] || $_SERVER['REMOTE_ADDR'] != "127.0.0.1" ){ die('access is not permitted'); } |
4. Use .htaccess
Use protection with htaccess is actually similar to the previous solution with checking IP address. We define the conditions for an IP address. In this case, however, the problem may be, for example, if you use some framework that creates URLs dynamically.
1 2 3 4 5 6 7 |
<Files "cron.php"> Order deny,allow Allow from THIS_SERVER Allow from ANOTHER_ALLOWED_SERVER Allow from 127.0.0.1 Deny from all </Files> |
5. Cron jobs outside public html
Probably the best solution is to place cron jobs outside public directory.
1 2 3 4 5 |
- project - app - lib - cron - public_html |
In this case it is not possible to run scripts publicly from browser.
Conclusion
Do you have any better solution to use?
php_sapi_name() === ‘cli’
Thanks you, I was looking for something like this.
I think I’ll combined some of these solutions 🙂
Thanks for this tutorial, but this looks like a long process and not for a beginner like me. Is there any easier way to do this or the easier alternative is to use Cloudways like platform to schedule cron jobs in php easily (an example: https://www.cloudways.com/blog/schedule-cron-jobs-in-php/)?
Thanks for this tutorial, but this looks like a long process and not for a beginner like me. Is there any easier way to do this or the easier alternative is to use Cloudways like platform to schedule cron jobs in php easily (an example: https://www.cloudways.com/blog/schedule-cron-jobs-in-php/)