浅谈PHP伪协议

0x01 介绍

这里引用官网的解释

PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数。 除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。

而对于php://,官网的解释如下

PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。

0x02 功能

php://主要支持以下几种类型协议

php://input

php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype=”multipart/form-data” 的时候 php://input 是无效的。

1
2
3
4
<?php
$ok=$_POST['ok'];
$ok2=$_POST['ok2'];
$test=readfile('php://input','r');//ok=1&ok2=2

php://output

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

1
2
3
<?php
echo 'ok';
$test=readfile('php://output','r');//ok

php://filter

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

一般来讲,resource是链接,但是通过read参数,可以读取文这里不需要开启allow_url_include参数也可以读取远程链接或文件。

1
2
<?php
$test=readfile('php://filter/read=convert.base64-encode/resource=3','r');

此时,能输出文件3的base64编码。

0x03 除了PHP://之外

data://

data://伪协议 >> 数据流封装器,和php://相似都是利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过你输入payload来实现目的;

用法:

1
?file=data://text/plain;base64,base64编码的payload

效果跟php://input是一样的,只不过不需要将数据放到post当中,直接在url输入即可。

phar://

phar://伪协议 >> 数据流包装器,自 PHP 5.3.0 起开始有效,正好契合上面两个伪协议的利用条件。说通俗点就是php解压缩包的一个函数,解压的压缩包与后缀无关。

用法:

1
?file=phar://压缩包/内部文件

只能解压phar以及zip后缀,rar不行。通常用于上传绕过。