PHP 怎么AppArmor

wen PHP项目 1

本文目录导读:

PHP 怎么AppArmor

  1. 为什么 PHP 需要 AppArmor?
  2. AppArmor 核心概念:Profile、模式与进程标签
  3. 为 PHP-FPM 生成专属 Profile
  4. 如何调试与修复被拦截的 PHP 文件操作
  5. 实战问答:常见配置错误与性能影响分析
  6. 扩展技巧:与 SELinux 对比及迁移注意事项

**
《PHP 环境加固实战:AppArmor 强制访问控制完整配置指南》


目录导读

  1. 为什么 PHP 需要 AppArmor?——从安全漏洞说起
  2. AppArmor 核心概念:Profile、模式与进程标签
  3. 为 PHP-FPM 生成专属 Profile(附命令行实操)
  4. 如何调试与修复被拦截的 PHP 文件操作(aa-log 分析)
  5. 实战问答:常见配置错误与性能影响分析
  6. 扩展技巧:与 SELinux 对比及迁移注意事项

为什么 PHP 需要 AppArmor?

PHP 作为动态语言,常被用于处理上传文件、执行系统命令或读写临时目录,若 Web 应用存在远程代码执行(RCE)漏洞,攻击者可能通过 system()include 函数渗透服务器,AppArmor(Application Armor)是 Linux 内核内置的强制访问控制(MAC)模块,能限制程序仅访问预设的特定文件、网络端口或目录,即使 PHP 进程被攻破,也无法越权读取 /etc/shadow 或写入 Web 根目录以外的区域。

与传统的 chmod 权限不同,AppArmor 基于“程序路径”而非“用户身份”进行限制,特别适合共享主机环境,一个 PHP 脚本试图读取 /var/www/private 下的文件,即便运行用户是 www-data,若 Profile 未授权,内核会直接返回 Permission denied

AppArmor 核心概念:Profile、模式与进程标签

  • Profile:定义特定程序(如 /usr/sbin/php-fpm8.1)允许的操作集合,语法类似 path flags
  • 模式enforce(强制拦截)与 complain(仅记录日志,放行操作),生产环境建议先使用 complain 模式测试。
  • 进程标签:通过 aa-status 命令查看当前活跃的 Profile,PHP-FPM 通常挂载为 php-fpm 标签。

检查系统是否已启用 AppArmor:

sudo aa-status

若输出 apparmor module is loaded,则可继续操作。

为 PHP-FPM 生成专属 Profile

步骤 1:安装工具链

sudo apt install apparmor-utils

步骤 2:生成基础 Profile(自动侦测)

sudo aa-genprof /usr/sbin/php-fpm8.1

程序会进入交互模式,此时需启动一些 PHP 请求以生成日志,用 curl 访问站点任意页面,触发文件读取操作。

步骤 3:手动补充关键路径规则
编辑生成的 /etc/apparmor.d/usr.sbin.php-fpm8.1,在 profile 块内添加:

  /var/www/html/ r,
  /var/www/html/** rw,
  /tmp/php*.sock rw,
  /var/log/php-fpm.log w,
  network inet stream,

/** rw 允许递归读写,但要注意开放过度,建议将上传目录单独设置为 rw,其他目录设为只读 r

步骤 4:重新加载并强制执行

sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.php-fpm8.1
sudo aa-enforce /usr/sbin/php-fpm8.1

使用 aa-complain 可临时切换回日志模式以便调试。

如何调试与修复被拦截的 PHP 文件操作

当 PHP 抛出不寻常的 readfile()mkdir() 失败时,查看内核日志:

sudo dmesg | tail -n 20
grep 'apparmor' /var/log/syslog

典型错误示例如下:

[ 1234.56] audit: type=1400 audit(...): apparmor="DENIED" operation="open" profile="php-fpm" name="/var/www/site/tmp/backup.zip" pid=1234 comm="php-fpm"

根据 name 字段,编辑 Profile 并在对应目录后追加权限:

  /var/www/site/tmp/** rw,

保存后重新加载,若拦截来自 PHP 的 exec() 调用,需添加 ixpx 规则允许执行特定二进制文件(如 /usr/bin/curl):

  /usr/bin/curl ix,

实战问答:常见配置错误与性能影响分析

问:AppArmor 会影响 PHP-FPM 性能吗?
答:影响极小,AppArmor 通过 LSM 钩子检查访问,每次文件操作增加约 0.1ms 开销,对于高并发场景可忽略不计,但注意,若 Profile 规则过于复杂(如数百条正则),会略微增加 CPU 占用。

问:为什么我的 PHP 脚本能读取 /etc/passwd 但仍提示权限错误?
答:请检查 Profile 是否处于 complain 模式,使用 sudo aa-status 确认状态,若显示 complain,则不会真正拦截,但日志会记录,需要执行 aa-enforce 才生效。

问:如何允许 PHP 连接外部 MySQL 数据库?
答:需添加网络访问规则,在 Profile 中加入:

  network inet tcp,
  network inet udp,

更严格的限定可指定端口:network inet tcp # 3306(注意 AppArmor 不支持端口限定,需通过 capabilitynet 域实现,此处建议直接允许 TCP)。

问:部署后 WordPress 上传图片失败,如何处理?
答:检查上传目录写入权限,在 Profile 中添加:

  /var/www/wordpress/wp-content/uploads/ rw,

并使用 aa-log 工具实时监控:

sudo tail -f /var/log/syslog | grep apparmor

扩展技巧:与 SELinux 对比及迁移注意事项

  • SELinux 使用标签(如 httpd_sys_script_t)管理,复杂度高但粒度更细;AppArmor 基于路径,更易理解。
  • 若从 SELinux 迁移,需注意 AppArmor 不区分“文件类型”(如管道、套接字),仅通过 rw 标记。
  • 在容器环境(Docker)中,默认不加载 AppArmor,需通过 --security-opt apparmor=php-profile 启用。

最后提示:在正式环境应用前,建议在 staging 环境开启 complain 模式运行 72 小时,通过 aa-log 汇总所有被拦截操作,一次性补齐权限规则,避免反复弹错。

抱歉,评论功能暂时关闭!