文件包含原理
开发人员将相同函数写入单独的文件中,需要使用某个函数直接调用此文件,无需再次编写,这种文件调用过程称为文件包含
文件包含漏洞
开发人员为了使代码更灵活,会将被包含的文件设置为变量,用来动态调用,从而导致客户端可以恶意调用一个恶意文件,造成文件包含漏洞
相关函数
- include: 包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个php文件继续执行
- include_once: 这个函数跟和include语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含
- require: 跟include唯一不同的是,当产生错误时候,整个php文件停止运行
- require_once: require_once语句和require 语句完全相同,唯一区别是PHP会检查该文件是否已经被包含过,如果是则不会再次包含
注:这四个函数不管执行哪个后缀的文件,都将他当作php文件执行
分类
注:
1、本实验127.0.0.1为windows系统,192.168.100.134为linux系统
2、注意每个实验中php的适用版本与php.ini等相关配置
一、本地文件夹包含
1、linux目录遍历
(1)test.php测试代码:
(2)进行目录遍历
2、windows目录遍历
(1)测试代码:
<?php
$filename = $_GET['file'];
include($filename);
?>
(2)进行目录遍历
3、session文件包含漏洞
(1)利用条件:
- 知道session的存储位置
- 有可控的值传入session中
- 存在本地文件包含漏洞
(2)原理
① 通过phpinfo可获取到session的存储位置或已知session的存储位置
例:
② session中的内容可控,可以传入恶意代码
例:一个可传恶意代码到session中的php代码
<?php
session_start();
$ctfs=$_GET['sess'];
$_SESSION["username"]=$ctfs;
?>
此时php会将获取到的GET型sess变量的值存入到session中
当访问http://www.ctfs-wiki/session.php?sess=hello后,会在/var/lib/php/session目录下存储session的值
如下图:
注:②中的第一幅图中的PHPSESSID值可以关注下,因为默认传入session目录中的文件是sess_后面加上PHPSESSID
③ 因此我们可以传入恶意代码,然后配合文件包含漏洞getshell
例:
传入恶意代码
配合文件包含getshell
4、截断
(1)%00截断
① 条件:magic_quotes_gpc = Off php版本<5.3.4
② 测试代码:
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
③ 对比图
(2)路径长度截断
① 条件:windows OS,点号需要长于256;linux OS 长于4096
Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃
② 测试代码
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
③
前提:这里以包含WWW目录下的文件为主,非WWW目录下我测试时出现了失败
例1:./绕过对比图
注:./中可掺杂/,但是不能全部用/
例2:.绕过对比图
二、远程文件包含
1、无绕过远程文件包含
(1)条件
allow_url_fopen = On(是否允许打开远程文件) allow_url_include = On(是否允许include/require远程文件)
(2)测试代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
例:
2、有绕过文件包含
(1)测试代码
<?php include($_GET['filename'] . ".html"); ?>
(2)对比图
① 没绕过的
② ?绕过
③ #绕过
④ 空格绕过
三、php伪协议
1、php://
php:// — 访问各个输入/输出流(I/O streams)
说明
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符,内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
2、php://filter
元封装器,设计用于"数据流打开”时的"筛选过滤”应用,对本地磁盘文件进行读写
只是读取,需要开启 allow_url_fopen,不需要开启 allow_url_include
(1)输出进行base64加密后的信息
?file=php://filter/convert.base64-encode/resource=xx.php
等于
?file=php://filter/read=convert.base64-encode/resource=xx.php
(2)test.php源码
<?php
$filename = $_GET['filename'];
include($filename);
?>
(3)利用实例
3、php://input(读取POST数据)
(1)前言:
可以访问请求的原始数据的只读流。即可以直接读取到POST上没有经过解析的原始数据。 enctype=”multipart/form-data” 的时候 php://input 是无效的
条件:开启 allow_url_fopen 和 allow_url_include(PHP < 5.3.0)
(2)test.php测试代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
注:查看当前运行的是哪个php.ini
- 打印出phpinfo(),找到Loaded Configuration File那一行
- php -i |grep php.ini(php -i其实就是输出phpinfo)
- php -r “phpinfo();” |grep php.ini
(3)利用实例
① 读取POST提交的数据
② 执行php或系统命令
③ 通过php://input写入一句话
4、file://伪协议(读取文件内容)
5、data://伪协议(读取文件)
(1)前言:这个和php://input类似,都可以执行php指令
(2)格式:
data://text/plain;base64,base64加密的代码
(3)test.php测试代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
(4)例:
5、phar://伪协议
(1)前言:这个参数是就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压
注意: PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用
(2)格式:
?file=phar://压缩包名/内部文件名
例:phar://x.zip/x.php
(3)test.php测试代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
(4)例
写一个一句话木马文件,压缩为.zip后缀的压缩包文件,然后利用php://char进行利用
6、zip://伪协议
(1)前言
zip伪协议和phar协议类似,但是用法不一样
注:条件: PHP > =5.3.0,注意在windows下测试要5.3.0<PHP<5.4 才可以 #在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符
(2)格式
?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名]
例: zip://xxx.png#shell.php
(3)test.php测试代码
<?php
$filename = $_GET['filename'];
include($filename);
?>