安全性与运维——CodeIgniter 4 上的 NextPDF
本页列出这套集成必须抵御的威胁,说明软件包源代码中实现的各项控制措施,并提供安全部署的运维规则。
威胁模型
标题为“威胁模型”的章节有三个可能受攻击者影响的接口。
- 队列任务负载。 队列会存储任务数据。具有 broker(消息代理)访问权限的攻击者可以更改这些数据。这属于未经信任且已反序列化的输入。
- 响应文件名。 用户可以提供下载文件名。恶意文件名可能注入标头内容。
- 配置路径。 字体路径与签名路径都来自配置。错误路径可能导致读取或写入到错误位置。
控制措施 1——队列负载允许清单
标题为“控制措施 1——队列负载允许清单”的章节队列任务会将负载视为未经信任且已反序列化的数据来处理。OWASP ASVS 要求对已反序列化的未信任数据执行安全的输入处理(ASVS V1.5.2)。
已验证的控制措施在 GeneratePdfJob 中实现:
- builder(构建器)必须是非空字符串。任务会拒绝其他类型的值。
- builder 必须符合
App\PdfBuilders\<Class>::<method>这个格式。任务会拒绝任何其他 namespace(命名空间)、普通函数,以及带有前缀或后缀的负载。 - builder 必须是可调用的。如果字符串符合格式但无法 resolve(解析)为可调用目标,任务会予以拒绝。
这些规则可防止通过篡改队列负载执行任意代码。软件包测试会逐一断言每一种拒绝情形。
控制措施 2——队列输出路径限制
标题为“控制措施 2——队列输出路径限制”的章节任务会将文件写入磁盘。当应用程序为文件操作构建文件路径时,OWASP ASVS 要求进行安全的路径处理(ASVS V5.3.2)。
已验证的控制措施在 GeneratePdfJob 中实现:
- 输出路径必须是非空字符串。
- 任务会对路径进行规范化。它会在任何检查之前先解析
.与..路径段,并转换分隔符。 - 规范化后的路径必须位于
WRITEPATH/pdfs/之内。任务会拒绝共用名称前缀的同级目录(pdfs-evil/)。 - 路径必须以
.pdf结尾(不分大小写)。
这些规则可防止通过篡改负载进行任意文件写入。
控制措施 3——响应标头强化
标题为“控制措施 3——响应标头强化”的章节PdfResponse 会为每个 PDF 响应附加一组固定标头:
| 标头 | 值 |
|---|---|
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
Content-Security-Policy | default-src 'none' |
X-Robots-Tag | noindex, nofollow |
Referrer-Policy | no-referrer |
Cache-Control | private, max-age=0, must-revalidate |
文件名写入标头之前会先经过清理。软件包会移除路径分隔符、null 字节以及 CR/LF。对于带引号的形式,它会转义双引号。对于非 ASCII 的名称,它会加上 RFC 5987 的 filename*=UTF-8''… 参数。空白名称会转换为 document.pdf。
控制措施 4——配置路径验证
标题为“控制措施 4——配置路径验证”的章节字体注册表会拒绝包含流包装器(stream wrapper,://)或 null 字节的 fontsPath。它会引发运行时错误。这可以阻止 php:// 或 phar:// 这类包装器路径。
控制措施 5——最小化的 service-locator 接口
标题为“控制措施 5——最小化的 service-locator 接口”的章节CodeIgniter 4 没有 PSR-11 container(容器),而是使用 Services locator(服务定位器)。PSR-11 §1.3 将 service-locator 模式视为不建议使用(modal SHOULD NOT)。软件包有意将定位器接口保持精简。每个服务都是一个具名的 factory(工厂)方法。请在 controller(控制器)边界处解析服务,并把具体对象向内传递。请勿把 Services 类传入领域代码。
签名与 TSA 运维作业(NextPDF Pro/Enterprise)
标题为“签名与 TSA 运维作业(NextPDF Pro/Enterprise)”的章节签名服务默认处于停用状态。只有当 signature.enabled 为 true,且 signature.certificate 为非空值时,它才会启用。软件包默认的签名级别为 B-B。NextPDF Pro 提供 B-B 基准签名。长期验证(LTV)是另一项独立的 Enterprise 功能。它记录在 Premium 参考文档中,不在此处说明。
运维规则:
- 请勿将证书与密钥文件纳入版本控制。请通过
.env或机密管理工具提供它们。 - 在生产环境中,请将
tsa.allow_insecure_http保持为false。明文 TSA 通道不可接受。 - 当 TSA 发布稳定的密钥时,请设置
tsa.pinned_public_keys。请将tsa.warn_on_key_rotation保持为true。 - 请将密钥文件的读取权限限制为应用程序用户可读。
运维检查清单
标题为“运维检查清单”的章节- 请在
composer.lock中锁定所有已解析的版本。 - 请在运行 worker 的应用程序中添加
codeigniter4/queue依赖。 - 请以低权限用户身份运行队列 worker。仅授予它对
WRITEPATH/pdfs/的写入权限。 - 请让 worker 具备与 web 层相同的 NextPDF 扩展。已签名的 PDF 需要在 worker 环境中安装 NextPDF Pro 或 Enterprise。
- 请在每个会构建 PDF 的运行环境中,确认已安装
mbstring与zlib扩展。 - 请确认响应标头经过反向代理后仍会保留下来。
- 请记录 PDF 生成作业及其上下文信息。请勿记录证书内容或密钥密码。
符合性
标题为“符合性”的章节- 队列负载的处理方式符合 OWASP ASVS V1.5.2。
- 队列输出路径的处理方式符合 OWASP ASVS V5.3.2。
- 定位器的设计遵循 PSR-11 §1.3 的指引。
商业背景
标题为“商业背景”的章节NextPDF core 采用 Apache-2.0。安装 NextPDF Pro 或 Enterprise 后,签名信任锚点与 TSA 强化才会生效。CodeIgniter 软件包会公开对应的服务方法;在尚未安装相符的 Premium 软件包时,这些方法会返回 null。详见 </get-license/?intent=codeigniter-signing>。
另请参阅
标题为“另请参阅”的章节- /integrations/codeigniter/production-usage/ ——正确的队列注册与派发。
- /integrations/codeigniter/configuration/ ——签名、TSA,以及路径相关的键。
- /integrations/codeigniter/troubleshooting/ ——已验证的拒绝消息。
- /integrations/codeigniter/overview/ ——完整的 API 接口。