8.3 php://输入输出流
提到流,大家会想到水流或者数据流,PHP提供了php://的协议允许访问PHP的输入输出流、标准输入输出和错误描述符,内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。主要提供如下访问方式来使用这些封装器:
php : //stdin
php : //stdout
php : //stderr
php : //input
php : //output
php : //fd
php : //memory
php : //temp
php : //filter
使用最多的是php://input、php://output以及php://filter,其中php://input是可以访问请求的原始数据的只读流。即可以直接读取到POST上没有经过解析的原始数据,但是php://input不能在获取“multipart/form-data”方式提交的数据。我们做一个测试,测试代码如下:
< ? php
echo file_get_contents ( "php : //input" );
当我们用POST提交a=111111时,a=111111被直接打印出来,如图8-4所示。
图 8-4
而php://output是一个只写的数据流,跟php://input相反,php://input是读取POST提交上来的数据,而php://output则是将流数据输出。
php://filter是一个文件操作的协议,可以对磁盘中的文件进行读写操作,效果类似于readfile()、file()和file_get_contents(),它有多个参数可以进行相应的操作,说明如表8-1所示。
表 8-1
我们来测试使用php://filter写文件,测试代码如下:
< ? php
file_put_contents ( "php : //filter/write=string.rot13/resource=example.txt" , "Hello World" );? >
当我们执行代码的时候,会像脚本同目录下写入“example.txt”文件,内容为rot13编码过的“Hello World”,而php://filter还可以用来读文件,如果有远程文件保护漏洞,类似如下的代码:
< ? php
include ( $_GET['f'] );? >
正常情况下如果我们直接传入一个文件名,则是会被include函数包含并执行,如果我们想读取Web目录下的PHP文件,则可以通过请求:
/1.php ? f=php : //filter/convert.base64-encode/resource=1.php
来将文件进行Base64编码后输出,输入结果如图8-5所示。
图 8-5