PHP 安全科普 · 防御向
PHP 对象注入:是什么,怎么修
把用户可控的数据交给 unserialize(),等于让攻击者决定 PHP 要创建哪些对象。PHP 手册明确警告不要这样做。
最近更新
这是什么
PHP 反序列化字符串时会重建其中描述的对象,并可能调用 __wakeup()、__destruct() 等魔术方法。如果字符串来自 Cookie、表单字段或 API 请求,攻击者就能挑选应用或其依赖库里已加载的类,把它们的方法串起来,最终可能写文件或执行代码。MITRE 把它归为 CWE-502(不可信数据的反序列化)。
怎么发现
- 在代码里搜索
unserialize(,追踪每个参数的来源。凡是能从$_GET、$_POST、$_COOKIE、请求头、上传文件或用户可写的数据库字段到达这里的,都是问题。 - 用同样的方法检查第三方插件和老旧库;历史上很多 CMS 插件公告就是对象注入。
- 带安全规则的静态分析工具(PHPStan、Psalm)和依赖审计(
composer audit)可以帮助找出已知有漏洞的包。
怎么修
- 跨越信任边界的数据用
json_encode()和json_decode(),JSON 无法创建 PHP 对象。 - 实在要用
unserialize(),就传入['allowed_classes' => false]或一份很短的明确列表。即便如此,PHP 手册仍建议不要处理不可信输入。 - 存放在客户端的序列化数据要用 HMAC 签名,解码前先校验。
- 保持框架和库更新,移除已知的利用链。
只读检查与安全写法
# Find unserialize() calls that may receive request data (read-only)
grep -rnE "unserialize\s*\(" --include=*.php . | grep -vE "/vendor/|/tests?/"
// Safer: exchange data as JSON
$data = json_decode($input, true, 512, JSON_THROW_ON_ERROR);
// If unserialize() is unavoidable for trusted data, forbid objects
$data = unserialize($trusted, ['allowed_classes' => false]);allowed_classes => false 就够了吗?
它阻止创建对象,去掉了主要风险,但 PHP 手册仍建议不要反序列化不可信输入。默认用 JSON 更安全。
这和 PHP2Shell 有关吗?
无关。PHP2Shell 是 PHP 运行时的漏洞,对象注入是应用代码的漏洞,PHP 打满补丁也照样存在。
其他常见 PHP 漏洞类型
- PHP 文件包含(LFI/RFI):是什么,怎么修当用户输入控制了 include 或 require 的路径时就会发生文件包含,攻击者可以读取本地文件(LFI),在开启 allow_url_include 时还能运行远程代码(RFI)。
- PHP 中的 SSRF:是什么,怎么修当 PHP 应用请求一个由用户控制的 URL 时就会发生服务端请求伪造(SSRF),攻击者可以借你的服务器访问内网服务或云元数据接口。
- PHP 中的 XSS:是什么,怎么防当 PHP 页面把用户可控的数据不经转义输出到 HTML 时就会发生跨站脚本(XSS),攻击者的脚本会在其他访客的浏览器里运行。
- phpinfo() 暴露:为什么重要,怎么修公开的 phpinfo() 页面会泄露精确的 PHP 版本、已加载模块、文件路径,常常还有环境变量或密钥,帮攻击者瞄准 PHP2Shell 这类漏洞。
来源
出站链接将离开本站。本站不托管利用代码。
- unserialize() — PHP Manual
- json_decode() — PHP Manual
- PHP Object Injection — OWASP
- CWE-502: Deserialization of Untrusted Data — MITRE CWE