在 Linux 服务器上部署 PHP,很多风险并不是来自某一个“高危漏洞”,而是配置暴露、权限过宽、上传目录可执行、依赖未审计这些细节叠加出来的结果。要把安全真正做扎实,不能只改一两项参数,而要从 PHP 运行时、Web 服务器、文件系统、编码方式到后续监控维护一起收紧。下面按五个最常见也最容易落地的层面展开,方便你逐项排查当前环境到底缺了什么、该先补哪一步。
PHP 配置先收口:减少暴露面和危险能力
php.ini 是 PHP 运行环境的第一道防线。很多默认项本身并不等于漏洞,但如果放在公网生产环境里不加限制,就会给攻击者更多试探空间。

先检查已加载扩展,关掉不用的模块
可以先用下面的命令查看当前启用的扩展:
php -m
原则很直接:业务不需要的模块就不要保留。比如应用根本不直连 MySQL,那么 mysqli、pdo_mysql 这类扩展就没有继续暴露在运行环境里的必要。扩展越多,攻击面通常也越大。
关闭版本和错误细节暴露
生产环境里,最忌讳把运行时信息直接送到前台。至少应处理好这几项:

expose_php = Off:避免在 HTTP 响应头暴露 PHP 版本。display_errors = Off:不把报错详情直接展示给访问者。log_errors = On:把错误留在日志里,方便排查。- 错误日志建议写入安全路径,例如
/var/log/php_scripts_error.log。
如果把栈信息、路径、函数名直接返回给用户,等于替攻击者完成了第一轮环境摸底。
禁用高危功能,压缩可利用空间
远程文件打开、远程包含和系统命令执行,都是 PHP 环境里最常被盯上的能力点。常见做法包括:
allow_url_fopen = Offallow_url_include = Off- 通过
disable_functions禁用system、exec、passthru、eval等函数
这样做不能替代代码修复,但能显著降低命令注入、远程包含被利用后的破坏范围。
限制脚本访问目录
用 open_basedir 可以约束 PHP 脚本只访问指定路径,例如:

open_basedir = /var/www/html:/tmp
它的价值在于,即使某段脚本出现问题,也不至于轻易越界读取 /etc/passwd 之类的系统敏感文件。
把会话安全做成默认设置
登录态相关问题经常被低估。为了降低会话固定和 Cookie 被窃取的风险,可以同时做两件事:
- 登录成功后调用
session_regenerate_id(true)重新生成会话 ID。 - 开启
session.cookie_httponly = On,并在 HTTPS 环境下设置session.cookie_secure = On。
前者用于切断旧会话,后者则是在浏览器侧减少脚本读取 Cookie 的机会。
Web 服务器层要做隔离,别让 PHP 和站点目录裸奔
PHP 安不安全,不只看 PHP 本身,Apache 或 Nginx 的运行方式同样关键。这里的核心思路是:服务进程不要拿过高权限,目录不要随便列出,PHP 处理链路尽量隔离。
Web 服务必须以普通用户运行
无论使用 Apache 还是 Nginx,都应确保进程不是以 root 身份长期处理业务请求。常见运行用户可以是 www-data。以 Apache 为例,可检查并调整 /etc/apache2/envvars 中的 APACHE_RUN_USER。
这一步的意义很现实:一旦站点被利用,攻击者拿到的首先是 Web 服务进程权限。如果这个权限本身就被限制住,后续横向扩展会困难很多。
关闭目录遍历,别把目录结构直接交给外部
目录列表暴露看似只是“可读性问题”,实际上会直接泄露文件命名、上传路径、备份文件和临时文件位置。常见配置方式如下:
- Apache:
Options -Indexes - Nginx:
autoindex off;
这类配置应当作为站点默认项,而不是发生信息泄露后再补。
通过 PHP-FPM 分离 PHP 处理
把 PHP 解析交给 PHP-FPM,一方面是常规性能方案,另一方面也有利于进程隔离。Nginx 中常见配置如下:
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
Apache 则通常通过启用 proxy_fcgi 模块来实现类似链路。这样做的好处是 Web 服务和 PHP 解释器职责更清晰,后续做权限划分、池配置和资源限制也更方便。
文件权限和上传目录要单独管,别给可写目录执行权
很多站点并不是被“打穿”在核心代码,而是被上传目录、缓存目录、临时目录这些边缘位置拖垮。文件系统权限如果过宽,应用层的小问题就更容易升级成可执行风险。
常规代码和目录权限要收紧
文中给出的基础建议很明确:
- PHP 文件权限设为
644 - 目录权限设为
755
也就是所有者可写,其他用户只保留必要的读取和进入权限。对大多数生产站点来说,这已经能避免不少因为“图省事”而留下的宽权限问题。
上传目录既要可用,也要不可执行
像 /var/www/html/uploads 这样的目录,通常既要允许业务写入,又要避免被当成脚本执行入口。建议至少满足这几项:
- 所有者设置为
www-data - 权限设为
755 - 禁止脚本执行
这类目录最容易被恶意上传利用,所以不能只看“能不能上传成功”,更要看“上传后能不能跑起来”。
在 Nginx 侧直接拒绝执行上传目录中的 PHP
如果使用 Nginx,可以增加专门规则,阻断上传路径中的 PHP 脚本执行:
location ~* ^/uploads/.*.(php|phtml)$ { deny all; }
这一步很重要,因为它把风险控制前移到了 Web 服务器层。就算应用没有完全挡住恶意文件上传,这条规则也能继续兜底,避免文件被当场执行。
代码安全不能省:输入校验、预处理和依赖审计都要做
运行环境加固能降低攻击成功率,但真正贴近业务风险的,仍然是代码本身。表单、URL 参数、数据库语句、第三方依赖,只要有一环处理粗糙,前面的配置加固就会被部分抵消。
用户输入必须验证,不要直接信任表单和参数
对邮箱、URL 等格式化输入,应使用 filter_var() 做校验和过滤。重点不在“做没做过滤”,而在于是否按字段类型做了严格验证,避免把任意字符串继续送进后续逻辑、SQL 或文件操作。
数据库操作统一使用预处理语句
防 SQL 注入时,PDO 或 MySQLi 的预处理语句仍是最基础也最有效的办法。原文中的示例如下:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");$stmt->execute([$username]);$user = $stmt->fetch();
这类写法把 SQL 结构和用户输入分开处理,比字符串拼接安全得多,也应该成为项目里的统一约定。
HTTPS 不是加分项,而是默认要求
传输层加密同样属于 PHP 站点的安全边界。可以通过 Let's Encrypt 申请 SSL 证书,并在 Web 服务器中启用 HTTPS。以 Nginx 为例,至少会涉及:
listen 443 ssl;- 证书路径配置
如果登录、Cookie、后台操作仍走明文 HTTP,那么就算应用本身没有明显漏洞,敏感数据也可能在链路上被窃听或篡改。
代码审计和依赖扫描要持续做
安全编码不是上线前一次性检查。可以借助 SonarQube、PHPStan 这类静态分析工具,持续扫描 SQL 注入、XSS 等潜在问题;同时配合定期渗透测试,从攻击者视角补齐遗漏。对于依赖较多的 PHP 项目,这一步尤其必要,因为风险往往不只在业务代码里。
最后一层是持续维护:更新、日志、WAF 和强制访问控制
安全工作如果停留在部署当天,通常很快就会失效。真正决定系统能否长期稳定的,是后续更新、网络入口控制和异常行为发现能力。
系统和 PHP 版本要及时更新
最基础的维护动作,就是定期打补丁:
sudo apt update && sudo apt upgrade -y
很多已知漏洞其实早有修复版本,真正出事往往不是“没有补丁”,而是“补丁一直没上”。
用 ufw 缩小暴露端口范围
防火墙配置应当遵循最小开放原则,只放行必要入站端口。文中的示例如下:
sudo ufw allow 22/tcpsudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw enable
实际执行时可按环境拆成多行,但保留的核心端口通常就是 SSH 的 22、HTTP 的 80 和 HTTPS 的 443。
盯住错误日志和访问日志,尽早发现异常行为
日志检查不能只在故障发生后才做。至少要定期查看这些位置:
- PHP 错误日志:
/var/log/php8.0-fpm.log - Web 访问日志:
/var/log/apache2/access.log
配合 Logwatch、ELK Stack 这类工具,可以更容易识别高频 404、异常 POST、重复探测路径等行为。很多攻击在真正利用成功前,其实已经在日志里留下了明显信号。
需要更强隔离时,再加 SELinux、AppArmor 和 ModSecurity
如果站点面向公网、业务价值较高,或者需要满足更严格的防护要求,可以继续叠加强制访问控制与 Web 应用防火墙:
- 启用 SELinux 或 AppArmor,限制进程能力边界
- 部署 ModSecurity,过滤恶意请求
这些措施会增加一定维护成本,但它们提供的是纵深防御能力:即便某一层配置或代码出现疏漏,后面的限制仍能继续拦截风险。
怎么判断当前 Linux PHP 环境是否已经达标
如果你要快速自查,至少可以按下面的顺序看一遍:php.ini 是否关闭了信息暴露和危险函数,Web 服务是否以普通用户运行,上传目录是否不可执行,数据库查询是否统一使用预处理,系统与日志监控是否持续维护。把这几层同时做好,PHP 站点的基础安全面才算真正建立起来。







