一、漏洞描述
程序在引用文件的时候,引用的文件名,用户可控的情况,传入的文件名没有经过合理的校验或者校验不严,从而操作了预想之外的文件,就有可能导致文件泄露和恶意的代码注入。
程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这重文件调用的过程一般被称为文件包含。程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
几乎所有脚本语言都会提供文件包含的功能,但文件包含漏洞PHP Web Application中居多,而在JSP、ASP、ASP.NET程序中却非常少,甚至没有,这是有些语言设计的弊端。
二、常见文件包含函数
三、漏洞危害
1、敏感信息泄露
2、拒绝服务攻击
3、执行恶意代码
4、配合文件上传,扩大危害
一般来说,远程文件包含漏洞危害更大。
四、利用前提
1、web应采用include()等文件包含函数通过动态变量的方式引入需要包含的文件
2、用户能够控制该动态变量
五、两个关键选项
Allow_url_fopen = on
是否允许将URL(HTTP,HTTPS等)作为文件打开处理,默认开启
Allow_url_include= on
是否允许include()和require()函数包含URL(HTTP,HTTPS)作为文件处理,默认关闭,远程文件包含必须为开启。
六、挖掘
抓包观察有无明显的参数用于打开或使用文件,在漏洞挖掘过程中,注意下即可,如果遇到疑似文件包含,可以使用以下的测试方法。
a.php是fileinclude.php的同⼀⽬录的⽂件 http://www.aaa.com/fileinclude.php?file=file://a.php
打开⽬标⽹站,⼀般不会被过滤掉 http://www.aaa.com/fileinclude.php?file=http://www.aaa.com
因为不知道对参数的过滤方式,因此该方法不一定成功。
七、本地文件包含(LFI)
能够读取或执行包含本地文件的漏洞,称为本地文件包含漏洞。
重要特点:把任何包含进来的文件都当作PHP文件来执行。
下面是pikachu靶场的源码
$_GET['filename'] 接收客户端传的参数,其中没有任何过滤带⼊到 include 函数中, include 包含这个⽂件,引⼊到当前⽂件中,因此会造成⽂件包含漏洞; ⽐如:http://pikachu.com/vul/fileinclude/fi_local.php?filename=123.jpg 1.jpg是图⽚,但是当有⽂件包含漏洞时,这个图⽚会被当做 php ⽂件处理,当然前提是它 ⾥⾯有 php 的代码,这样我们就可以先写⼀个 php 代码的⽊⻢,然后伪装成图⽚上传,从⽽ 达到控制对⽅的⽬的。
八、php伪协议
1、简介
PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数,除了这些封装协议,还能通过stream_wrapper_register()来注册自定义的封装协议。
可以在phpinfo中的Registered PHP Streams中找到可使用的协议。
2、测试环境
测试代码
php.ini配置
各协议的利用条件和方法
1、PHP://filter
php://filter是一种元封装器,设计用于数据流打开时的筛选过滤应用。
参数
过滤器列表
字符串过滤器
String.strip_tags
转换过滤器
压缩过滤器
加密过滤器
可⽤过滤器列表:https://www.php.net/manual/zh/filters.php
利用姿势1:
?file=php:filter/read=convert.base64-encode/resource=index.php
通过指定末尾的文件,可以读取经base64加密后的文件源码,之后再base64解码一下就行,虽然不能直接获取到shell等,但能读取敏感文件危害也是挺大的,同时也能够对网站源码进行审计。
利用姿势2:
?file=php://filter/convert.base64-encode/resource=index.php
效果跟前面一样,只是少了个read关键字,在绕过一些waf时也许有用。
file://
专门用于访问本地文件系统和php://filter类似都可以对本地文件进行读取。
2、PHP://input
PHP://input是个可以访问请求的原始数据的只读流,将post请求中的数据作为php代码执行。
利用条件:
Allow_url_fopen =on
Allow_url_include=on
注意:当entype=“multipart/form-data",php://input是无效的
利用姿势:
也可以使用curl进行利用
GETSHELL
3、Phar://
Phar://支持zip、phar格式的文件包含。
(1)zip
利用条件:php>=5.3.0
利用姿势1:配合文件上传漏洞,当仅可以上传zip格式时。
新建shell.php,使用zip格式压缩→shell.zip
新建shell.php,使用zip格式压缩→shell.zip
利用姿势2:
配合文件上传漏洞,当仅可以上传图片格式时。
针对phar://不管后缀是什么,都会当做压缩包来解压。
将做好的zip后缀改为png格式。
(2)phar
phar文件本质上也是一种压缩文件。
制作phar文件:
制作包含恶意代码文件的phar文件
1、确保本地php.ini中phar.readonly=off
2、编写恶意phar文件的php脚本
利用条件:php>=5.3.0
利用姿势1:
利用姿势2:
利用协议特性,更改后缀文件可适当绕过一些限制。
4、zip://
zip协议和phar协议类似,都支持相对路径和绝对路径。
在php version 5.2.9事已经修复zip://相对路径问题。
使用zip协议,需要将#编码为%23(浏览器时)
利用条件:php>=5.2(绝对路径) php>=5.29(相对/绝对路径)
利用姿势1:
利用姿势2:
针对zip://不管后缀是什么,都会当做压缩包来解压,可以适当的绕过一些限制。
5、bzip2://
需要安装,这里不做介绍
6、zlib://
利用条件:php>=5.2
利用姿势1:
?file=compress.zlib://shell.gz
7、data://
数据流封装器,和php://相似都是利用了流的概念。
利用条件
九、包含日志getshell
中间件例如iis、apache、nginx这些web中间件,都会记录访问日志,如果访问日志中或错误日志中,存在有php代码,也可以引入到文件包含中,如果日志有php恶意代码,也可以导致getshell。
利用条件:
1、需要知道服务器日志的存储路径
2、日志文件可读
在linux下日志文件权限默认是root而php的权限是www.data一般情况下是读取不了,如果是windows环境下是可以读取的,权限是允许的。
日志路径:
Linux:
Apache:
/etc/httpd/logs/access_log
/var/log/httpd/access_log
配置⽂件:/etc/httpd/conf/httpd.conf
index.php?page=/etc/init.d/httpd
Nginx:
⽇志⽂件在⽤户安装⽬录logs⽬录下
例如:/usr/local/nginx/logs
Win:
IIS6.0+win2003: C:\WINDOWS\system32\Logfiles
配置⽂件:C:/Windows/system32/inetsrv/metabase.xml
IIS7.0+win2003:%SystemDrive%\inetpub\logs\LogFiles
配置⽂件:C:\Windows\System32\inetsrv\config\applicationHost.config
集成环境: ⼩⽪:phpstudy_pro\Extensions\Apache2.4.39\logs\access.log
xampp:xampp\apache\logs\access.log
环境:
方便使用,制作一个具有文件包含漏洞的文件。
访问,测试,日志会记录。
我们可以直接插入恶意的php代码,使其记录下来。
==注意:浏览器会把<>编码,这种情况下,包含文件进来是执行不了里面的php代码的,这种情况我们可以使用burp绕过。==
同时,这里还需要注意一个问题,不要发送多个请求,不然会造成同个请求会写入多个,但payload不一样,这时候如果无法解析,就会报错。
十、phpinfo包含临时文件
原理:利用php post上传文件产生临时文件,phpinfo()读临时文件的路径和名字,本地包含该临时文件生成一句话后门。
这里可以参考P牛搭建的。
十一、包含session
先了解一下服务器上针对用户会话session的存储与处理是什么过程,只有了解了其存储和使用机制我们才能够合理的去利用它得到我们想要的结果。
1、测试环境
2、session存储
(1)存储方式
java是将用户的session存入内存中,而php则是将session以文件的形式存储在服务器某个文件中,可以在php.ini里面设置session的存储位置session.save_path
知道session的存储后,总结常见的php-session默认存放位置是很有必要的,因为在很多时候服务器都是按照默认设置来运行的,这个时候假如我们发现了一个没有安全措施的session包含漏洞就可以尝试利用默认的会话存放路径去包含利用。
(2)命名格式
如果某个服务器存在session包含漏洞,要想去成功的包含利用的话,首先必须要找到的是服务器是如何存放该文件的,只要知道了其命名格式我们才能够正确的去包含文件。
3、session利用
LFI本地⽂件包含漏洞主要是包含本地服务器上存储的⼀些⽂件,例如Session会话⽂件、
⽇志⽂件、临时⽂件等。但是,只有我们能够控制包含的⽂件存储我们的恶意代码才能拿到
服务器权限。
其中针对 LFI Session ⽂件的包含或许是现在⻅的⽐较多,简单的理解session⽂件包含
漏洞就是在⽤户可以控制session⽂件中的⼀部分信息,然后将这部分信息变成我们的精⼼构
造的恶意代码,之后去包含含有我们传⼊恶意代码的这个session⽂件就可以达到攻击效果。
利⽤条件: session⽂件路径已知,且其中内容部分可控。
利⽤姿势:
分析session.php可以看到⽤户会话信息username的值⽤户是可控的,因为服务器没有对
该部分作出限制。那么我们就可以传⼊恶意代码就⾏攻击利⽤。
十二、远程文件包含(RFI)
十三、绕过姿势
我们平常很多时候碰到的情况肯定不会是简单include $_GET【‘file’】;这样直接把变量传入包含函数的,在很多时候包含的变量/文件不是完全可控的。
现在代码常做的限制有这些。
1、Bypass-指定前缀
测试代码
(1)LFI-目录遍历
(2)LFI-编码绕过
2、Bypass-指定后缀
测试代码
(1)RFI-URL
2、LFI-压缩协议
(1)利用姿势
(2)利用phar协议
(3)利用zip协议
(3)LFI-长度截断
(4)LFI-零字节截断
3、Bypass-协议限制
十四、防御方案
- 严格判断包含中的参数是否外部可控,因为⽂件包含漏洞利⽤成功与否的关键点就
在于被包含的⽂件是否可被外部控制; - 路径限制:限制被包含的⽂件只能在某⼀⽂件内,⼀定要禁⽌⽬录跳转字符,
如:"../"; - 包含⽂件验证:验证被包含的⽂件是否是⽩名单中的⼀员;
- 尽量不要使⽤动态包含,可以在需要包含的⻚⾯固定写好,如:
include('head.php'); - 设置 allow_url_include 为 Off ;
十五、总结与后记
本篇文章只是学习笔记,请注意。