security: fix critical/high/medium vulnerabilities (authcode AES-256-GCM, CSRF timing, cookies, UUID, logging)#14
Merged
Conversation
…n audit
立即修复:
- Action.php: 将 CSRF token 最终比较由 === 改为 hash_equals() 防止时序攻击
- Action.php: setCookie() 添加 HttpOnly/Secure/SameSite 安全属性(auto-detect HTTPS)
- Action.php: CSRF 验证失败响应码由 401 改为语义更准确的 403
- Engine.php: 生产环境 500 错误不再泄露 getMessage()/getCode(),开发环境输出经 htmlspecialchars 转义
- Engine.php: session_start() 前设置 httponly/strict_mode/samesite ini 选项
- Engine.php: BIZ 路径验证由黑名单改为白名单正则 + segment 逐段校验,防路径遍历
- PlumeHelper.php: signature() 由 md5() 替换为 hash_hmac('sha256', ...)
- PlumeHelper.php: uuid() 使用 random_bytes(16) 生成符合 RFC 4122 v4 的 UUID,弃用 rand()/uniqid()/md5
- PlumeHelper.php: authcode() 废弃 MD5+RC4,替换为 AES-256-GCM 认证加密,保持 expiry 语义兼容
- PlumeHelper.php: redirect() 拦截 javascript:/data:/vbscript: URI,对输出内容做 htmlspecialchars 转义
计划修复:
- ActionInvoker.php: sanitizeForLog() 敏感字段列表大幅扩充(PII/支付/密钥),新增子串模糊匹配兜底
- Logger.php: 日志目录权限由 0755 改为 0700(仅属主可读)
- Router.php: 路由缓存目录权限由 0755 改为 0700
- View.php: extract() 添加 EXTR_SKIP 防止外部变量覆盖内置变量
测试: 335 tests, 555 assertions, all passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbNQpz52cgzdcqPw3fhYbD
setcookie() options array requires samesite to be one of the literal union types 'Lax'|'lax'|'Strict'|'strict'|'None'|'none'. Add runtime validation with fallback to 'Lax' and a @var annotation so PHPStan can verify the narrowed type at the call site. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbNQpz52cgzdcqPw3fhYbD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
本 PR 对 PlumePHP 框架进行了全面安全加固,修复了代码审计中发现的所有 Critical、High、Medium 级别漏洞,335 个测试全部通过。
修复详情
立即修复(Critical / High)
library/core/Plume/Libs/Action.php===,存在时序攻击hash_equals()常量时间比较library/core/Plume/Libs/Action.phpsetCookie()缺少 HttpOnly / Secure / SameSitelibrary/core/Plume/Libs/Action.phplibrary/Plume/Engine/Engine.phpgetMessage()/getCode()htmlspecialchars转义library/Plume/Engine/Engine.phpsession_start()前未设置安全 inihttponly/use_strict_mode/samesite/ HTTPSsecure配置library/Plume/Engine/Engine.phpstr_replace('..')),可绕过/^[a-zA-Z0-9_\-\.]+$/+ 逐 segment 校验library/PlumeHelper.phpsignature()使用 MD5,可被碰撞伪造hash_hmac('sha256', ...)library/PlumeHelper.phpuuid()使用rand()/uniqid()/md5(),熵不足random_bytes(16)生成符合 RFC 4122 v4 的 UUIDlibrary/PlumeHelper.phpauthcode()使用废弃的 MD5 + RC4 流加密(Discuz 遗产)$expiry语义兼容性library/PlumeHelper.phpredirect()未过滤javascript:/data:URI,输出未转义htmlspecialchars转义计划修复(Medium / Low)
library/Plume/Engine/ActionInvoker.phplibrary/Plume/Support/Logger.php0755(世界可读)0700(仅属主可读写)library/Plume/Http/Router.php07550700library/Plume/Support/View.phpextract()无标志,外部变量可覆盖内置变量EXTR_SKIP标志兼容性说明
authcode()破坏性变更:新实现(AES-256-GCM)与旧实现(RC4)的密文格式不兼容。若应用中有旧密文存储在数据库/Cookie 中,需要在部署前完成数据迁移。uuid()格式变更:返回值由 32 位纯 hex 改为标准 UUID 格式(xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx),带前缀时格式为prefix-uuid。已更新对应测试。signature()破坏性变更:输出由 MD5 hex(32 位)改为 HMAC-SHA256 hex(64 位)。若与外部系统(如微信支付)对接需要 MD5 签名,请在调用方自行使用md5()。setCookie()新增参数:新增$httpOnly、$secure、$sameSite参数,默认值向后兼容(true, auto,'Lax')。Test plan
./vendor/bin/phpunit tests/ --no-coverage— 335 tests, 555 assertions, all passingauthcode()ENCODE/DECODE 往返加解密正确..时正确抛出异常plumephp.env=production)500 页面不暴露错误细节🤖 Generated with Claude Code
https://claude.ai/code/session_01KbNQpz52cgzdcqPw3fhYbD
Generated by Claude Code