今天继续给大家介绍渗透测试相关知识,本文主要内容是CVE-2019-11043 Nginx配置详解。
免责声明:
本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负!
再次强调:严禁对未授权设备进行渗透测试!
一、Nginx处理PHP文件与Fastcgi
要想理解CVE-2019-11043漏洞成因,我们从Nginx处理PHP类型的文件开始讲起。在早期(Web1.0)时期,web大多是静态页面,所谓静态页面,即HTML、JPG等静态资源组成,没有PHP、JSP等的动态页面语言。
后来PHP等动态语言出现以后,Nginx如何支持PHP语言的网站称为了一个问题。Apache的解决方案是将处理PHP等动态语言的程序编译成一个模块,当我们需要处理PHP页面时,就可以调用这个模块。而对于Nginx而言,选择的是另一种解决方案,即Nginx本身只解析静态资源,如果有PHP页面,就将这个请求给PHP相关程序来进行处理,然后将处理后的结果反馈给用户。
为了解决这种PHP(语言解析器)与Nginx(Web服务器)之间的通信问题,我们制定了cgi协议。有了cgi协议以后,意味着以后出现新的动态语言(比如go语言),出现了新的Web服务器,只要遵循了cgi协议,就可以快速方便的实现语言解析器和Web服务器之间的通信问题。cgi协议非常重要,但是也有其自身的缺点,那就是每次语言解析器和Web服务器之间的通信,都需要创建一个进程,当通信结束后,就要杀死这个进程,这样的机制无疑大大浪费了系统资源。为了解决这一问题我们,我们对cgi协议进行了修改,cgi协议的改良版本有很多,但是其中一个很具有代表性的就是fast-cgi协议。fast-cgi协议改进了进程的处理模式,当一次通信完成后,通信进程会得以保留,不会杀死通信使用的进程,其他的通信还可以继续使用这个进程,这样一来,就大大提升了系统资源使用效率。
对于Nginx而言,为了实现与PHP的通信交互,因此出现了php-cgi和php-fpm。php-cgi支持cgi协议,可以用于处理和解析PHP脚本程序,php-cgi通过调用PHP的php_execute_script函数来解析和运行PHP脚本。php-cgi的问题在于,尽管其本身可以解析和处理PHP脚本程序,但是其本身没有进程管理的相关功能。为了解决这一问题,就出现了php-fpm。php-fpm全称是php Fastcgi Process Manager,php-fpm实现了Fast-cgi协议,并可以提供进程管理的相关功能。在PHP5.4版本之前,Nginx处理PHP的流程是调用php-fpm,php-fpm再创建进程,调用php-cgi,以此实现了Ngixn对PHP的解析问题,此时php-fpm起到的是管理php-cgi的作用。在PHP5.4版本之后,php内核中集成了php-fpm,本身带有了php解析的功能,就不再以来php-cgi来解析PHP了。
二、Nginx配置中location相关含义
在上一章中,我们讲解了Nginx处理PHP文件与Fastcgi。简单来看,Nginx本身没有处理PHP的能力,为了实现对PHP相关脚本代码的解析,就需要调用Fastcgi。
在Nginx实际配置中,对Fastcgi的解析,需要我们进行实际的配置。存在CVE-2019-11043漏洞的Nginx相关配置如下所示:
location ~ [^/]\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
在上述配置中,location是Nginx配置中的一个模块,具体功能是指明不同的文件需要交给哪个程序来进行处理。location后面的~含义是大小写无关的正则匹配,后面紧跟着是一个正则表达式,意思是凡是符合后面正则表达式的请求,都需要按照本模块大括号里面的配置来进行处理。这一部分详细了解可参考文章:LNMP详解(六)——Nginx location语法详解
[^/].php(/|$)是一个正则表达式(关于正则表达式,如果看不懂,可参考Linux 正则表达式与元字符一文),表示匹配末尾是.php的字符串或者是中间存在.php/的字符串。
在这里,上述表达式的含义是匹配需要进行php解析的页面。之所以匹配中间存在.php/的字符串,是因为考虑到有些站点使用了伪静态,例如show.php/id/110,该页面表面上是一个静态页面,但是其实等同于show.php?id=110。这样,上述正则表达式就可以把这样需要PHP解析的页面来匹配上了。
在大括号内,又有很多参数,fastcgi_pass指定了FastCGI 服务器的地址,即Nginx要把PHP请求送给谁来处理。fastcgi_index指定了如果请求的最后是一个斜杠时,我们需要附加到斜杠后面的URL,实际上就是默认页面。include fastcgi_params表示引入FastCGI的各项参数,这一行配置是为了使得后面的配置生效。之所以要进行这样的配置,是因为Nginx在与PHP进行通信的时候,有时需要传递一些必要的参数,这样才方便PHP的解析。为了解决这种参数传递的问题,就需要配置FastCGI参数。fastcgi_split_path_info参数后面是一个正则表达式,但是可以匹配两个字符串,第一个匹配的是(.+?\.php),第二个是(/.*)。匹配到的第一个字符串会被赋值给$fastcgi_script_name参数,第二个字符串会被赋值给$fastcgi_path_info参数。例如,假设请求是show.php/id/110,那么在进行匹配后,$fastcgi_script_name参数的值是show.php,而$fastcgi_path_info参数的值是/id/110。后面的两个fastcgi_param分别用于设置PATH_INFO和SCRIPT_FILENAME的值,$fastcgi_path_info为刚刚fastcgi_split_path_info匹配后的值,$document_root$fastcgi_script_name表示将这两个参数的值链接到一起。参数SCRIPT_NAME表示脚本名称,PATH_INFO表示可自定义的变量。
在如上设置后,就可以真正实现Nginx到PHP的通信了。
三、CVE-2019-11043漏洞原因
上述Nginx的配置会导致CVE-2019-11043漏洞,主要漏洞成因是在如下配置:
fastcgi_split_path_info ^(.+?\.php)(/.*)$
如果用户传入的信息存在换行符(URL编码是%0a),则会破坏fastcgi_split_path_info参数后面的正则表达式匹配,从而导致PATH_INFO变量为空,从而触发漏洞。攻击者通过精心的构造和利用,可以导致远程代码执行。
原创不易,转载请说明出处:https://blog.csdn.net/weixin_40228200