文件包含


文件包含漏洞

描述

程序在引用文件的时,引用的文件名,用户可控的情况,传入的文件名没有经过合理的校验或校验不严,从而操作了预想之外的文件,就有可能导致文件泄漏和恶意的代码注入。

程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这重文件调用的过程一般被称为文件包含。程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。

几乎所有脚本语言都会提供文件包含的功能,但文件包含漏洞在 PHP WebApplication 中居多,而在 JSP、ASP、ASP.NET 程序中却非常少,甚至没有,这是有些语言设计的弊端。在 PHP 中经常出现包含漏洞,但这并不意味这其他语言不存在。

常见的文件包含函数

include():执行到 include 时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行

require():只要程序一运行就包含文件,找不到被包含的文件时会产生致命错误,并停止脚本

include_once()和 require_once():若文件中代码已被包含则不会再次包含

代码分析

cd /var/www/html/06/vul/fileinclude
cat fileinclude.php

image-20211024175323997

我们把源码拿出来看 清晰一点

image-20211024175349393

$_GET[‘filename’] 接收客户端传的参数,没有任何过滤,然后带入到 include 函数中,include 包含这个文件,引入到当前文件中,因此会造成文件包含漏洞。

利用

文件包含漏洞,需要引入上传的文件到网站目录,或是服务器内部的文件,而且权限是可读,才能引入进来,或远程包含进来,但是需要条件。

文件包含 /etc/passwd

这是Linux中一个比较敏感的文件

image-20211024175805618

文件包含图片

寻找网站上传点,把 php 恶意代码文件改成 jpg 上传到网站上,本地包含引入恶意代码,当文件被引入后代码就被执行。

image-20211024180029604

1.jpg

<?php phpinfo();?>

image-20211024180138015

包含日志文件getshell

中间件例如 iis 、apache、nginx 这些 web 中间件,都会记录访问日志,如果访问日志中或错误日志中,存在有 php 代码,也可以引入到文件包含中。如果日志有 php 恶意代码,也可导致 getshell。

linux 默认的 apache 日志文件路径是

访问日志

/var/log/apache2/access.log

错误日志

/var/log/apache2/error.log

把文件日志包含进来即可

image-20211024181734567

抓包写入php代码 send

image-20211024181831205

image-20211024181857838

但是在linux下我们没有权限包含日志文件,需要root权限,但是php权限是www-data,我们在windows下可以做到此操作

所以我们在phpstudy上新建一个网站,在根目录中写

image-20211024180755718

image-20211024180805215

还是同样的操作

image-20211024182425327

我们在apache中找到日志

image-20211024182454722

image-20211024182504581

可以看到php代码被记录了下来

包含日志文件 找到此日志路径

image-20211024183105183

包含日志文件发现php代码被执行了

image-20211024183031702

包含环境变量getshell

/proc/self/environ 这个文件保存了一些系统的变量

image-20211024184219595

我们抓包修改user-agent,写入php代码

image-20211024184107609

如果权限足够就会把代码写入到上面那个文件,包含此文件即可执行php代码

phpinfo文件包含临时文件

原理: 利用 php post 上传文件产生临时文件,phpinfo()读临时文件的路径和名字,

本地包含漏洞生成 一句话后门

1.php 在解析 multipart/form-data 请求时,会创建临时文件,并写入上传内容,脚本执行后即删除

2.phpinfo 可以输出$_FILE 信息

3.通过多种方式争取时间,在临时文件删除前进行执行包含

1)通过在数据报文中加入大量的垃圾数据,似 phpinfo 页面过大,导致 phpinfo页面过大,导致 php 输出进入流式输出,并不一次输出完毕

2)通过大量请求来延迟 php 脚本的执行速度php post 方式上传任意文件,服务器都会创建临时文件来保存文件内容。在 HTTP 协议中为了方便进行文件传输,规定了一种基于表单的 HTML 文件传输方法

其中要确保上传表单的属性是 enctype=”multipart/form-data”

其中 PHP 引擎对 enctype=”multipart/form-data”这种请求的处理过程如下:

1、请求到达;

2、创建临时文件,并写入上传文件的内容;

3、调用相应 PHP 脚本进行处理,如校验名称、大小等;

4、删除临时文件。

PHP 引擎会首先将文件内容保存到临时文件,然后进行相应的操作。临时文件的名称是 php+随机字符 。$_FILES 信息,包括临时文件路径、名称在 PHP 中,有超全局变量$_FILES,保存上传文件的信息,包括文件名、类型、临时文件名、错误代号、大小把文件上传到 phpinfo 获取临时文件路径

利用

写个上传表单,让文件上传到我们写的phpinfo.php

image-20211024185328114

上传文件后,phpinfo创建了一个临时文件

image-20211024185239634

这个临时文件在上传过后就会被删除,所以我们在目录下找不到此文件

我们利用脚本修改利用的文件和路径

脚本就不放了

执行成功后回在/tmp下建立一个g的文件,

image-20211024193928068

g文件已经创建了

image-20211024194041896

包含此文件

image-20211024194635206

这里1也可以执行命令

image-20211024194725911

伪协议

file:// — 访问本地文件系统

http:// — 访问 HTTP(s) 网址

ftp:// — 访问 FTP(s) URLs

php:// — 访问各个输入/输出流(I/O streams)

zlib:// — 压缩流

data:// — 数据(RFC 2397)

glob:// — 查找匹配的文件路径模式

phar:// — PHP 归档

ssh2:// — Secure Shell 2

rar:// — RAR

ogg:// — 音频流

expect:// — 处理交互式的流

php.ini参数设置

在 php.ini 里有两个重要的参数 allow_url_fopen、allow_url_include。

allow_url_fopen:默认值是 ON。允许 url 里的封装协议访问文件;

allow_url_include:默认值是 OFF。不允许包含 url 里的封装协议包含文件;

各协议的利用条件和方法:

image-20211026170242776

php://input

php://input 可以访问请求的原始数据的只读流,将 post 请求的数据当作 php 代码执行。当传入的参数作为文件名打开时,可以将参数设为 php://input,同时 post想设置的文件内容,php 执行时会将 post 内容当作文件内容。

注:当 enctype=”multipart/form-data”,php://input 是无效的。php.ini 条件是 allow_url_fopen =ON allow_url_include=ON

image-20211026171121497

设置请求为 post 请求,在正文输入 php 代码<?php phpinfo();?>提交即可允许

image-20211026171144602

看到php代码被执行了

file://

访问本地文件,在本地包含漏洞里可以使用 file 协议,使用 file 协议可以读取本地文件

file:///etc/passwd

image-20211026171448143

读取相对路径的文件

image-20211026171810708

image-20211026171819347

php://

php:// 用于访问各个输入/输出流(I/O streams),经常使用的是 php://filter 和php://input

php://filter 用于读取源码;php://input 用于执行 php 代码。

协议 作用
php://input 可以访问请求的原始数据的只读流,在POST 请求中访问 POST 的 data 部分,在 enctype=”multipart/form-data” 的时候 php://input 是无效的。
php://output 写的数据流,允许以 print 和 echo 一样的方式写入到输出缓冲区。
php://fd (>=5.3.6)允许直接访问指定的文件描述符。例如 php://fd/3 引用了文件描述符3。
php://memory php://temp (>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory 总是把数据储存在内存中,而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。临时文件位置的决定和sys_get_temp_dir() 的方式一致。
php://filter (>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式(all-in-one)的文件函数非常有用,类 似 readfile()、file() 和file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。

php://filter 参数详解

参数 描述
resource=<要过滤的数据流> 必须项。它指定了你要筛选过滤的数据流。
read=<读链的过滤器> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
<; 两个链的过滤器> 任何没有以 read= 或 write= 作前缀的筛选器列表会视情况应用于读或写链。

可用的过滤器列表

字符串过滤器 作用
string.rot13 等同于 str_rot13(),rot13 变换
string.toupper 等同于 strtoupper(),转大写字母
string.tolower 等同于 strtolower(),转小写字母
string.strip_tags 等同于 strip_tags(),去除 html、PHP 语言标签
转换过滤器 作用
convert.base64-encode &convert.base64-decode 等同于 base64_encode()和base64_decode(),base64 编码解码
bzip2.compress & bzip2.decompress bzip2.decompress 同上,在本地文件系统中创建 bz2 兼容文件的方法。
加密过滤器 作用
mcrypt.* libmcrypt 对称加密算法
mdecrypt.* libmcrypt 对称解密算法

使用伪协议以base64编码过滤方式读取文件源码

image-20211026173918910

phar://、zip://、bzip2://、zlib://

用于读取压缩文件,zip:// 、 bzip2:// 、 zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等。

1.zip://[压缩文件绝对路径]%23[压缩文件内的子文件名]( #\编码为%23)

image-20211027131327365

这里不知道为啥没读出来

image-20211027131244680

但是直接?file=1.zip可以解析

image-20211027131336372

2、compress.bzip2://file.bz2

http://127.0.0.1/include.php?file=compress.bzip2://D:/soft/phpStudy/WWW/file.jpg

http://127.0.0.1/include.php?file=compress.bzip2://./file.jpg

3、compress.zlib://file.gz

http://127.0.0.1/include.php?file=compress.zlib://D:/soft/phpStudy/WWW/file.jpg

http://127.0.0.1/include.php?file=compress.zlib://./file.jpg

4、phar://

http://127.0.0.1/include.php?file=phar://E:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.txt

data://

1.data://text/plain

http://10.163.193.76/lfi.php?file=data://text/plain,%3C?php%20phpinfo();?%3E

image-20211027132944458

2.data://text/plain;base64

http://10.163.193.76/lfi.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

image-20211027133831321

文件包含常用路径

包含日志文件 getshell

/usr/local/apache2/logs/access_log

/logs/access_log

/etc/httpd/logs/access_log

/var/log/httpd/access_log

读取网站配置文件

dedecms 数据库配置文件 data/common.inc.php,

discuz 全局配置文件 config/config_global.php,

phpcms 配置文件 caches/configs/database.php

phpwind 配置文件 conf/database.php

wordpress 配置文件 wp-config.php

包含系统配置文件

windows

C:/boot.ini//查看系统版本

C:/Windows/System32/inetsrv/MetaBase.xml//IIS 配置文件

C:/Windows/repairsam//存储系统初次安装的密码

C:/Program Files/mysql/my.ini//Mysql 配置

C:/Program Files/mysql/data/mysql/user.MYD//Mysql root

C:/Windows/php.ini//php 配置信息

C:/Windows/my.ini//Mysql 配置信息

linux

/root/.ssh/authorized_keys

/root/.ssh/id_rsa

/root/.ssh/id_ras.keystore

/root/.ssh/known_hosts

/etc/passwd

/etc/shadow

/etc/my.cnf/etc/httpd/conf/httpd.conf

/root/.bash_history

/root/.mysql_history

/proc/self/fd/fd[0-9]*(文件标识符)

/proc/mounts

/porc/config.gz

远程文件包含

当远程文件开启时,可以包含远程文件到本地执行。当 allow_url_fopen=On,allow_url_include=ON 两个条件同时为 On 允许远程包含文件。

http://10.163.193.76/lfi.php?file=http://10.163.193.76/shell.txt

image-20211027134144483

image-20211027134224739

文件包含%00截断

文件包含截断攻击,在 php 版本小于 5.3.4 允许使用%00 截断,在使用 include等文件包含函数,可以截断文件名,截断会受 gpc 影响,如果 gpc 为 On 时,%00会被转以成\0 截断会失败。

当前我们是5.2.17 gpc=off

image-20211027143303680

可以看到是文件名拼接.php,但是文件名可控导致可以截断

%00截断

image-20211027143522798

超长截断

这个适用于于 win32 可以使用\.进行截断 和 . 进行截断

(php 版本小于 5.2.8 可以成功,linux 需要文件名长于 4096,windows 需要长于256)

利用操作系统对目录最大长度限制,在 window 下 256 字节,linux 下 4096 字节

点截断

image-20211027144439694

http://include.moonteam.com/file02.php?file=x.jpg................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

image-20211027144449845

\.截断

http://include.moonteam.com/file02.php?file=x.jpg\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.

image-20211027144532619

这里我试了下/.也能截断

远程文件包含截断

适用于远程截断的字符

符号 url编码
# %23
? %3f
00 %00

以上这个字符都可以截断

allow_url_fopen =On

allow_url_include=On

这里远程用%00截断,没解析出来

image-20211027145120175

剩余俩个可以

image-20211027145148513

防御

  1. 严格判断包含中的参数是否外部可控,因为文件包含漏洞利用成功与否的关键点就在于被包含的文件是否可被外部控制
  2. 路径限制:限制被包含的文件只能在某一文件内,一定要禁止目录跳转字符,如:”../“;
  3. 包含文件验证:验证被包含的文件是否是白名单中的一员;
  4. 尽 量 不 要 使 用 动 态 包 含 , 可 以 在 需 要 包 含 的 页 面 固 定 写 好 , 如 :include(‘head.php’)。
  5. 设置 allow_url_include 为 Off

文章作者: 晓莎K
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 晓莎K !
评论
  目录