温故知新--文件上传文件名绕过的内部原理
文件上传文件名绕过原理
最近学习php的fpm和cgi看到了以前刚开始学习到文件上传时的一些漏洞发生原理,记录一下吧
Nginx(IIS7)解析漏洞
漏洞现象
用户访问http://127.0.0.1/favicon.ico/.php
时,访问到的文件是favicon.ico,但却按照.php后缀解析了
原理
正常来说,SCRIPT_FILENAME
的值是一个不存在的文件/var/www/html/favicon.ico/.php
,是PHP设置中的一个选项fix_pathinfo
导致了这个漏洞。PHP为了支持Path Info模式而创造了fix_pathinfo
,在这个选项被打开的情况下,fpm会判断SCRIPT_FILENAME
是否存在,如果不存在则去掉最后一个/
及以后的所有内容,再次判断文件是否存在,往次循环,直到文件存在。
所以,第一次fpm发现/var/www/html/favicon.ico/.php
不存在,则去掉/.php
,再判断/var/www/html/favicon.ico
是否存在。显然这个文件是存在的,于是被作为PHP文件执行,导致解析漏洞。
正确的解决方法有两种,一是在Nginx端使用fastcgi_split_path_info
将path info信息去除后,用tryfiles判断文件是否存在;二是借助PHP-FPM的security.limit_extensions
配置项,避免其他后缀文件被解析。
.php3 .php4 .php5 .php7
这个可以去看一下PHP-FPM的未授权访问漏洞
在fpm某个版本之前,我们可以将SCRIPT_FILENAME
的值指定为任意后缀文件,比如/etc/passwd
;但后来,fpm的默认配置中增加了一个选项security.limit_extensions
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5 .php7
其限定了只有某些后缀的文件允许被fpm执行,默认是.php
。所以,当我们再传入/etc/passwd
的时候,将会返回Access denied.
注: 这个配置也会影响Nginx解析漏洞, 但也有少部分发行版安装中security.limit_extensions
默认为空,此时就没有任何限制了。