Recommended Services
Supported Scripts
Secure Your CMS by Disabling Dangerous PHP Functions

One of the most effective ways to harden any CMS — WordPress, Joomla, Drupal, or Magento — is to disable the dangerous PHP functions that attackers rely on. When a site is compromised through a vulnerable plugin or theme, the attacker’s malware almost always tries to call functions like exec(), shell_exec(), or system() to run commands, drop backdoors, or pivot across accounts. If those functions are disabled at the PHP level, most automated exploits simply fail. This guide shows you which functions to disable per CMS (because each one needs a slightly different set), and exactly how to apply it on cPanel, Plesk, CWP (CentOS Web Panel) Pro, and DirectAdmin.

Why Disable PHP Functions at All?

A normal CMS website renders pages, queries a database, and sends email. It almost never needs to execute operating-system commands. But many PHP functions can execute commands, read arbitrary files, or spawn processes — and these are exactly what malware uploaded through a hacked plugin abuses. Disabling them removes the attacker’s toolkit without affecting how your website works for visitors.

The Dangerous PHP Functions

FunctionWhat It DoesRisk
execExecutes an external programRun shell commands
shell_execExecutes a command via shell, returns outputRun shell commands
systemExecutes a command and prints outputRun shell commands
passthruExecutes a command, passes raw outputRun shell commands
popen / proc_openOpens a process pipeSpawn processes / backdoors
pcntl_execExecutes a program in the current processRun shell commands
show_sourceReveals PHP source codeInformation disclosure
dlLoads a PHP extension at runtimeLoad malicious extensions
posix_* / posix_killLow-level process/user controlProcess manipulation

Note: eval() is a language construct, not a function, so it cannot be disabled via disable_functions. Block it with a WAF (ModSecurity / Imunify360) instead.

Recommended disable_functions List — Per CMS

The reason you tune this per CMS is that some platforms legitimately need a few of these functions for backups, image processing, or cron. Disable too much and you break the admin panel; disable too little and you leave gaps. Below are battle-tested lists for each major CMS.

WordPress

WordPress core never needs command-execution functions. The only caveat: a few backup/optimisation plugins (e.g. some UpdraftPlus zip operations) and WP-CLI use proc_open. If you rely on those, omit proc_open and popen.

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source,pcntl_exec,dl

Joomla

Joomla behaves like WordPress here. Akeeba Backup can use exec but has a pure-PHP fallback, so the full list is safe.

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl,posix_kill,posix_mkfifo,posix_getpwuid

Drupal

Drupal’s web requests don’t need command execution (Drush runs on the CLI, which uses a separate php.ini). Safe to disable the full set.

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl,posix_kill,posix_setuid,posix_setgid

Magento 2

Be careful with Magento. Some indexing, compilation, and third-party modules call exec, shell_exec, or proc_open. Best practice: keep these enabled on the CLI PHP config, but disable them on the web-facing PHP-FPM pool. A conservative web-pool list:

disable_functions = show_source,pcntl_exec,dl,posix_kill,posix_mkfifo,posix_setuid,posix_setgid

Test the admin panel, checkout, and cron thoroughly after applying. If something breaks, the culprit is usually a module needing proc_open.

OpenCart / PrestaShop

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl
CMSDisable command exec?Watch out for
WordPress✅ Yes (full list)WP-CLI / some backup plugins need proc_open
Joomla✅ Yes (full list)Akeeba Backup (has PHP fallback)
Drupal✅ Yes (full list)None on web (Drush is CLI)
Magento 2⚠️ Web pool onlyKeep enabled on CLI for compile/cron
OpenCart / PrestaShop✅ Yes (full list)None typically

Important: disable_functions Is a “System” Directive

This is the part most tutorials get wrong. disable_functions has a changeability of PHP_INI_SYSTEM, which means it cannot be set in .user.ini, .htaccess, or with ini_set(). It must be set in either:

  • The master php.ini for that PHP version, or
  • The PHP-FPM pool configuration for that specific domain/user (the recommended way to apply it per-CMS).

Because each CMS usually lives on its own domain or hosting account, the per-domain PHP-FPM pool is exactly where you set a CMS-specific list. Here’s how to do it in each control panel.

How to Apply It on cPanel / WHM

Option A — Per PHP Version (WHM, server-wide)

  1. Log in to WHM as root
  2. Go to Software → MultiPHP INI Editor
  3. Switch to the Editor tab and select the PHP version your CMS uses (e.g. ea-php82)
  4. Add your disable_functions = ... line and click Save

Option B — Per Domain (PHP-FPM pool, recommended)

To target one CMS only, add a per-domain FPM override via SSH:

# Create a per-domain FPM override (replace USER and DOMAIN)
nano /var/cpanel/userdata/USER/DOMAIN.com.php-fpm.yaml

# Add this line:
php_admin_value_disable_functions: "exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl"

# Rebuild FPM config and restart
/usr/local/cpanel/scripts/php_fpm_config --rebuild
/usr/local/cpanel/scripts/restartsrv_apache_php_fpm

How to Apply It on Plesk

Plesk makes per-CMS configuration the easiest because every domain has its own PHP settings page:

  1. Log in to Plesk
  2. Go to Websites & Domains → (select your domain) → PHP Settings
  3. Scroll to Additional configuration directives at the bottom
  4. Add your line:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl
  1. Click OK / Apply — Plesk applies it to that domain’s PHP-FPM pool immediately. No restart needed.

How to Apply It on CWP (CentOS Web Panel) Pro

Via the PHP-FPM Selector (per user/domain)

  1. Log in to CWP Pro admin
  2. Go to PHP Settings → PHP-FPM Selector (or PHP Version Switcher)
  3. Select the domain/user and the PHP version it runs
  4. Edit that pool’s configuration and add the directive line:
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl

Via SSH (PHP-FPM pool file)

# CWP PHP-FPM pools live under the selected PHP version, e.g. PHP 8.2
nano /usr/local/php82/php-fpm.d/USERNAME.conf

# Add inside the [pool] block:
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl

# Restart the matching FPM service
systemctl restart php-fpm82

For a server-wide setting across all sites on a version, edit that version’s php.ini under CWP → PHP Settings → PHP Version (select) → Edit php.ini and add disable_functions there.

How to Apply It on DirectAdmin

DirectAdmin uses CustomBuild with PHP-FPM. You can set it per user/domain via a custom FPM pool include:

# Per-user FPM override (PHP 8.2 example) — DirectAdmin reads custom includes here:
nano /usr/local/php82/etc/php-fpm.d/USERNAME.conf

# Inside the [USERNAME] pool block add:
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,show_source,pcntl_exec,dl

# Restart the FPM service for that version
systemctl restart php-fpm82

For a server-wide change per PHP version, edit the master php.ini and rebuild via CustomBuild:

# Add disable_functions to the version's php.ini, e.g.:
nano /usr/local/php82/lib/php.ini

# Then rebuild PHP configuration
cd /usr/local/directadmin/custombuild
./build php_ini
systemctl restart php-fpm82

Verify It Worked

After applying and restarting PHP-FPM, confirm the functions are actually disabled. Create a temporary file in the CMS web root:

# Create a temp checker (delete it immediately after!)
echo '' > check.php
# Visit https://yourdomain.com/check.php
# Both should print bool(false)
# Then remove it:
rm check.php

Or check from the command line (note: CLI uses a different php.ini, so always verify via the web for the FPM pool):

# Show the active disable_functions for a PHP-FPM pool
php -i | grep disable_functions

Layer It With Other Protections

Disabling PHP functions is one layer — combine it with these for defence in depth:

  • open_basedir — restrict PHP to the domain’s own directory so a hacked site can’t read other accounts
  • Imunify360 / ModSecurity WAF — blocks eval()-based and upload exploits that disable_functions can’t
  • CloudLinux + CageFS — isolates each account so one compromise can’t spread
  • Keep CMS, plugins, and themes updated — most breaches start with an outdated component
  • File permission hardening — 644 for files, 755 for directories, 600 for wp-config.php

Security Built In, Not Bolted On

Every Linux Shared Hosting and WordPress Hosting plan at IAMEM HOSTING ships with CloudLinux account isolation, Imunify360, and ModSecurity already configured — and our team will set up CMS-specific disable_functions hardening for you on request. If you need full control over PHP-FPM pools and server-level security, a Managed Linux VPS gives you root access with our 24×7 security monitoring behind it.

Leave a Reply

Your email address will not be published. Required fields are marked *