freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

PHP三种解析方式(Nginx解析漏洞)
2022-12-16 09:32:28
所属地 江西省

PHP_MOD

以模块化的方式运行:将PHP集成到Apache中,以同一个进程运行

CGI(公共网关接口)Common Gateway Interface

Apache在遇到PHP脚本时,会将其提交给CGIphp-cgi)应用程序进行处理,解释之后再将结果返回给Apache,然后再返回给请求的用户(CGI是规定web server传递过来的数据是何种标准格式,简单说就是一个协议

  1. 如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据
  2. 如果请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器

需要时才创建

FASTCGI (多进程的CGI)

这种形式是CGI的加强版本,CGI是单进程、多线程的运行方式,程序执行完成之后就会销毁,所以每次都需要加载配置和环境变量(创建-执行)

FastCGI则不同,FastCGI像是一个常驻 (long-live) 型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去创建新的进程 。FastCGI进程管理器自身初始化,启动多个CGI解释器进程 (在任务管理器中可见多个php-cgi)并等待来自web server的连接

  1. 首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境
  2. 然后再启动多个worker
  3. 当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率提高了
  4. 而且当worker不够用时,master可以根据配置预先启动几个worker等着,同时如果发现空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源

提前创建好

Nginx解析漏洞:

nginx默认以cgi的方式支持php的运行,在配置文件中如下配置:

location ~ \.php$

{    

root html;  

fastcgi_pass 127.0.0.1:9000;   

fastcgi_index index.php;   

fastcgi_param SCRIPT_FILENAME /scripts/$fastcgi_script_name;   

include fastcgi_params;

}

背景说明

PHP中,经常要获取当前请求的URL的路径信息,一般可以通过环境变量$_SERVER['PATH_INFO']获取,而cgi.fix_pathinfo选项与这个值得获取有关,PATH_INFO是一个CGI1.1的标准,经常用来作为传递参数给后端的CGI Server

被很多系统用来优化url路径格式,比如对于很多框架,下面这个网址

比如:http://shtwo.top/tag/Rev27?c=index&m=search

  • $_SERVER['PATH_INFO'] = '/tag/Rev27'
  • $_SERVER['QUERY_STRING'] = 'c=index&m=search'

php.ini中的配置参数cgi.fix_pathinfo=1,它是用来对设置cgi模式下为php是否提供绝对路径信息或PATH_INFO信息

【若PHP获取不到PATH_INFO信息,那些依赖PATH_INFO进行URL美化的程序就失效了】

配置参数

  1. location对请求进行选择的时候会使用URI环境变量(也就是URL中的传参以及目录格式)进行选择
    1. 其中传递到后端Fastcgi的关键变量SCRIPT_FILENAMEnginx生成的$fastcgi_script_name决定

      fastcgi_param指令负责将参数传给FastCGI Server

    2. 而通过分析可以看到 $fastcgi_script_name是直接由URI环境变量控制的

  2. 这里就是产生问题的点:而为了较好的支持PATH_INFO的提取,PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出最终要执行的那个文件的名称

攻击场景

  1. 假设存在一个URL:http://shtwo.top

  2. 我们以如下的方式去访问: http://shtwo.top/test/test.jpg/test.php漏洞利用

  3. nginx将会得到:/test.jpg/test.php参数

  4. 经过location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为 :/scripts/test.jpg/test.php

  5. 后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理 (cgi_fix_pathinfo = 1),一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启

    cgi.fix_pathinfo=1用于修复路径,如果当前路径不存在则采用上层路径】

    php通过该选项查找的方式是查看文件是否存在,在检查到test.php不存在后,将采用上层路径,也就是test.jpg

    此时分离出来的:

    • PATH_INFOtest.php
    • SCRIPT_INFO/script/test.jpg
    //判断逻辑
    if (script_path_translated &&
         (script_path_translated_len = strlen(script_path_translated)) > 0 &&
         (script_path_translated[script_path_translated_len-1] == '/' ||
    
  6. 最后,由于test.php不存在,/scripts/test.jpg作为此次请求需要执行的脚本,而nginx会使用php解析器来处理这个jpg文件,攻击者就可以实现让nginxphp来解析任何类型的文件

漏洞的本质实际上就是由于fastcgiweb serverscript路径级参数的理解不同出现的问题:

Nginx接收到/test.jpg/test.php的请求时,其 PATH_INFO会设置为/test.jpg/test.php,由于其中请求了php文件,需要解析,于是直接将该路径 PATH_INFO传递给CGI,拼接给其$fastcgi_script_name,交给CGI进行解析,CGI收到后会尝试待解析的文件是否存在,若开启了cgi_fix_pathinfo选项,则当前路径的文件不存在,会继续尝试上一级文件,而此时若是没有设置security.limit_extensions=.php限制只能解析.php的文件,则会将所有后缀的文件都尝试以php文件进行解析,这也就带来了安全的风险

这是典型的因为跨系统语境不同导致对同一个请求的不同解释导致的漏洞,它的攻击面是带有这种漏洞的nginx

预防方式

  1. cgi_fix_pathinfo=0不合实际,会影响实际业务
  2. php-fpm.conf中的 security.limit_extensions=.php(该配置将限制fastcgi解析文件的格式),此项设置为空的时候才允许fastcgi.png等文件当做代码解析

深入学习

Nginx 与 pathinfo - Steemit

# 渗透测试 # web安全 # 漏洞分析
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录