1. 文件包含基础
和SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。
1.1. 文件包含简介
什么叫包含呢?以PHP为例,我们常常把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。
1.2. 文件包含的作用
文件包含可以更好的提高代码的重用性,引入文件包含函数,可以通过文件包含函数将文件包含进来,直接使用包含文件的代码。
1.3. 文件包含函数
require():找不到被包含的文件会产生致命错误,并停止脚本运行
include():找不到被包含的文件只会产生警告,脚本继续执行
require_once()与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once()与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
1.4. 文件包含案例
1.4.1. include 函数
1.4.2. Include _ once 函数
1.4.3. require 函数
因为2.php不存在,执行错误终止,不会执行下面的语句与include不同
Include会产生告警,但是会继续执行下面的语句。
1.4.4 require _ once 函数
只会进行一次包含
2. 文件包含漏洞
2.1 文件包含漏洞成因
程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
2.2. 文件包含漏洞的危害
读取文件
远程文件读取实现网站挂马
包含日志文件getshe11
利用php://input伪协议可以执行任意脚本代码(即时没有文件上传也能执行脚本代码)配合文件上传漏洞getshe11
2.3. 文件包含漏洞利用
2.3.1. 本地文件包含( LFI )
在name出传参就可以看到对应的本地文件
2.3.2. 远程文件包含
2.3.2.1. 远程文件包含的条件
allow_url_fopen = 0n #本地文件包含,如果此项设置为off就表示禁止本地文件包含
allow_url_include = 0n #远程文件包含,如果设置为off则表示禁止远程文件包含
2.4. 文件包含漏洞特点
2.4.1. 无视文件扩展名
在PHP中当使用上面的一些函数的时候,这个文件就会被当作PHP代码进行执行,PHP内核并不会在意包含的文件是什么类型的,也就是说当发过来的是.png的文件也会被当作PHP执行。
将文件后缀改为.txt .jpg仍然能够执行代码
2.4.2. 无条件解析 PHP 代码
文件包含洞在读取源码的时候,若遇到符合PHP语法规范的代码,将会无条件执行。
3. 文件包含漏洞综合利用
3.1.本地文件包含漏洞利用技巧
3.1.1配合文件上传使用
以dvwa靶场为例,先写一个图片马
上传到服务器
尝试用蚁剑连接
因为文件包含漏洞会默认将该文件当成php代码解析。
3.1.2包含Apache日志文件
日志会记录客户端请求及服务器响应的信息,访问http://www.xx.com/\<?php phpinfo();?>时,<?phpphpinfo();?>也会被记录在日志里,也可以插入到User-Agent,但是请求的信息有可能被url编码之后记录日志,这里可以通过burp来发送请求包来防止被编码,通过相对路径找到日志文件,利用包含漏洞执行。
有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。
在用户发起请求时,服务器会将请求写入access.log,当发生错误时将错误写入error.log,日志文件如下:
当我们正常访问一个网页时,如`http://127.0.0.1/phpinfo.php,access日志会进行记录,如下图所示:
如果我们访问一个不存在的资源,也一样会进行记录。
我们再次访问时候,进行抓包,修改后发送
此时再查看access日志,正确写入php代码:
再通过本地文件包含漏洞访问,即可执行
3.1.3包含session文件
可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。
利用条件:
找到Session内的可控变量
Session文件可读写,并且知道存储路径
php的session文件的保存路径可以在phpinfo的session.save_path看到。
3.1.4包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
4.PHP伪协议
4.1file://协议
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow url fopen与allow url include的影响
?file=php://filter/convert.base64-encode/resource=filter flag.phpresource=<要过滤的数据流>这个参数是必须的。它指定了你要筛选过滤的数据流。read=<读链的筛选列表>该参数可选。可以设定一个或多个过滤器名称,以管道符(1)分隔。write=<写链的筛选列表>该参数可选。可以设定一个或多个过滤器名称,以管道符(1)分隔。任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。
使用:
file:// [文件的绝对路径和文件名]
4.2php://协议
php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input
php://filter用于读取源码。
php://input用于执行php代码。
php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
利用条件:
allow_url_fopen :off/on
allow_url_include:off/on
4.3ZIP://协议
zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
zip://中只能传入绝对路径。
要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型还有zlib://和bzip2://
4.4data://协议
data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
利用data:// 伪协议可以直接达到执行php代码的效果,例如执行phpinfo()函数:
利用条件:
allow_url_fopen :on
allow_url_include:on
5.常见敏感路径
5.1.windows系统
c:\boot.ini 查看系统版本
c:\xxx\php.iniphp 配置信息
c:\xxx\my.inimysq1 配置信息
c:\xxx\httpd.conf apache配置信息
5.2.linux系统
/etc/passwd/ linux系统账号信息
/etc/httpd/conf/httpd.conf apache配置信息
/etc/my.cnfmysq1 配置文件
/usr/etc/php.ini php 配置信息
6.绕WAF
6.1. 空字符绕过
6.1.1. 原理
空字符绕过是存在PHP小于5.3.4版本的一个漏洞,这个漏洞就是用于接收来自路径中的空字符,这样在部分需求下攻击者可以利用将此字符放置安全文件后面来绕过访问限制。
前提条件就是需要PHP版本小于5.3.4,并且关闭PHP魔术引导、
6.1.2. PHP魔术引号介绍
当sql句中含有单引号,双引号,反斜杠和NUL时,这时候如果不对这些符号进行转义,写入数据库时就会出错,而魔术引号magic_quotes_gpc()就是对这些符号进行转义以便能把数据正确写入数据库。不过该参数在php.ini文件中修改。
PHP魔术引号特性已自 PHP5,3.0起废弃并将自PHP5.4.0起移除。也就是说在本实验环境的PHP版本中仍
是存在的。
6.1.3其他绕过
00截断,但是PHP版本必须小于5.3长路径:利用系统特性绕过waf。windowx系统中,当点号数量大于256个字符时,256个字符以后的内容就会被丢弃因此可利用此特性进行绕过;Liunx系统中点号大于4096个。
路径双写绕过:..././..././
后缀处添加斜杠点号进行绕过:ino.php/.
?绕过:phpinfo.php?
#绕过:直接使用#并不能绕过,需要输入编码23才能够生效。phpinfo.php23
7.防御
7.1.过滤
对传入的文件名进行过滤
对敏感路径的关键字进行过滤
7.2.php.ini配置文件参数设置
allow url fopen=off #表示本地文件包含
allow url include=off #表示远程文件包含
开启魔术引号magic quotes qpc=on
7.3.对包含的文件范围做出限制
后台定义被包含文件的自名单
配置open basedir=指定目录,限制访问区域
修改apache日志文件的存放地址