worker进程复用攻击是指利用php-fpm中fastcgi协议的多请求复用(multiplexing)特性,通过在一个tcp连接上连续发送多个请求,诱导fpm worker进程在同一个执行上下文中处理不同请求,从而引发变量污染、会话劫持或敏感信息泄露的安全漏洞。109619号问题(通常指代cve-2019-11043等类似机制的底层缺陷或特定版本中的具体复现案例)依赖这一机制,是因为它利用了worker进程在处理完一个请求后,未能完全重置全局状态(如$_get, $_post, 环境变量等),导致下一个请求直接继承了上一个请求的残留数据。

为什么FPM必须使用多请求复用?
FPM启用多请求复用主要是为了减少TCP连接的建立和销毁开销,提高吞吐量。如果禁用复用,每个请求都需要独立的TCP握手,这在高并发场景下会成为严重的性能瓶颈。

server {
listen 80;
server_name example.com;
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 关键配置:保持连接以支持复用
keepalive_timeout 65;
}
}
预期结果:Nginx与PHP-FPM之间维持长连接,单个Socket可承载多个FastCGI Record序列。若设置 fastcgi_keep_conn off; 或在PHP-FPM配置中限制 pm.max_children 导致连接频繁切换,复用效果将减弱。
如何验证Worker进程中的变量残留?
要验证变量残留,可以构造一个脚本,第一个请求设置一个全局变量或修改超全局数组,第二个请求不重新初始化该变量,直接读取。在多请求复用开启的情况下,第二个请求可能会读到第一个请求留下的值。

<?php // test_residue.php
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// 模拟第一个请求的行为:设置一个“脏”数据
if (!isset($_SESSION['dirty'])) {
$_SESSION['dirty'] = 'from_request_1';
echo "Set dirty: from_request_1\n";
} else {
echo "Read dirty: " . $_SESSION['dirty'] . "\n";
}
}
?>
预期结果:在启用Keep-Alive且FPM Worker复用的环境下,连续发送两个GET请求,第二次请求可能输出 Read dirty: from_request_1,证明状态未清理。若每次请求都新建连接,则第二次会重新初始化并输出 Set dirty: from_request_1(取决于Session存储方式,本地文件Session可能仍残留,但内存变量不会)。此测试重点在于观察非持久化存储的全局变量或静态变量在不同请求间的表现。











