文件包含简介

服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,这会为开发者节省大量的时间

文件包含函数

require()

require_once()

include()

include_once()

includerequire区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行,而include_once()require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题

漏洞产生原因

文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码
示例代码

<?php
    $filename  = $_GET['filename'];
    include($filename);
?>

文件包含漏洞

无限制本地文件包含漏洞

测试代码:

<?php
    $filename  = $_GET['filename'];
    include($filename);
?>

常见敏感文件目录:
Windows系统

c:\boot.ini // 查看系统版本

c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件

c:\windows\repair\sam // 存储Windows系统初次安装的密码

c:\ProgramFiles\mysql\my.ini // MySQL配置

c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码

c:\windows\php.ini // php 配置信息

Linux/Unix系统

/etc/passwd // 账户信息

/etc/shadow // 账户密码文件

/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件

/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置

/usr/local/app/php5/lib/php.ini // PHP相关配置

/etc/httpd/conf/httpd.conf // Apache配置文件

/etc/my.conf // mysql 配置文件

测试结果:
1.png

包含session文件

利用条件:
知道session文件路径,在phpinfo()里面可以看到
默认情况下,session.use_strict_mode值是0。此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=ghtwf01
2.png
示例代码:

<?php

session_start();

$ctfs=$_GET['ctfs'];

$_SESSION["username"]=$ctfs;

?>

3.png
查看一下生成的session文件,phpinfo成功写入
4.png
然后利用文件包含包含一下,当然也可以写入一句话getshell
5.png
以phpMyAdmin CVE-2018-12613为例包含session文件
首先进入执行SQL语言地方,执行如下操作

select '<?php phpinfo();?>'

打开F12查看到session名,完整的session文件就是sess_session
23.png
phpstudy里面默认session存储位置是phpstudytmp/tmp,于是包含该session文件
24.png

包含图片马

一般用于文件上传,上传图片马后如果存在文件包含漏洞,那么就可以执行图片马里面的php代码

包含日志文件

(1)包含apache日志
进入一个网页,比如phpmyadminburpsuite抓包,在URL栏添加一句话木马,这样它就会报错,并把报错语句(一句话木马)写入apache日志
6.png
日志里面已经写入了phpinfo,然后包含日志
7.png
但是我这个环境的日志不允许包含,所以没法执行代码,但是实战中就有可能权限允许包含
(2)包含ftp日志
ftp连接时,用户名输入一句话木马
日志位置在/var/log/vsftpd.log
(3)包含ssh日志

ssh -p 22 "<?php phpinfo(); ?>"@目标ip地址

日志位置在/var/log/auth.log
(4)包含临时文件

无限制远程文件包含

远程文件包含需要打开远程文件包含许可,即allow_url_include = On
13.png

有限制文件包含绕过

(1)%00截断
条件:magic_quotes_gpc=off

 `php版本<5.3.4`

测试代码

<?php
    $filename  = $_GET['filename'];
    include($filename.".php");
?>

如果要包含1.txt,它在后面自动加上.php,所以包含的文件就是1.txt.php,没有这个文件,所以采用%00截断
8.png
(2)路径长度截断
Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃
测试代码

<?php
    $filename  = $_GET['filename'];
    include($filename.".php");
?>

exp:

.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

所以效果如下
9.png
(3)问号截断
测试代码

<?php
    $filename  = $_GET['filename'];
    include($filename.".php");
?>

问号截断漏洞是针对远程文件包含的情况,在PHP的配置文件中,打开远程文件包含许可,即allow_url_include = On
10.png
(4)#号绕过
测试代码

<?php
    $filename  = $_GET['filename'];
    include($filename.".php");
?>

一样是需要打开远程文件包含
11.png
(5)空格绕过
测试代码

<?php
    $filename  = $_GET['filename'];
    include($filename.".php");
?>

一样是需要打开远程文件包含
12.png

php伪协议

(1)php://filter
因为直接打开php文件不会显示里面的代码,所以我们可以以base64编码的方式读取指定文件的源码
php://filter/convert.base64-encode/resource=php文件名
14.png
base64解码即为源代码
15.png
(2)data://

利用data:// 伪协议可以直接达到执行php代码的效果
16.png
如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入(才发现php代码里面加了分号的base64无法执行)
17.png
(3)zip:// bzip2:// zlib://
zip://
执行压缩文件,如果网站允许我们上传压缩文件,我们也可以将php文件压缩后进行上传,再通过zip://协议执行,以dvwa平台为例
18.png
然后包含

payload:http://127.0.0.1/zx/test.php?filename=zip://D:/Program%20Files/PHPTutorial/WWW/DVWA/hackable/uploads/phpinfo.zip%23phpinfo.php

bzip2://
压缩文件至xxx.bz2并上传,访问的使用使用compress.bzip2://
zlib://
压缩文件至xxx.gz并上传,访问的时候使用compress.zlib://
19.png
(4)php://input
我们可以利用这种方法直接写入文件,比较特殊的一点,enctype=multipart/form-data 的时候php://input是无效的
20.png
发现shell.php已经写入到本地
21.png
(5)phar://
这个伪协议和zip://一样可以读取压缩包里面的内容,以刚才在dvwa上传的zip文件为例
22.png
(6)file://
这个伪协议是用来读文件内容的,需要加文件的绝对路径
25.png

上述伪协议适用条件

php://

allow_url_fopen:off/on
仅php://input需要on(还有一些也需要on为了方便记忆就没写上去了)

data://

allow_url_fopen:on
allow_url_include :on

file://

allow_url_fopen:off/on
allow_url_include :off/on

zip:// bzip2:// zlib://

allow_url_fopen:off/on
allow_url_include :off/on

phar://

allow_url_fopen:off/on
allow_url_include :off/on

参考链接

https://blog.csdn.net/Monsterlz123/article/details/93964916
https://www.freebuf.com/articles/web/182280.html
https://www.jianshu.com/p/3dc97deec491