发布于22小时前22小时 本文仅用于已授权环境中的漏洞确认。验证过程使用独立 canary 文件,不执行系统命令、不写入持久化内容,避免直接在业务入口测试。一、漏洞背景CVE-2024-4577 是 Windows 平台 PHP-CGI 参数注入漏洞。PHP 以 CGI 方式运行时,会在特定条件下把不包含等号的查询字符串解释为命令行参数。Windows 部分代码页存在 Best-Fit 字符映射,例如软连字符 0xAD 可能被转换为普通连字符 0x2D,从而绕过 PHP 过去针对 CGI 参数注入的检查。常见风险环境包括 Windows、Apache、php-cgi.exe 组合,尤其是使用日文或中文代码页的主机。CP932、CP936、CP950 是排查时需要重点关注的代码页,但不应只根据系统语言判断是否安全。PHP 官方在 8.1.29、8.2.20、8.3.8 中修复了该问题。PHP 7.x、8.0 等已停止维护的分支不应继续使用。实际处置时应升级到当前仍受支持分支的最新安全版本,而不是仅停留在最低修复版本。二、漏洞成立条件该漏洞不是“Windows 上安装 PHP 就一定可利用”,至少需要确认以下条件:PHP 运行于 Windows。Web 服务器将 PHP 请求交给 php-cgi.exe,并采用可能触发 CGI 参数解析的方式。系统代码页或字符转换链路可将特殊字符映射为命令行选项前缀。请求在进入 php-cgi.exe 前未被补丁或有效规则拦截。Apache 配置中出现以下结构时需要重点核查。该配置仅作为风险特征示例,不建议直接部署:ScriptAlias /php-cgi/ "C:/xampp/php/" Action application/x-httpd-php "/php-cgi/php-cgi.exe" AddHandler application/x-httpd-php .php需要注意,安装目录中存在 php-cgi.exe 并不等于正在使用 CGI。部分 FastCGI 部署同样使用该文件,因此最终应以 Web 服务器处理器映射、实际请求链路和无害验证结果为准。三、资产与配置排查可以先在 Windows 主机上确认 PHP 版本、活动代码页以及 Apache 配置中的 CGI 映射:$roots = @("C:\xampp", "C:\Apache24", "C:\php") Get-ChildItem $roots -Filter php-cgi.exe -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $version = & $_.FullName -v | Select-Object -First 1 "{0} => {1}" -f $_.FullName, $version } chcp Get-ChildItem "C:\xampp\apache\conf" -Recurse -File -ErrorAction SilentlyContinue | Select-String -Pattern 'ScriptAlias|Action\s+application/x-httpd-php|php-cgi\.exe'若使用 IIS,还应检查处理程序映射,区分 CGI 与 FastCGI,并确认实际引用的 PHP 路径:%windir%\system32\inetsrv\appcmd.exe list config /section:system.webServer/handlers %windir%\system32\inetsrv\appcmd.exe list config /section:system.webServer/fastCgi资产盘点时不要只检查 PATH 中的 PHP。XAMPP、旧版运维面板、遗留站点目录中经常同时存在多套 php-cgi.exe,Web 服务实际加载的版本可能与命令行执行的 php.exe 不一致。四、无害验证方法推荐在测试虚拟主机中新建一个独立 canary 文件,通过 CGI 的 -s 源码显示选项验证参数是否被注入。该方法不执行操作系统命令,也不依赖外连。首先创建仅用于验证的文件,其中注释标记不会在正常执行时输出:Set-Content ` -Path "C:\xampp\htdocs\cve4577_canary.php" ` -Encoding Ascii ` -Value '<?php /* SOURCE_ONLY_4577 */ echo "NORMAL"; ?>'先发送普通请求建立基线,再发送保留原始路径编码的测试请求:curl.exe -i --path-as-is " curl.exe -i --path-as-is " NORMAL。如果第二个请求返回经过语法高亮或转义后的 PHP 源码,并能看到 SOURCE_ONLY_4577,说明特殊字符已被转换为 -s,CGI 参数注入成立。如果第二个请求返回 403,可能已经存在临时拦截规则,仍需确认 PHP 版本是否已升级。如果第二个请求仍只返回 NORMAL,不能仅凭这一点完全排除风险,还应核对处理器映射、代码页、前置代理是否改写请求以及测试请求是否原样到达源站。验证完成后删除 canary 文件:Remove-Item "C:\xampp\htdocs\cve4577_canary.php" -Force不建议在生产业务文件上使用 -s 测试。若漏洞成立,该选项可能直接暴露源码中的数据库口令、接口密钥或内部路径。五、技术影响与权限边界-s 只能用于低影响确认,但漏洞本身不仅限于源码泄露。攻击者还可能通过 CGI 的配置参数改变 PHP 运行行为,最终让请求体中的 PHP 内容被解释执行。执行权限通常继承自 Apache、IIS 应用程序池或对应服务账户,并不天然等于 SYSTEM。实际影响取决于该身份的权限边界:是否可写 Web 根目录、上传目录、临时目录及计划任务目录。是否能读取 wp-config.php、数据库连接配置、云服务密钥和部署凭据。服务账户是否拥有 SeImpersonatePrivilege、管理员组成员身份或网络共享权限。主机是否可访问数据库、域控管理接口、Redis、文件服务器等内网资源。在 WordPress 等 PHP 应用中,即使 Web 服务账户权限较低,读取 wp-config.php 后获得数据库凭据,也可能进一步导致管理员账户接管、插件写入或内网数据库访问。因此评估时不能只看是否获得本机管理员权限。六、访问日志排查Apache access.log 通常会保留原始请求目标,可优先搜索软连字符编码、CGI 配置参数和异常 PHP 输入特征:$log = "C:\xampp\apache\logs\access.log" Select-String -Path $log -Pattern ` '%AD', '%ad', '%C2%AD', '%c2%ad', ` 'allow_url_include', 'auto_prepend_file', ` 'php://input', 'php-cgi'IIS 日志可使用类似方式检查:Get-ChildItem "C:\inetpub\logs\LogFiles" -Recurse -File -ErrorAction SilentlyContinue | Select-String -Pattern '%AD|%ad|%C2%AD|%c2%ad|auto_prepend_file|allow_url_include'排查时应同时检查反向代理、WAF、CDN 和源站日志。部分组件会解码、规范化或丢弃原始查询字符串,单一日志源没有命中不能作为未受攻击的依据。重点关注以下组合特征:查询字符串以 %AD 开头,且没有常规键值形式。同一来源先探测 -s,随后出现 POST 请求或其他 CGI 配置参数。请求返回 200、500 后,Web 目录或临时目录出现新文件。php-cgi.exe、httpd.exe、w3wp.exe 随后启动 cmd.exe、powershell.exe、certutil.exe 或脚本解释器。七、主机侧留痕检查如果已部署 Sysmon,可检查进程创建事件中异常的父子关系:Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-Sysmon/Operational' Id = 1 } -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'ParentImage:.*(php-cgi|httpd|w3wp)\.exe' -and $_.Message -match 'Image:.*(cmd|powershell|certutil|mshta|rundll32)\.exe' } | Select-Object TimeCreated, Id, Message没有 Sysmon 时,可在已启用进程创建审核的主机上检查 Security 4688。还应结合以下位置进行时间线分析:站点根目录、上传目录以及 Windows Temp 中近期新增或修改的 PHP、PHTML、BAT、PS1 文件。Apache error.log、PHP error_log 和 Windows 应用程序日志中的异常报错。计划任务、服务、启动项及 IIS/Apache 配置的近期变更。数据库账户登录日志及来自 Web 主机的异常管理操作。若发现 Web 服务进程派生系统命令、配置凭据被读取或站点目录出现未知文件,应按已入侵事件处理,而不是仅完成补丁升级。需要隔离主机、保全日志、轮换数据库和应用密钥,并重新部署可信版本。八、修复与缓解首选方案是升级 PHP,并重启所有相关 Web 服务,确认新进程实际加载了升级后的文件。只替换 php.exe 而遗漏 php-cgi.exe,或者升级后未重启 Apache/IIS,都可能导致漏洞继续存在。升级到当前仍受支持 PHP 分支的最新安全版本。移除未使用的旧 PHP 目录及处理器映射,避免请求仍被转发到旧版 php-cgi.exe。没有业务需要时,取消 CGI 映射和可直接访问的 php-cgi ScriptAlias。以低权限专用账户运行 Web 服务,禁止其写入程序目录和系统目录。将站点代码设置为只读,仅允许上传目录和必要缓存目录写入。轮换可能已暴露的数据库密码、WordPress salts、API 密钥和部署凭据。无法立即升级时,可参考临时重写规则拒绝以相关编码开头的查询字符串:RewriteEngine On RewriteCond %{QUERY_STRING} ^%ad [NC] RewriteRule ^ - [F,L]该规则只能作为短期缓解措施。代理解码顺序、双重编码、不同日志规范化方式和服务器配置差异都可能影响效果。部署后必须使用原始编码请求从代理入口和源站分别复测,不能把 WAF 或 RewriteRule 当作永久修复。九、修复复核修复后建议完成以下闭环:php-cgi.exe -v 显示的版本属于受支持且已修复的版本。Apache/IIS 实际处理器映射指向升级后的唯一 PHP 路径。服务重启后,相关进程的启动时间和映像路径符合预期。无害 canary 测试不再显示源码。代理层和源站日志均能记录或拦截测试请求。历史日志中没有可疑参数、异常子进程和落地文件;如有命中,已转入事件响应。十、总结CVE-2024-4577 的关键不只是版本号,而是 Windows 字符映射、PHP-CGI 参数解析和 Web 服务器处理器配置共同形成的攻击面。排查时应先确认真实请求链路,再使用独立 canary 文件做低影响验证,并结合访问日志、进程事件和文件时间线判断是否已经被利用。修复应以升级受支持版本和移除不必要 CGI 映射为主,重写规则只能用于临时止血。 服务器、云资产与权限边界梳理示意 网络请求、日志与边界流量分析示意
20小时前20小时 这类问题建议先确认“是否使用 Windows 下的 php-cgi.exe”,不要只看 PHP 版本。PHP-FPM、Apache 模块模式和 CLI 不属于同一暴露面,常见风险配置是 Apache 的 Action/ScriptAlias、XAMPP,或 IIS FastCGI 直接映射到 php-cgi.exe。 可以先在服务器上确认版本和进程: where.exe php-cgi.exe php-cgi.exe -v Get-CimInstance Win32_Process | Where-Object { $_.Name -ieq "php-cgi.exe" } | Select-Object ProcessId, ParentProcessId, ExecutablePath, CommandLine 修复版本至少为 PHP 8.1.29、8.2.20、8.3.8;更老且已停止维护的分支建议直接升级到当前受支持版本,而不是只改一两个 php.ini 参数。 如果需要无害验证,建议仅在本机或隔离测试环境放一个临时脚本,用请求级、无副作用的配置项判断参数是否被注入: <?php header('Content-Type: text/plain'); echo ini_get('memory_limit'), PHP_EOL; curl.exe --path-as-is " curl.exe --path-as-is " 如果第二次响应变成 123M,说明软连字符经过 Windows 字符转换后被当成了 -d 参数,存在注入风险。测试后应立即删除脚本;不要在生产环境使用包含代码执行、文件包含或外连行为的 PoC。 日志排查不能只搜明文 %AD,反向代理、WAF 和 Web 服务器可能记录原始值、二次编码值或 UTF-8 形式。可先查以下组合: $pattern = '(?i)(%ad|%c2%ad|%25ad).*(auto_prepend_file|allow_url_include|php://|data://|%ad[dns])' Get-ChildItem C:\Apache24\logs,C:\inetpub\logs\LogFiles -Recurse -File -ErrorAction SilentlyContinue | Select-String -Pattern $pattern 重点关注查询串开头出现 %ADd、%ADs、%ADn,以及同一请求中出现 auto_prepend_file、allow_url_include、php://input 等内容。还要结合状态码、响应长度和后续访问判断,单条 403 不代表成功利用。 主机侧建议同步查看 php-cgi 是否拉起了异常子进程。启用了进程创建审核时,可查询安全日志 4688;Sysmon 则看事件 1: Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-Sysmon/Operational' Id=1 StartTime=(Get-Date).AddDays(-7) } | Where-Object { $_.Message -match 'ParentImage:.*php-cgi\.exe' -or $_.Message -match 'ParentCommandLine:.*php-cgi\.exe' } | Format-List TimeCreated, Message 如果发现 php-cgi.exe 派生 cmd.exe、powershell.exe、certutil.exe、curl.exe、mshta.exe 等进程,应按失陷处理,而不是升级后就结束:保留 Web/代理日志、隔离主机、检查 Web 目录新增文件、计划任务、服务、启动项和账号变更。 临时无法升级时,优先移除不必要的 CGI/FastCGI 映射或限制到可信来源。Apache 可在补丁上线前临时拦截原始查询串中的软连字符编码: RewriteEngine On RewriteCond %{THE_REQUEST} "\?[^\ ]*(%ad|%c2%ad|%25ad)" [NC] RewriteRule ^ - [F,L] 这类规则只能作为临时缓解,且需要确认代理层没有提前解码或规范化 URL。最终还是应升级 PHP、重启对应 Web/FastCGI 进程,并再次确认实际运行的 php-cgi.exe 路径和版本,避免机器上存在多套 PHP、升级了错误目录。
创建帐户或登录后发表意见