一、什么是文件包含
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,无需再次编写,这种调用文件的过程一般被称为文件包含
二、文件包含漏洞形成原因
程序开发人员将被包含的文件设置为变量,用来进行动态调用,这种灵活性通过动态变量的方式引入需要包含的文件时,用户对这个变量可控而且服务端又没有做合理的校验或者校验被绕过就造成了文件包含漏洞
三、PHP文件包含的函数
- include( )
当使用该函数包含文件时,只有代码执行到 include()函数时才将文件包含进来,发生错误时之给出一个警告,继续向下执行
- include_once( )
功能与 Include()相同,区别在于当重复调用同一文件时,程序只调用一次
- require( )
require()与 include()的区别在于 require()执行如果发生错误,函数会输出错误信息,并终止脚本的运行
- require_once( )
功能与 require()相同,区别在于当重复调用同一文件时,程序只调用一次
四、文件包含类型
1.本地文件包含:
- 以DVWA文件包含漏洞为例,我们再dvwa目录下创建一个2.png文件,里面隐藏着phpinfo,php的测试语句,使用该漏洞包含2.png文件,会以当前程序语言来执行
- png文件,如果包含的文件不符合当前程序语言格式,会直接输出2.png文件里的内容
- 如果限制了文件包含的后缀此时,可以使用%00截断,不过需要有前提条件:
1). PHP版本 < 5.3 (不包括5.3) ;
2). PHPmagic_quotes_gpc = off;(对输入的字符创中的字符进行转义处理)
3).PHP对所接收的参数,未使用addslashes函数。(addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。)
2.中间件日志文件包含(Apache)
- 再请求RUL路径或者User-Agent直接写上php测试代码,发现该代码会存在Apache日志文件里
- 本地日志文件包含
3.远程文件包含
形成原因:当包含的文件在远程服务器上时,就形成了远程文件包含。
- 远程包含文件需要满足以下几点:
1). 需要php.ini中allow_url_include = on以及allow_url_fopen=on
2). 所包含远程服务器的文件后缀不能与目标服务器语言相同。(比如目标服务器是php脚本语言解析的,那么包含的远程服务器文件后缀不能是php)
4.文件包含漏洞之伪协议
data:text/plain 或 data:text/plain;base64(执行base64之后的编码)
php://input
php://filter
file://
zip://
- data:text/plain,可以直接执行后面的php语句
- php://input可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行
- file:// 用于访问本地文件系统,且不受allow_url_fopen与allow_url_include的影响。
使用方法:file://文件绝对路径 file://C:/Windows/system.ini。
五、防御方案
1.PHP 中使用 open_basedir 配置限制访问在指定的区域
2.过滤.(点)/(反斜杠)(反斜杠)
3.禁止服务器远程文件包含