针对与“php2shell” CVE-2026-109618 / CVE-2026-109619(PHP longjmp() 内存处理中的潜在 RCE)相关的 HTTP 指标,提供 Zeek 检测和 Suricata 规则。检测结果可识别可疑流量或可能受影响的软件。
需要 Zeek 7.0.0 或更高版本。使用 Zeek Package Manager 安装:
zkg install https://github.com/corelight/php2shell-detect
使用 @load packages 在 Zeek 配置中加载已安装的软件包。
若为直接检出,请加载 /path/to/php2shell-detect/scripts。
该软件包使用标准的 Zeek HTTP、文件分析、notice 和集群 API。
该软件包会检查 POST 字段名长度、选定的序列化数据结构以及重复的 MIME 头。它还会使用配置的会话 cookie 关联相关的可疑事务。响应头提供单独的 PHP 版本清单。流量必须对 Zeek 的 HTTP 分析器可见;加密的 HTTP 需要在检查前解密。
所有通知类型均位于 PHP2SHELL:: 下:
| 通知 | 观察内容 |
|---|---|
PHP_Crash_Sequence | 同一会话内相关的可疑 HTTP 事务 |
Multipart_Header_Flood | 已识别 MIME 头的过度重复 |
Large_Form_Key | 异常长的 URL 编码表单字段名 |
Serialized_Integer_Overflow | 异常大的序列化整数标记 |
Serialized_Integer_Collisions | 已识别的序列化整数键模式 |
Serialized_String_Collisions | 已识别的序列化字符串键模式 |
Serialized_Duplicate_Array | 重复的序列化数组条目模式 |
Serialized_Object_Repetition | 重复的序列化对象模式 |
Potentially_Affected_PHP_Version | 响应头通告的版本位于配置的受影响范围内 |
结果写入标准 notice.log;该软件包不会创建额外的日志流。通知的 sub 字段提供有界上下文,例如头名称、事务深度、计数以及简短的转义 POST 正文样本。默认情况下,样本在转义前限制为 64 个原始字节;设置 notice_body_sample_bytes=0 可省略样本。Cookie 及其摘要仅在内存中使用,本软件包不会记录它们。
默认情况下,每个不同的请求指示器可在每个事务中发出一次通知。同一指示器的重复匹配会被抑制。设置 detect_only_once=T 可在每个事务中首次请求发现后停止正文检查。版本清单通知独立于请求发现。
所有设置均使用 PHP2SHELL:: 命名空间:
| 设置 | 默认值 | 作用 |
|---|---|---|
detect_only_once | F | 报告每个不同的请求指示器;T 在首次发现后停止 |
max_trans_depth | 3 | 检查每个连接的前三个 HTTP 事务;0 表示全部 |
inspect_cookies | T | 使用会话 cookie 进行关联 |
session_cookie_names | {"PHPSESSID"} | 用于关联会话的 cookie 名称 |
correlation_window | 1 min | 待处理会话关联状态的最大存续时间 |
max_pending_sessions | 1000 | 每个关联表中保留条目的上限 |
inspect_post_bodies | T | 检查 POST 实体数据和 MIME 头 |
http_body_analysis_byte_depth | 8388608 | POST 正文检查工作的保守 8 MiB 上限,跨 MIME 部分共享;0 禁用正文传递 |
body_overlap_bytes | 256 | 为跨正文块的模式保留的重叠字节 |
large_form_key_bytes | 65536 | 表单名线上字节阈值 |
multipart_header_threshold | 128 | 触发发现所需的重复已识别 MIME 头数量 |
notice_body_sample_bytes | 64 | 每个通知样本的最大原始正文字节数;0 省略样本 |
detect_affected_php_versions | T | 启用响应头版本清单 |
php_version_notice_interval | 1 hr | 按服务器 IP 跨端口和版本抑制版本通知 |
php_fixed_patch_versions | 8.2: 35, 8.3: 36, 8.4: 27, 8.5: 12 | 每个分支暂定的首个修复补丁版本 |
例如:
redef PHP2SHELL::detect_only_once = T;
redef PHP2SHELL::notice_body_sample_bytes = 0;
redef PHP2SHELL::session_cookie_names += { "custom_session" };
POST 检查使用带有限重叠的文件分析分块,而不是组装完整正文。表单名称计数会遵循值分隔符和原始 NUL 终止。只有符合条件的 POST 实体才会分配分析器;正文预算和事务限制会有意约束检测范围。这些指标并不完整,也可能匹配良性流量。
在 Zeek 集群中,工作进程通过 Cluster::publish_hrw() 将会话的小型观测结果路由到代理。同一会话的两个阶段会到达同一个代理,由该代理进行匹配并直接触发 PHP_Crash_Sequence。该通知保留后续请求的连接 ID、UID 和事务深度;peer_descr 标识代理。工作进程不会为回调保留完整的连接或 HTTP 记录。
触发器和未匹配的后续请求会在 correlation_window 之后过期,max_pending_sessions 会限制每个表的大小。代理会为每个会话键保留第一个未匹配的后续请求。触发器会直接查找该键,以处理按相反顺序到达的消息;同一键的后续未匹配后续请求会被合并,直到该条目匹配或过期。匹配使用观测时间戳以及客户端、服务器、服务器端口、HTTP 主机和会话摘要。独立运行的 Zeek 会在本地进行关联。需要正常的代理连接。
代理通知使用标准通知抑制机制,按 UID 和事务深度在 correlation_window 内进行抑制。这与工作进程的发现相互独立,并且不会停止工作进程的正文检查。不同代理上针对不同会话 cookie 的同时匹配,仍可能在集群抑制传播之前产生重复通知。
会检查外层 Server 和 X-Powered-By 响应头,包括对 GET 的响应。头名称不区分大小写。受影响的下限是 PHP 5.4.0。以下截止版本假设在 2026 年 10 月 18 日检查到的最新稳定版本之后的下一个补丁版本将修复这两个缺陷:
| 分支 | 检查时的最新稳定版本 | 暂定首个修复版本 |
|---|---|---|
| 8.2 | 8.2.34 | 8.2.35 |
| 8.3 | 8.3.35 | 8.3.36 |
| 8.4 | 8.4.26 | 8.4.27 |
| 8.5 | 8.5.11 | 8.5.12 |
已配置的修复版本以及同一分支中的后续补丁不会触发告警。未配置截止版本的分支仍视为候选。常见的厂商后缀会使用底层数字版本。横幅可能缺失、被改写,或反映带有向后移植修复的厂商构建,因此这些只是清单提示。
suricata/php2shell.rules 中的三条规则独立于 Zeek 运行。使用 zkg 安装 Zeek 包不会将这些规则加载到 Suricata 中。文件中的三条规则均已启用;Zeek 配置选项不会影响它们。
| SID | 检查缓冲区 | 观测内容 |
|---|---|---|
| 3000650 | 方法为 POST 的 http.request_body | 请求正文中的检测标记 |
| 3000651 | http.response_header | Server 或 X-Powered-By 声明的可能受影响的 PHP 版本 |
| 3000652 | http.response_body | phpinfo 形状的 HTML 标题中可能受影响的 PHP 版本 |
将规则文件添加到 suricata.yaml 中现有的 rule-files 列表,同时保留其他规则条目。使用你的检出目录的绝对路径:
rule-files:
- /path/to/php2shell-detect/suricata/php2shell.rules
验证你的配置,然后使用你正常的部署流程重新加载或重启 Suricata:
suricata -T -c /path/to/suricata.yaml
这些规则已使用 Suricata 8.0.6 验证。必须启用 HTTP 正文检查;请求/响应正文限制和流重组限制决定了哪些内容会到达这些规则。加密 HTTP 需要先解密才能进行检查。
在 EVE 告警记录中通过 alert.signature_id 查找这些规则,或在已配置的告警输出中按其 SID 查找。POST 标记可能出现在正常流量中,并不能证明存在漏洞利用尝试。Suricata 不执行 Zeek 包中的会话关联。
版本规则属于软件清单信号。头部名称按大小写不敏感方式匹配,正文规则识别 phpinfo 形式的 HTML 标题。两者均使用上文的临时版本截止值;缺失或被改写的横幅以及厂商回移植会限制其准确性。发布前 TODO: 对照官方 PHP 安全公告和发布说明,核实两条规则的影响范围和首个修复版本。
每条版本规则将告警限制为每个服务器 IP 每小时一次,跨客户端、端口和所声明的版本。它们检查响应,因此 track by_src 跟踪的是服务器。每个 SID 维护各自的限制;因此同一服务器在同一小时内可能同时产生头部告警和 phpinfo 告警。POST 标记规则没有每小时限制。
安装 btest,并确保 zeek、zeek-cut、unzip、bash 和 make 位于 PATH 中,然后运行:
make check
make test
make zam
make zam 会在启用 Zeek 的 ZAM 优化器的情况下重复该测试。唯一
包含的 btest 使用压缩合并的上游 Zeek HTTP 语料库,并
比较完整的 TSV HTTP 和 notice 日志。预期会出现一条 PHP 8.0.26 清单
notice;reporter.log 必须不存在。有关输入详情和许可,请参见
语料库来源。