The disabled_functions directive in php.ini is used to disable certain PHP functions that may pose a security risk (e.g., exec, shell_exec, system, etc.). This is typically used to harden shared hosting environments, such as DirectAdmin
In this article we look through the limitations of disable_functions within DirectAdmin and look at a workaround for setting customised disable_functions per-user within DirectAdmin.
The following script can be used to set custom disable_functions per-user within DirectAdmin:
#!/bin/bash
# Author: Ben (ICTU LTD)
# Email: [email protected]
# Filename: custom_per_user_disable_functions_php_fpm.sh
# Description: This DirectAdmin modification will allow you to have custom PHP disable functions per user when using php-fpm.
# By default his functionality is not allowed in DirectAdmin and disable functions are inherited from server wide conf.
# If you have a weak server wide configuration with limited fuctions disabled this will not be required and addition
# functions can be blocked using the control panel (see reading below).
# Using this script will allow you to use Secure PHP and have custom disable functions per user with ease.
# Reading:
# [01] https://docs.directadmin.com/webservices/php/php-fpm.html
# [02] https://docs.directadmin.com/webservices/php/secure-php.html
# [03] https://forum.directadmin.com/threads/cant-enable-exec-functions.56391/
# [04] https://forum.directadmin.com/threads/enable-exec-function-in-php-just-for-1-user.72640/
# [05] https://forum.directadmin.com/threads/limit-disable_functions-for-one-user-domain.62875/
######################################################################################################################################
# HOW TO USE
######################################################################################################################################
# [01] Copy phpfpm_disabled_functions.mods to a user PHP directory in DirectAdmin:
# cp -a phpfpm_disabled_functions.mods /usr/local/directadmin/data/users/$USERNAME/php/phpfpm_disabled_functions.mods
# [02] Edit the file and remove the functions you wish to enable for the user:
# vim /usr/local/directadmin/data/users/$USERNAME/php/phpfpm_disabled_functions.mods
# [03] Allow this file to execute:
# chmod +x custom_per_user_disable_functions_php_fpm.sh
# [04] Run the file:
# sh /root/custom_per_user_disable_functions_php_fpm.sh
# GLOBAL VARIABLES
USERS_PATH=/usr/local/directadmin/data/users
PHP_PATH=php
CONFIG_FILE=phpfpm_disabled_functions.mods
################################################################################################################
# START: PROCESS FILE CHANGES
################################################################################################################
for USERNAME in $(ls -1 $USERS_PATH); do
echo "======================================================================================================"
echo Processing user: $USERNAME
echo "======================================================================================================"
# SET VARIABLE FOR CUSTOM PHP DISABLED_FUNCTION FILE
CUSTOM_CONFIG_FILE="$USERS_PATH/$USERNAME/$PHP_PATH/$CONFIG_FILE"
if [ -e $CUSTOM_CONFIG_FILE ]; then
echo "Custom disabled_functions modification file exists for username: $USERNAME"
echo ""
echo "File path: $CUSTOM_CONFIG_FILE"
echo ""
echo "Locating php-fpm configuration files for: $USERNAME"
echo ""
# SET VARIABLE FOR LOCATING PHP FPM CONFIG FILE SPECIFIC TO USER
PHP_FPM_FILES=$(find "$USERS_PATH/$USERNAME/$PHP_PATH" -maxdepth 1 -type f -name 'php-fpm*.conf')
if [ -n "$PHP_FPM_FILES" ]; then
while IFS= read -r PHP_FPM_CONFIG_FILE; do
echo "Working on applying changes to: $PHP_FPM_CONFIG_FILE"
echo ""
# READ THE FULL CONTENTS OF THE CUSTOM FILE (ESCAPING FOR SED)
DISABLED_LINE=$(< "$CUSTOM_CONFIG_FILE")
ESCAPED_LINE=$(printf '%s\n' "$DISABLED_LINE" | sed 's/[&/\]/\\&/g')
sed -i.bak "s|^php_admin_value\[disable_functions\].*|$ESCAPED_LINE|" "$PHP_FPM_CONFIG_FILE"
echo "Changes sucessfully applied to: $PHP_FPM_CONFIG_FILE"
echo ""
done <<< "$PHP_FPM_FILES"
else
echo "For some reason we cannot locate a PHP FPM config file for $USERNAME."
fi
else
echo "No modifications file exists for user $USERNAME."
echo ""
echo ""
fi
done
################################################################################################################
# END: PROCESS FILE CHANGES
################################################################################################################
################################################################################################################
# START: RESTART PHP FPM PROCESS
################################################################################################################
for PHP_VERSION in $(systemctl list-units --type=service | grep php-fpm | awk '{print $1}'); do
echo "======================================================================================================"
echo Detected PHP version: $PHP_VERSION
echo "======================================================================================================"
echo "Attempting to restart $PHP_VERSION"
echo ""
systemctl restart $PHP_VERSION
sleep 5
if systemctl is-active --quiet $PHP_VERSION; then
echo "SUCCESS: PHP_VERSION is running after being restarted."
echo ""
else
echo "FAILED: PHP_VERSION does not seem to be running. Please manually check the service."
echo ""
fi
echo ""
done
################################################################################################################
# END: RESTART PHP FPM PROCESS
################################################################################################################
Example of phpfpm_disabled_functions.mods:
php_admin_value[disable_functions] = exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname,mail
What the script does:
How to use the script:
1. Copy phpfpm_disabled_functions.mods to a user PHP directory in DirectAdmin:
cp -a phpfpm_disabled_functions.mods /usr/local/directadmin/data/users/$USERNAME/php/phpfpm_disabled_functions.mods
2. Edit the file and remove the functions you wish to enable for the user:
vim /usr/local/directadmin/data/users/$USERNAME/php/phpfpm_disabled_functions.mods
3. Allow this file to execute:
chmod +x custom_per_user_disable_functions_php_fpm.sh
4. Run the file:
sh /root/custom_per_user_disable_functions_php_fpm.sh
You can download the scripts as a zip:
You can read more about how DirectAdmin applies disable_functions using the following guides:
You can check out our other useful guides by searching our Knowledge Base.