PHP-CGI的漏洞(CVE-2024-4577)

通过前两篇文章的铺垫,现在我们可以了解 CVE-2024-4577这个漏洞的原理

漏洞原理

CVE-2024-4577是CVE-2012-1823这个老漏洞的绕过,php cgi的老漏洞至今已经12年,具体可以参考我的另一个文档

简单来说,就是使用cgi模式运行的PHP,根据RFC3875的规定,Apache会将请求的QUERY_STRING作为命令行参数交给php-cgi执行。攻击者利用这个特性,就可以-d选项修改PHP的配置项,最后执行任意代码。

文章的最后,我也提到了当时PHP官方修复了两次才完成的补丁:

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);
}

修复方式就是在获取到QUERY_STRING后,检查其开头是否是横线(-),如果是-,则跳过后面对参数的解析。而@Orange 这次发现的CVE-2024-4577实际上就是横线检查的绕过,来说下原理。

在Windows中,如果当前系统的字符集(也被称为代码页,Code Page)非Unicode编码,在main()函数获取argv的时候,会自动执行编码的转换,其中就会涉及到所谓的Best-Fit。cp936

gbk

Best-Fit是一种字符映射策略,用以解决源代码页中的字符在目标代码页中没有直接等价物时的问题。在将Unicode代码页中字符转换成非Unicode代码页字符时,如果无法找到对应的字符,就会按照Best-Fit预定义的一个转换表进行转换。

比如,GBK编码(cp936)的Best-Fit Mapping转换表是:https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit936.txt

其中有一些有趣的字符转换,比如0xaa在转换后会变成a,0xb2在转换后会变成2,0xad在转换后会变成-。

所以,这里我们就可以利用Best-Fit这个特性,使用%ad来代替横线-。PHP在执行上述检查的时候,会认为命令行的第一个字符是0xAD;实际上main()函数的argv的第一个字符已经被Windows按照best-fit mapping转换成-。

本质来说,这仍然是一个利用解析差异绕过防御措施的案例。

什么情况下才会使用Best-Bit转换字符串?

我们可以编写下面这个简单的Python代码来复现best-fit这个trick:

os.system("php \xadh")

虽然传入的是\xad,但实际最后执行成功。

但我们多测试几次就会发现,并不是所有程序的所有参数都会进行Best-Bit的转换,我们测试下面几个命令:

php -h => php \xadh => 成功

php -v => php \xadv => 出错

python -h => python \xadh => 出错

arp -h => arp \xadh => 成功

有的成功,有的出错。这是为什么呢?

阅读PHP代码就会发现,有一部分选项是直接使用的main()函数的argv,另一部分选项是从Windows API GetCommandLineW()函数获取。由GetCommandLineW()获取的这部分参数仍然保持原样,没有转换成横线,最后无法正确执行。

XAMPP为什么可以被利用?

Orange在文章中提到,XAMPP默认配置就可以被利用。最初读到这里的时候,我会以为XAMPP是以php-cgi模式运行的PHP服务器,但下载安装XAMPP后我发现,PHP实际上是以Apache 2.0 Handler的方式运行。

这时候就非常有趣了,为什么XAMPP仍然可以在不修改任何配置文件的情况下直接利用呢?为什么很多人在实际测试中会遇到500错误呢?

这实际上是PHP没有修复的另一个安全机制bypass

比如,默认情况下我们需要将php解释器放在cgi-bin目录下,这样用户通过访问/cgi-bin/php/dir/script.php,即可执行/dir/script.php。

这个操作是很危险的,所以PHP增加了如下配置:cgi.force_redirect=1,开启了这个选项(默认开启)以后,只有经过了重定向规则请求才能执行。

Apache在重定向(rewrite)的时候,会增加一个名为REDIRECT_STATUS的环境变量,cgi.force_redirect就是依赖这个环境变量,来判断是否经历了重定向。

如果非Apache服务器,我们就需要设置一下cgi.redirect_status_env,来指定php判断请求是否经历重定向的条件。

XAMPP默认使用的sapi

我们下载XAMPP后,查看PHPINFO可以发现,其运行PHP的模式是“Apache 2.0 Handler”。在这个模式下,PHP会被编译成Apache的一个模块(dll动态链接库)并由Apache来调用执行。

我们在apache/conf/extra/httpd-xampp.conf中可以找到相关的配置:

 LoadFile "/program/xampp/xampp/php/php8ts.dll"
 LoadFile "/program/xampp/xampp/php/libpq.dll"
 LoadFile "/program/xampp/xampp/php/libsqlite3.dll"
 LoadModule php_module "/program/xampp/xampp/php/php8apache2_4.dll"

 <FilesMatch "\.php$">
   SetHandler application/x-httpd-php
 </FilesMatch>

 <FilesMatch "\.phps$">
   SetHandler application/x-httpd-php-source
 </FilesMatch>

可见,这里所有的.php后缀文件会被交给php8apache2_4.dll来执行,这和PHP CGI是没有任何关系的。

如何正常配置使用PHP CGI?

思考一个问题,如果我们需要正常配置一个使用PHP CGI解析PHP的Apache服务器,应该如何编写配置文件呢?

如果是部署基于脚本的CGI服务器,我们需要将可执行文件放置在某个目录下,比如/cgi-bin/hello.cgi。这个hello.cgi脚本的第一行是“shebang”,用以指定当前脚本的解释器,比如 # !/bin/bash

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI
    AddHandler cgi-script .cgi .pl .php
    Require all granted
</Directory>

  1. 设置 PHP 文件的 Shebang 行和 Content-Type 头

    在每个 PHP 脚本的开头添加 Shebang 行和 Content-Type 头。例如,/cgi-bin/hello.cgi 文件内容如下:

    #!/usr/bin/php
    <?php
    header('Content-Type: text/html; charset=UTF-8');
    
    echo "<html>";
    echo "<head><title>Hello, CGI!</title></head>";
    echo "<body>";
    echo "<h1>Hello, World!</h1>";
    echo "</body>";
    echo "</html>
    

    其中,#!/usr/bin/php 是 Shebang 行,用于指定 PHP 解释器的路径。

  2. 设置文件权限

    确保 PHP 文件具有执行权限,使其可以作为 CGI 脚本运行:

    chmod +x /cgi-bin/hello.cgi
    
  3. 测试脚本

    通过浏览器访问该脚本。例如,如果 CGI 脚本路径是 /cgi-bin/hello.cgi,则访问 http://yourdomain.com/cgi-bin/hello.cgi

事实上几乎没有PHP应用会这么编写代码,相比于这种将脚本直接作为可执行文件的方法,PHP另辟蹊径,专门设计了一个SAPI就叫php-cgi。

调用php-cgi执行一个PHP文件时,它会负责输出“Content-Type”头。比如执行echo '<?php echo 123;' | php-cgi

所以,类似于hello.cgi,我们也可以直接将php-cgi这个可执行文件映射到/cgi-bin/目录下,然后再使用Apache的Action指令,将PHP相关请求“重定向”到php-cgi上,最后执行PHP代码。

此时配置文件如下:

 ScriptAlias /php-cgi/ "/program/xampp/xampp/php/"

 <Directory "/program/xampp/xampp/htdocs">
     AddHandler application/x-httpd-php .php
     Action application/x-httpd-php /php-cgi/php-cgi.exe
 </Directory>

ScriptAlias指令的作用是将/php-cgi/路径指向/program/xampp/xampp/php/目录,

Action指令的作用就是将所有对.php文件的请求都使用/php-cgi/php-cgi.exe,也就是/program/xampp/xampp/php/php-cgi.exe来执行。

Apache在调用php-cgi的时候,会设置环境变量REDIRECT_STATUS。php-cgi为了确认这个请求确实是由Action指令执行的,而不是用户直接请求的,增加了一个开关“cgi.force_redirect”,默认开启。开启这个开关的情况下,php-cgi会验证此次执行是否包含环境变量REDIRECT_STATUS。

XAMPP为什么可以被利用?

了解了php-cgi正常的部署方式,我们回来看下XAMPP。虽然XAMPP执行PHP时使用的是Apache 2.0 Handler,但它仍然给PHP CGI预留了一个口子,就是使用ScriptAlias指令把php-cgi.exe映射到了Web目录下。

上述两个关键指令,XAMPP中使用了ScriptAlias指令,但是Action指令被注释了

这本身也没太大问题,因为有cgi.force_redirect的限制,在没有Action指令的情况下直接访问php-cgi.exe,REDIRECT_STATUS环境变量不会被设置。我们可以做个测试,直接请求/php-cgi/php-cgi.exe会返回500错误,查看日志会有Security Alert!的字眼

php-cgi.exe 接收cgi格式 -d=cgi.force_redirect=0 说明不再检测环境变量REDIRECT_STATUS

因为我们前面说到,对于REDIRECT_STATUS环境变量的限制是cgi.force_redirect这个开关来决定的。那么我们直接利用CVE-2024-4577漏洞,添加-d cgi.force_redirect=0关闭这个开关,即可绕过限制了。

值得注意的是,因为在高版本PHP中,allow_url_include这个开关已经被废弃,所以会抛出一个警告,导致Content-Type头输出失败,也会返回500。网上很多人没有注意到这一点,我们需要添加一个-d error_reporting=0来规避这一点。

PHP没有修复的另一种cgi.force_redirect绕过

前面我们使用-d cgi.force_redirect=0关闭PHP的检查,实际上PHP中有另一个Bug,也可以导致cgi.force_redirect的绕过,而且最新版本仍然没有修复

我们查看PHP源码sapi/cgi/cgi_main.c中对于REDIRECT_STATUS环境变量的检查代码:

​
     /* check force_cgi after startup, so we have proper output */
     if (cgi && CGIG(force_redirect)) {
         /* Apache will generate REDIRECT_STATUS,
          * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
          * redirect.so and installation instructions available from
          * http://www.koehntopp.de/php.
          *   -- kk@netuse.de
          */
         if (!getenv("REDIRECT_STATUS") &&
             !getenv ("HTTP_REDIRECT_STATUS") &&
             /* this is to allow a different env var to be configured
              * in case some server does something different than above */
             (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
         ) {
             zend_try {
                 SG(sapi_headers).http_response_code = 400;
                 PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
 <p>This PHP CGI binary was compiled with force-cgi-redirect enabled.  This\n\
 means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
 set, e.g. via an Apache Action directive.</p>\n\
 <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"PHP: 以 CGI 模式安装时 - Manual \">\
 manual page for CGI security</a>.</p>\n\
 <p>For more information about changing this behaviour or re-enabling this webserver,\n\
 consult the installation file that came with this distribution, or visit \n\
 <a href=\"PHP: Windows 系统下的安装 - Manual \">the manual page</a>.</p>\n");
             } zend_catch {
             } zend_end_try();
  if  defined(ZTS) && !defined(PHP_DEBUG)
             /* XXX we're crashing here in msvc6 debug builds at
              * php_message_handler_for_zend:839 because
              * SG(request_info).path_translated is an invalid pointer.
              * It still happens even though I set it to null, so something
              * weird is going on.
              */
             tsrm_shutdown();
  endif 
             free(bindpath);
             return FAILURE;
         }
     }

可见,除了getenv("REDIRECT_STATUS")以外,还有一个getenv("HTTP_REDIRECT_STATUS"),这两个环境变量都可以用于cgi.force_redirect的检查。而第二个环境变量HTTP_REDIRECT_STATUS是由HTTP_开头。

httpoxy漏洞就是因为很多HTTP客户端会使用HTTP_PROXY环境变量的值作为代理,因为这个环境变量是HTTP_开头,导致我们可以通过HTTP请求头控制,造成漏洞

PHP这里也是一样的问题,环境变量HTTP_REDIRECT_STATUS原本是为了兼容Netscape,但它是由HTTP_开头,所以用户可以直接控制。

PHP这里也是一样的问题,环境变量HTTP_REDIRECT_STATUS原本是为了兼容Netscape,但它是由HTTP_开头,所以用户可以直接控制。

我们去掉前面POC中的-d cgi.force_redirect=0,并添加一个HTTP头Redirect-Status: 1,仍然可以成功利用漏洞

虽然CVE-2024-4577漏洞在最新的PHP版本中已经修复了,但这个环境变量HTTP_REDIRECT_STATUS仍然可以导致cgi.force_redirect的绕过。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/740299.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

充电桩--充电桩智能化发展趋势

聚焦光伏产业、深耕储能市场、探究充电技术 小Q下午茶 相互交流学习储能和BMS相关内容 43篇原创内容 公众号 一、背景介绍 国家提出“新基建”以来&#xff0c;充电基础设施产业跃入人们的视线成为热门话题。充电基础设施作为充电网、车联网、能源网和物联网的连接器&…

JS对象、数组、字符串超详细方法

JavaScript 对象方法 对象创建的方式 对象字面量 var dog1 {name: "大黄",age: 2,speak: function () {console.log("汪汪");}, };使用Object构造函数 var dog2 new Object(); dog2.name "大黄"; dog2.age 2; dog2.speak function () …

卷积的通俗解释

以时间和空间两个维度分别理解卷积&#xff0c;先用文字来描述&#xff1a; 时间上&#xff0c;任何当前信号状态都是迄至当前所有信号状态的叠加&#xff1b;时间上&#xff0c;任何当前记忆状态都是迄至当前所有记忆状态的叠加&#xff1b;空间上&#xff0c;任何位置状态都…

初见:AntDB智能运维“三剑客“之ADC

引言 6月15日&#xff0c;PostgreSQL数据库技术峰会广州站圆满落幕。峰会上&#xff0c;亚信安慧数据库智能运维产品负责人李志龙介绍了AntDB的6大数据库引擎和3大工具产品能力。 这里的3大工具分别指&#xff1a; AntDB数据库迁移工具包 MTK 数据库智能运维平台 ACC AntDB数据…

SwiftUI 6.0(iOS 18/macOS 15)关于颜色 Color 的新玩法

概览 WWDC 2024 重装升级的 SwiftUI 6.0 让 Apple 不同平台&#xff08;iOS 18/macOS 15&#xff09;显得愈发的冰壶玉衡、美轮美奂。 之前梦寐以求的颜色混合功能在 WWDC 24 里终于美梦成真啦&#xff01; 在本篇博文中&#xff0c;您将学到如下内容&#xff1a; 概览1. 梦想…

this.$prompt 提示框增加文本域并修改文本域高度

2024.06.24今天我学习了如何对提示框增加文本域的方法&#xff0c;效果如下&#xff1a; 代码如下&#xff1a; <script>methods:{reject_event(){this.$prompt(驳回内容, 提示, {confirmButtonText: 确定,cancelButtonText: 取消,inputType: textarea,inputPlaceholder…

精益思想在机器人开发中的应用体现

精益思想源于制造业&#xff0c;旨在通过消除浪费、优化流程、持续改进来提升企业竞争力。在机器人开发中&#xff0c;精益思想同样具有指导意义。它要求开发团队在需求分析、设计、制造、测试等各个环节中&#xff0c;不断追求精益求精&#xff0c;力求在降低成本的同时提升产…

同元软控智能电动汽车数字化解决方案亮相CICV 2024

2024年6月18日-20日&#xff0c;由中国汽车工程学会、国家智能网联汽车创新中心、清华大学车辆与运载学院、清华大学智能绿色车辆与交通全国重点实验室举办的第十一届国际智能网联汽车技术年会&#xff08;CICV 2024&#xff09;在北京召开。苏州同元软控信息技术有限公司&…

C++并发之协程实例(四)(通过迭代器访问生成器序列)

目录 1 协程2 实例3 运行 1 协程 协程(Coroutines)是一个可以挂起执行以便稍后恢复的函数。协程是无堆栈的&#xff1a;它们通过返回到调用方来暂停执行&#xff0c;并且恢复执行所需的数据与堆栈分开存储。这允许异步执行的顺序代码&#xff08;例如&#xff0c;在没有显式回调…

【Linux】Centos升级到国产操作系统Openeuler

一、前言 迁移工具采用Openeuler官网提供的x2openEuler工具&#xff0c;是一款将源操作系统迁移到目标操作系统的迁移工具套件&#xff0c;具有批量化原地升级能力&#xff0c;当前支持将源 OS 升级至 openEuler 20.03。 官网链接&#xff1a;openEuler迁移专区 | 迁移专区首页…

8、MFC界面开发

界面开发 1、创建Ribbon样式的应用程序框架2、为Ribbon Bar添加控件2.1 下拉菜单2.2 添加消息处理函数 1、创建Ribbon样式的应用程序框架 创建MFC界面时选择样式为"Office"&#xff0c;然后再选择功能区。 2、为Ribbon Bar添加控件 Ribbon界面开发利用Ribbon Des…

lvs集群 Keepalived

Keepalived高可用集群 Keepalived概述 功能 LVS规则管理LVS集群真实服务器状态监测管理VIP Keepalived实现web高可用 安装keepalived软件 在webservers上配置 启动服务 webservers systemctl start keepalived.service ip a s | grep 192.168 #web1主机绑定vip 测试…

【gif制作】Win下视频生成GIF;工具GifCam单色保存,灰度保存,调速,编辑删除帧添加文本

下载地址 https://blog.bahraniapps.com/gifcam/#download https://gifcam.en.softonic.com/ 界面功能 GifCam 简洁、小巧的 gif 录制软件。GifCam就像照相机一样位于所有窗口的顶部&#xff0c;可以移动它并调整其大小录屏所需的区域。 如图&#xff1a;空闲状态下窗口内…

【uniapp】HBuilderx中uniapp项目运行到微信小程序报错Error: Fail to open IDE

HBuilderx中uniapp项目运行到微信小程序报错Error: Fail to open IDE 问题描述 uniapp开发微信小程序&#xff0c;在HBuilderx中运行到微信开发者工具时报错Error: Fail to open IDE 解决方案 1. 查看微信开发者工具端服务端口是否开放 打开微信开发者工具选择&#xff1…

探秘獭崎酱酒的“12987”工艺,品味纯正酱香

随着中国酱酒市场的不断发展&#xff0c;獭崎酱酒凭借其独特的“12987”酿造工艺&#xff0c;逐渐在白酒行业中崭露头角。今天&#xff0c;我们将深入探讨这一工艺的奥秘&#xff0c;并品味这款独具风味的酱香型白酒。      獭崎酱酒品牌创立于2015年&#xff0c;通过深入调…

小程序安卓手机点击uni-data-select 下拉框选择器会出现蓝色阴影

解决方法&#xff1a;在导入的包中找到uni-data-select.vue&#xff0c;接着找到.uni-stat__select样式&#xff0c;把cursor: pointer去掉。 如果出现穿透问题&#xff0c;uni-select__selector的z-index加高&#xff0c;默认是2。

Linux 字符型设备 + platform总线 + sysfs设备模型

1 概述 第一部分先简单介绍下字符型设备 platform总线 sysfs设备模型的关系。 1.1 . 字符设备驱动 Linux设备驱动分三种&#xff0c;包括字符设备驱动、块设备驱动和网络设备驱动。字符设备只能按字节流先后顺序访问设备内存&#xff0c;不能随机访问。鼠标、触摸屏、LCD等…

骑马与砍杀战团mod制作-基础-对话制作笔记(四)

骑马与砍杀战团mod制作-基础-对话制作笔记&#xff08;四&#xff09; 资料来源 学习的资料来源&#xff1a; b站【三啸解说】手把手教你做【骑砍】MOD&#xff0c;基础篇&#xff0c;链接为&#xff1a; https://www.bilibili.com/video/BV19x411Q7No?p4&vd_sourcea507…

P8813 [CSP-J 2022] 乘方

题目&#xff1a; P8813 [CSP-J 2022] 乘方 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 提交记录&#xff1a; 记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 个人主页&#xff1a; xuzb 的个人中心 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) AC代码&…

适用于轨道交通专用的板卡式网管型工业以太网交换机

是网管型 CompactPCI板卡式冗余环网交换机。前面板带有6个 10/100/1000Base-T(X)M12接口。后面的CPCI接口有 8个10/100/1000Base-T (X) 以太网接口。 是特别为轨道交通行业EN50155标准要求而设计的坚固型交换机。它同时具有以下特性&#xff1a; ● 支持2线以太网距离扩展端口&…