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 .phpAction 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.mzph.cn/diannao/34376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MOD和DIV的区别说明

1.说明 div 是取 A/BC&#xff0c;得到是C的值&#xff1b; mod 是取 A/BC...D,得到余数D的值。 2.实践 A8,B3,C2,D2 A9,B3,C3,D0

13.1.k8s集群的七层代理-ingress资源(进阶知识)

目录 一、ingress概述 1.前言 2.问题 3.ingress资源 二、ingress-nginx是什么 三、ingress-nginx 实现原理 四、部署ingress-nginx 1.获取部署文件 ingress-nginx.yaml 2.部署ingress-nginx 3.检查部署是否成功 五、编写使用Ingress样例代码 1.Ingress资源对象yaml文…

PhotoShop自动生成号码牌文件

1、说明 设计卡牌的时候&#xff0c;遇到自动生成编号&#xff0c;从01500到-02500&#xff0c;一个一个的手写&#xff0c;在存储保存成psd格式的文件&#xff0c;会很耗时。 下面将介绍如何使用ps自动生成psd格式的文件 2、使用excle生成数字 从01500到-02500 第一步&…

做现货白银模拟账户太爽,一做实盘就亏?

太多现货白银投资者有过这样的经历&#xff1a;自己做模拟账户的时候如鱼得水&#xff0c;盈利几乎手到拿来&#xff0c;实在爽得不要不要的&#xff0c;但在实盘操作中却常常面临亏损&#xff0c;甚至出现巨亏的情况。其实这主要是由于模拟交易与实盘交易之间存在显著的差异&a…

VBA技术资料MF166:提取某区域特定数据到工作表

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞(六十六)

Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞&#xff08;六十六&#xff09; 漏洞环境搭建 这里我们使用Kali虚拟机安装docker并搭建vulhub靶场来进行ThinkPHP漏洞环境的安装&#xff0c;我们进入 ThinkPHP漏洞环境&#xff0c;可以 cd ThinkPHP&#xff0c;然后通过 …

3d怎么把歪的模型摆正?---模大狮模型网

在进行3D建模过程中&#xff0c;有时候会遇到模型出现歪曲或者旋转不正确的情况&#xff0c;这可能会影响到后续的设计和渲染效果。因此&#xff0c;学会将歪曲的模型摆正是一个非常重要的技巧。模大狮将介绍几种常用的方法&#xff0c;帮助您有效地将歪曲的3D模型摆正&#xf…

Python19 lambda表达式

在 Python 中&#xff0c;lambda 表达式是一个小型匿名函数&#xff0c;通常用于实现简单、单行的函数。lambda 函数可以接受任意数量的参数&#xff0c;但只能有一个表达式。 基本语法&#xff1a; lambda arguments: expression这里&#xff0c;arguments 是传递给 lambda …

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

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

多路h265监控录放开发-(14)

首先创建一个新类XCalendar继承QCalendarWidget类&#xff0c;然后在UI视图设计器中把日历提升为XCalendar&#xff0c;通过这个函数自己设置日历的样式 xcalendar.h #pragma once #include <QCalendarWidget> class XCalendar :public QCalendarWidget { public:XCal…

论文神器:即插即用归一化模型!无缝插入助力涨点!

归一化是深度学习和机器学习中一个非常重要的步骤&#xff0c;它通过对数据或网络层的输出进行变换&#xff0c;使其符合特定的标准&#xff0c;有效缓解不同特征间由于量纲和数值范围差异造成的影响&#xff0c;加速模型的收敛速度&#xff0c;并提高模型精度。 大多数归一化…

【ONLYOFFICE深度探索】:ONLYOFFICE桌面编辑器8.1震撼发布,打造高效办公新境界

文章目录 一、功能完善的PDF编辑器&#xff1a;解锁文档处理新维度二、幻灯片版式设计&#xff1a;释放创意&#xff0c;打造专业演示三、改进从右至左显示&#xff1a;尊重多元文化&#xff0c;优化阅读体验四、新增本地化选项&#xff1a;连接全球用户&#xff0c;跨越语言障…

os7安装gitlab

gitlab安装要求&#xff1a;os7以上版本&#xff0c;4G内存&#xff0c;磁盘50GB 1.克隆 由于我这里不想影响原来的&#xff0c;所以这里克隆一个os系统。如果其他是第一次安装则不用。 2.修改ip地址 cd /etc/sysconfig/network-scriptsvi ifcfg-ens33 按&#xff1a;insert…

对于GPT-5的些许期待

目录 1.概述 2.GPT-5技术突破预测 3.智能系统人类协作 3.1. 辅助决策 3.2. 增强创造力 3.3. 处理复杂任务 3.4.人机协同的未来图景 4.迎接AI技术变革策略 4.1.教育方面 4.2.职业发展方面 4.3.政策制定方面 4.4.人才与技能培养 1.概述 GPT-5作为下一代大语言模型&a…

cityscapes数据集转换为COCO数据集格式【速来,我吃过的苦,兄弟们就别再吃了】

利用CityScapes数据集&#xff0c;将其转换为COCO格式的实例分割数据集 – – – 进而再训练出新的YOLOv8-seg模型 写个前言&#xff1a; 人嘛&#xff0c;总想着偷点懒&#xff0c;有现成的数据集&#xff0c;就得拿来用&#xff0c;是吧&#xff1f;确实是这样。 接下来的步…

开启调试模式

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 run()方法虽然适用于启动本地的开发服务器&#xff0c;但是每次修改代码后都要手动重启它。这样并不够方便&#xff0c;如果启用了调试支持&#xff…

AIGC-商业设计大师班,商业设计全流程(22节课)

课程内容&#xff1a; 02.AIGC大师计划(百天磨炼&#xff0c;只为让你一次成为大师).mp4 03.这5个细心的翻译工具我想全部告诉你(感受不到的工具才是好工具),mp4 04.扎实的基础是成功的关键(汇聚精华指导新功能演示方法).mp4 05.AI绘画大师级十二体咒语书写(大师级起步).mp…

SaaS企业营销:海外小众独立站Homage如何实现客群破圈?

深度垂直的市场标签对小众出海品牌来说&#xff0c;既是挑战也是机遇。由于品牌若想取得长远发展&#xff0c;无法仅凭单一狭窄的市场空间来支撑其持续壮大。因此&#xff0c;在追求可持续发展的道路上&#xff0c;小众品牌面临着需要突破既有市场圈层的挑战。 在这一过程中&am…

基于Java考研助手网站设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

Calibre - 翻译电子书(Ebook Translator)

本文参考教程 &#xff1a;https://bookfere.com/post/1057.html 使用 Ebook Translator 插件&#xff0c;详见&#xff1a; 官网&#xff1a;https://translator.bookfere.comgithub &#xff1a;https://github.com/bookfere/Ebook-Translator-Calibre-Plugin 一、基本翻译 …