如何应对禁用exec函数后的PHP命令执行漏洞及加固措施?
- 内容介绍
- 文章标签
- 相关推荐
本文共计967个文字,预计阅读时间需要4分钟。
当Web服务器运行PHP环境时,直接修改主配置文件php.ini可一次性阻止exec及其同类函数被调用,适用于所有PHP进程,无需修改业务代码即可切断多数RCE输入。
1、使用文本编辑器打开php.ini文件,典型路径包括/etc/php/8.2/apache2/php.ini或/usr/local/php/etc/php.ini。
2、搜索disable_functions配置项,若该行以分号开头则删除分号取消注释。
3、在disable_functions = 后追加exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,多个函数间严格使用英文逗号分隔,注意不可添加空格。
立即学习“PHP免费学习笔记(深入)”;
4、保存文件后执行systemctl restart apache2或systemctl restart php8.2-fpm,使配置立即生效。
二、利用open_basedir限制文件操作边界
即使exec等函数已被禁用,攻击者仍可能借助文件包含、临时目录写入或符号链接等方式实现跨目录访问,open_basedir能强制将所有文件类操作约束在指定路径内,形成第二道隔离屏障。
1、在php.ini中定位open_basedir指令,若不存在则新增一行。
2、设置其值为网站根目录与必需临时路径的组合,例如:/var/www/html:/tmp:/var/tmp。
3、确保各路径之间使用冒号分隔,且末尾不带斜杠,避免因路径匹配失败导致功能异常。
4、重启PHP服务后,尝试在脚本中执行scandir('/')将返回false或警告,验证限制已生效。
三、检测并拦截动态函数调用行为
攻击者常绕过disable_functions,通过反射、变量函数、array_map等机制间接调用被禁函数,因此需在应用层主动识别并阻断此类调用链,而非仅依赖配置层封堵。
1、在关键执行入口处插入预检逻辑,调用is_callable('exec')判断函数是否可用。
2、进一步读取ini_get('disable_functions')返回值,使用逗号包围法校验exec是否在禁用列表中:stripos(',' . $disabled . ',', ',exec,') !== false。
3、若检测到exec被禁但调用意图存在,立即记录日志并终止流程,避免后续反射或回调触发。
4、对用户可控的函数名参数(如$_GET['func'])实施白名单校验,仅允许safe_log、format_date等已知安全函数名通过。
四、屏蔽反引号命令执行操作符
PHP中反引号(`)操作符具有与shell_exec相同的功能,且不受disable_functions控制,是常见绕过点。必须在Web服务器层面或应用输入过滤中显式拦截该语法结构。
1、在Nginx配置的location块中添加rewrite规则,匹配URL中出现反引号的请求并返回403:if ($args ~ "`") { return 403; }。
2、Apache环境下,在.htaccess中启用mod_rewrite后添加:RewriteCond %{QUERY_STRING} "`" [NC],RewriteRule ^ - [F]。
3、PHP应用层对所有用户输入执行preg_replace('/[`\\$\{\}]/', '', $input),清除反引号、美元符、花括号及反斜杠。
4、在日志中单独记录含反引号的请求,便于后续分析攻击尝试频率与来源IP。
五、部署PHP沙盒环境隔离高风险操作
对于确需执行外部命令的业务场景(如代码编译、图像处理),不应开放system/exec,而应启用独立沙盒进程,在资源、网络、文件系统维度实施硬性隔离,防止逃逸影响主服务。
1、使用firejail或bubblewrap启动受限子进程,禁止网络访问与文件系统写入,仅挂载只读的必要库路径。
2、通过pcntl_fork()创建子进程后,在子进程中调用posix_setsid()和chroot()构建轻量级隔离环境。
3、设置子进程最大执行时间为3秒,超时后由父进程调用pcntl_kill()强制终止。
4、命令输出统一重定向至内存缓冲区,禁止直接写入磁盘,输出内容须经HTML实体编码后再返回前端。
本文共计967个文字,预计阅读时间需要4分钟。
当Web服务器运行PHP环境时,直接修改主配置文件php.ini可一次性阻止exec及其同类函数被调用,适用于所有PHP进程,无需修改业务代码即可切断多数RCE输入。
1、使用文本编辑器打开php.ini文件,典型路径包括/etc/php/8.2/apache2/php.ini或/usr/local/php/etc/php.ini。
2、搜索disable_functions配置项,若该行以分号开头则删除分号取消注释。
3、在disable_functions = 后追加exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,多个函数间严格使用英文逗号分隔,注意不可添加空格。
立即学习“PHP免费学习笔记(深入)”;
4、保存文件后执行systemctl restart apache2或systemctl restart php8.2-fpm,使配置立即生效。
二、利用open_basedir限制文件操作边界
即使exec等函数已被禁用,攻击者仍可能借助文件包含、临时目录写入或符号链接等方式实现跨目录访问,open_basedir能强制将所有文件类操作约束在指定路径内,形成第二道隔离屏障。
1、在php.ini中定位open_basedir指令,若不存在则新增一行。
2、设置其值为网站根目录与必需临时路径的组合,例如:/var/www/html:/tmp:/var/tmp。
3、确保各路径之间使用冒号分隔,且末尾不带斜杠,避免因路径匹配失败导致功能异常。
4、重启PHP服务后,尝试在脚本中执行scandir('/')将返回false或警告,验证限制已生效。
三、检测并拦截动态函数调用行为
攻击者常绕过disable_functions,通过反射、变量函数、array_map等机制间接调用被禁函数,因此需在应用层主动识别并阻断此类调用链,而非仅依赖配置层封堵。
1、在关键执行入口处插入预检逻辑,调用is_callable('exec')判断函数是否可用。
2、进一步读取ini_get('disable_functions')返回值,使用逗号包围法校验exec是否在禁用列表中:stripos(',' . $disabled . ',', ',exec,') !== false。
3、若检测到exec被禁但调用意图存在,立即记录日志并终止流程,避免后续反射或回调触发。
4、对用户可控的函数名参数(如$_GET['func'])实施白名单校验,仅允许safe_log、format_date等已知安全函数名通过。
四、屏蔽反引号命令执行操作符
PHP中反引号(`)操作符具有与shell_exec相同的功能,且不受disable_functions控制,是常见绕过点。必须在Web服务器层面或应用输入过滤中显式拦截该语法结构。
1、在Nginx配置的location块中添加rewrite规则,匹配URL中出现反引号的请求并返回403:if ($args ~ "`") { return 403; }。
2、Apache环境下,在.htaccess中启用mod_rewrite后添加:RewriteCond %{QUERY_STRING} "`" [NC],RewriteRule ^ - [F]。
3、PHP应用层对所有用户输入执行preg_replace('/[`\\$\{\}]/', '', $input),清除反引号、美元符、花括号及反斜杠。
4、在日志中单独记录含反引号的请求,便于后续分析攻击尝试频率与来源IP。
五、部署PHP沙盒环境隔离高风险操作
对于确需执行外部命令的业务场景(如代码编译、图像处理),不应开放system/exec,而应启用独立沙盒进程,在资源、网络、文件系统维度实施硬性隔离,防止逃逸影响主服务。
1、使用firejail或bubblewrap启动受限子进程,禁止网络访问与文件系统写入,仅挂载只读的必要库路径。
2、通过pcntl_fork()创建子进程后,在子进程中调用posix_setsid()和chroot()构建轻量级隔离环境。
3、设置子进程最大执行时间为3秒,超时后由父进程调用pcntl_kill()强制终止。
4、命令输出统一重定向至内存缓冲区,禁止直接写入磁盘,输出内容须经HTML实体编码后再返回前端。

