文件包含
什么是文件包含
和sql注入攻击方式类似,文件包含本质上就是输入一段用户能够控制的脚本或者代码,并让服务器执行。
许多脚本支持使用包含文件(include file),这种功能允许开发者把可使用的代码或脚本插入到单个文件中,然后包含文件中的代码被解释并执行,就好像直接插入到包含指令的位置一样。
以PHP为例,常用的文件包含函数有以下四种:include()
,require()
,include_once()
,require_once()
区别如下:
require(),找不到被包含的文件时会产生致命错误,并停止脚本运行。
include(),找不到被包含的文件时只会产生警告,脚本将继续运行。
include_once()与include()类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。
require_once()与require()类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。
本地文件包含
- include.php
<?php
if(isset($_GET['file'])){
$a = $_GET['file'];
include($a.'.php');
}else{
highlight_file(__FILE__);
}
- payload:url/?file=flag
可以嵌套包含文件,例:url/?file=flag/../flag(此payload等价于上面的payload)

- %00截断
条件
magic_quotes_gpc
= Offphp < 5.3.4
- 路径长度截断
条件
php < 5.2.8
Windows下目录最大长度为256字节,超出的部分会被丢弃;
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
PHP伪协议
- 原理:事实上是支持的协议与封装协议
php://
作用:访问各个输入/输出流
条件:
allow_url_fopen:On/Off
allow_url_include:仅
php://input,php://stdin,php://memory,php://temp
需要on
php://input
- 条件:
allow_url_fopen: On/Off
allow_url_include: On
PHP < 5.3.0
用法:用于执行php代码
可以访问请求的原始数据的只读流,在POST请求中访问POST的
data
部分,在enctype="multipart/form-data"
的时候php://input
是无效的。演示:
<?php #test.php $a = $_GET['a']; include($a);

php://filter
条件:
allow_url_fopen: Off/On
allow_url_include: Off/On
用法:主要用于读取文件源码或者写入源码
名称 描述 备注 resource=<要过滤的数据流> 指定了你要筛选过滤的数据流 必选 read=<读链的筛选列表> 可以设定一个或多个过滤器名称,以管道符( )分隔 <;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链 可选 read参数可为
string.strip_tags: 将数据流中的所有html标签清除
string.rot13:将数据流中的内容rot13变换
string.toupper: 将数据流中的内容转换为大写
string.tolower: 将数据流中的内容转换为小写
convert.base64-encode: 将数据流中的内容转换为base64编码
convert.base64-decode: 将数据流中的内容转换为base64解码
演示:
<?php #test.php $a = $_GET['a']; include($a);
data://
条件:
allow_url_fopen: On
allow_url_include: On
PHP >= 5.2.0
用法:数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。
data://text/plain;base64,
your source
(或者 data:text/plain;base64,your source
)data://text/plain,
your source
or data:text/plain,your source
演示:
<?php #test.php #<?php phpinfo(); ===base64===> PD9waHAgcGhwaW5mbygpOw== $a = $_GET['a']; include($a);
file://
条件:
allow_url_fopen: Off/On
allow_url_include: Off/On
用法:用于访问本地文件系统
file://
文件的绝对路径和文件名
a=file://D:phpstudy_pro/www/phpinfo.php文件的相对路径和文件名 a=./test.php
http://网络路径和文件名
a=http://127.0.0.1/phpinfo.php演示:
<?php #test.php $a = $_GET['a']; include($a);
日志文件包含
- 原理:对网站进行访问时,日志文件会记录相关的信息(UA头中的信息)
- 要求:知道日志文件的路径并且能够包含
- 步骤:
- 访问网站,在UA头里写马
- 通过post检查代码是否执行
- 成功后蚁剑连接反弹shell
Session文件包含
Session:
Session就是保存在服务器的文本文件。 默认情况下,PHP.ini 中设置的SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,而 SESSION 文件保存的目录由 session.save_path 指定,文件名以 sess_为前缀,后跟 SESSION ID,文件中的数据即是序列化之后的 SESSION 数据
原理:由于Session保存的文件名没有经过严格的过滤或者限制,从而可以被用户控制,执行任意代码
要求:
PHP >= 5.4.0
必须先启动,在PHP中先调用
session_start(void)
,注意,此函数前不能有任何输出如果在PHP.ini中session.auto_start已经开启则不用,但默认情况下是关闭的
配置
- session.auto_start:在php接收请求的时候自动初始化Session,不需要再执行
session_start()
,默认情况下关闭 - session.save_path:Session存储的位置,我这里就是
D:\phpstudy_pro\Extensions\tmp\tmp
- session.serialize_handler
- php:一直都在(默认方式) 它是用 |分割
- php_serialize :php5.5之后启用
它是用serialize反序列化格式分割
- session.upload_progress:php5.4添加的。最初是PHP为上传进度条设计的一个功能,在上传文件较大的情况下,PHP将进行流式上传,并将进度信息放在Session中(包含用户可控的值),即使此时用户没有初始化Session,PHP也会自动初始化Session。
而且,默认情况下session.upload_progress.enabled是为On的,也就是说这个特性默认开启- session.upload_progress.enabled:默认开启,表示
upload_progress
功能开始,php能在每一个文件上传时监测上传进度,这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态 - session.upload_progress.cleanup:默认开启这个选项,表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项非常重要。
- session.upload_progress.prefix与session.upload_progress.name:当一个上传在处理中,同时POST一个与INI中设置的
session.upload_progress.name
变量同名(PHP_SESSION_UPLOAD_PROGRESS
)时(这部分数据用户可控),上传进度可以在SESSION中获得。当PHP检测到这种POST请求时,它会在SESSION中添加一组数据(系统自动初始化session),
索引是session.upload_progress.prefix
与session.upload_progress.name
连接在一起的值 - session.upload_progress.freq
与session.upload_progress.min_freq:选项控制了上传进度信息应该多久被重新计算一次。
通过合理设置这两个选项的值,这个功能的开销几乎可以忽略不计
- session.upload_progress.enabled:默认开启,表示
- session.use_strict_mode:默认为0,用户可以自己定义
Session ID
。比如,我们在Cookie里设置PHPSESSID=flag
,PHP将会在服务器上创建一个文件:sess_flag
- session.auto_start:在php接收请求的时候自动初始化Session,不需要再执行
演示
#test.php <?php $test = $_GET['test']; include($test);
#session.php <?php session_start(); $file = $_POST['file']; $_SESSION['file'] = $file;
恶意写session文件马
包含session文件,成功执行命令