防御.htaccess上传攻击需三管齐下:一是在Apache主配置中对上传目录设AllowOverride None和php_flag engine off;二是PHP层严格校验文件名、扩展名及二进制头;三是将上传目录移出Web根目录或禁用其直接访问。

PHP 8.4 本身不处理 .htaccess 文件——那是 Apache 服务器的行为。防御“.htaccess 配合上传”类攻击,核心是阻断攻击者通过上传恶意 .htaccess 文件来篡改服务器行为(如开启 PHP 解析、绕过权限限制、重写规则劫持等)。
这类攻击典型路径是:
攻击者利用网站文件上传功能 → 上传一个伪造的 .htaccess(如命名为 shell.htaccess 或通过截断、覆盖等方式写入)→ 放在可被 Apache 读取的目录(如 uploads/)→ Apache 加载该文件 → 执行其中指令(如 AddType application/x-httpd-php .jpg)→ 后续上传 .jpg 实际被当作 PHP 执行 → RCE。
要真正防御,需从上传控制、目录隔离、Apache 配置加固三方面入手:
严格限制上传目录的 Apache 解析能力
不能依赖“用户不会传 .htaccess”,而要让即使传了也无效。在站点主配置或虚拟主机中明确禁止上传目录解析 .htaccess:
<Directory "/www/wwwroot/example.com/uploads">
AllowOverride None
php_flag engine off
Require all granted
</Directory>-
AllowOverride None:彻底禁用该目录下所有.htaccess指令(包括AddType、RewriteRule、php_flag等) -
php_flag engine off:关闭 PHP 引擎,防止任何 PHP 文件被执行(哪怕后缀被绕过) - 此配置必须放在 Apache 主配置或 vhost 中,
.htaccess自身无法覆盖它(因为AllowOverride None已禁用)
上传时强制剥离/过滤危险文件名和内容
PHP 层面不能只校验后缀,还要防伪装、截断、空字节、大小写混淆(如 .HtAcCeSs):
立即学习“PHP免费学习笔记(深入)”;
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
- 拒绝文件名含
.htaccess(全匹配 + 不区分大小写) - 使用
pathinfo($filename, PATHINFO_EXTENSION)获取真实扩展名,而非依赖$_FILES['file']['name']字符串解析 - 对上传文件做二进制头检测(如
finfo_file()),确认是图片就应有 JPEG/PNG 签名,不是纯文本或.htaccess内容 - 示例判断:
$finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $_FILES['file']['tmp_name']); if (!in_array($mime, ['image/jpeg', 'image/png', 'image/gif'])) { die('Invalid file type'); }
禁止上传目录被 Web 直接访问(或仅允许白名单类型)
即使 .htaccess 被禁用,也要防其他风险(如泄露源码、敏感配置)。推荐两种方式:
方式一:Web 根目录外存放上传文件
将uploads/放在/www/uploads/example_com/(不在/www/wwwroot/下),再用 PHPreadfile()输出,完全脱离 Apache 文件服务链。-
方式二:Apache 层硬性屏蔽危险扩展 + 重定向
在站点根目录.htaccess或 vhost 中添加:<Files ".ht*"> Require all denied </Files> <FilesMatch "\.(php|phtml|pl|py|jsp|asp|sh|cgi|inc|bak|swp|log)$"> Require all denied </FilesMatch>注意:此规则需放在
<directory></directory>块内且AllowOverride All时才生效;若已设AllowOverride None,则该.htaccess不起作用——所以优先用第一种AllowOverride None方式。
补充:宝塔用户特别注意
宝塔默认对 uploads/ 目录不做特殊防护。务必手动进入「网站 → 设置 → 配置文件」,在 前插入上述 <directory></directory> 块,并重启 Apache。不要依赖“防跨站”开关——它只管 open_basedir,不管 .htaccess 解析。
不复杂但容易忽略。


















