今天刷到一道题 , 需要用到PHP伪协议读取源码 , 刚好对这种利用方式不太熟练 , 这里做个总结
PHP中支持多种伪协议
伪协议 | 功能 |
---|---|
file:// | 访问本地文件系统 |
http(s):// | 访问 HTTP(S) 网址 |
ftp(s):// | 访问FTP(S) URLS |
php:// | 访问各个输入输出流(IO Stream) |
zlib:// | 压缩流 |
data:// | 数据(RFC 2397) |
glob:// | 查找匹配的文件路径模式 |
phar:// | PHP归档 |
ssh2:// | Secure Shell 2 |
rar:// | RAR |
ogg:// | 音频流 |
expect:// | 处理交互式的流 |
当然在一般CTF中用不着这么多的协议 , 下面就说一下常用的
php://
php://
用于访问各个输入 / 输出流 ( IO Stream ) , 在CTF中常用的是php://input
和php://filter
php://input
是用于访问请求的原始数据的只读流 . 简单的说 , 在POST请求的情况下 , 通过 php://input 可以读取到post的数据 , 或者执行php代码 !
需要注意的是 , 当
enctype=multipart/form-data
时 ,php://input
是无效的 !1 . 读取POST的原始数据 , 来看个非常经典的demo
源代码
构造请求 ,
php://input
可以读取Post请求的内容 , 而源码中是以Get请求获取数据 , 所以可以把php://input
的值作为Get请求的参数 . 这里用 bp 的 repeater 模块来复现2 . 执行php代码
上面这个代码是非常危险的 , 但是除了存在 LFI , RFI 之外 , 还可以直接通过
php://input
进行代码执行代码执行的利用条件是
allow_url_include = On
, 虽然当这个选项开启时已经可以 RFI 了 , 但是这依旧是一种思路 !
php://filter
另外一个重点就是
php://filter
, 该伪协议常常被用于任意文件读取
php://filter
是一个元封装器 , 设计用于数据流打开时的筛选过滤应用 . 这对于一体式( all-in-one )的文件函数非常有用 . 类似于readfile()
,file()
和file_get_contents()
, 在数据流内容读取之前没有机会应用其它过滤器
php://filter
在allow_url_include
和allow_url_fopen
都为Off时也可以使用 !php://filter 目标使用以下的参数作为路径的一部分 , 复合过滤链能够在一个路径上指定 , 下面是参数列表
resource=<要过滤的数据流> : 这个参数是必须的 , 指定要筛选过滤的数据流
read=<读链的筛选列表> : 设定一个或多个过滤器名称 , 以管道符 ( | ) 分隔
write=<写链的筛选列表> : 设定一个或多个过滤器名称 , 以管道符 ( | )
<两个链的筛选列表> : 任何没有以 read= 或者 write= 作为前缀的筛选器列表会视情况应用于读链或者写链
最常用的Payload
php://filter/read=convert.base64-encode/resource=xxx.php
读取源代码并进行base64编码输出 , 不然会直接当做php代码执行就看不到源代码内容了.
举个例子 ,
a.php
读取同目录下b.php
的源码可以看到在原输出下面显示了一段base64编码 , 可以通过很多解码器来解码( 比如bp自带Decoder模块 )
解码后的代码看起来很简单 , 但是这只是最简单的情况 , 在测试的时候如果能获取到后端源码 , 在代码审计上会容易很多
Zip:// && Bzip2:// && Zlib
上面三个都属于压缩流 , 可以访问压缩文件中的子文件 , 在利用时有两个非常好的因素
1 . 三个协议都可以在
allow_url_include
和allow_url_fopen
为 Off 的情况下正常使用2 . 使用它们的时候不需要指定后缀名 , 意味着可以作为任意文件进行上传
Zip:// 协议
利用方法
zip://[ 压缩文件的绝对路径 ] # [ 压缩文件内的子文件名 ]
在使用的时候有几个注意点
1 . 执行的phpcode写入文件并命名为
phpcode.txt
, 然后将phpcode.txt
通过zip压缩为file.zip
2 . 目标站点支持zip上传 , 那么直接将
file.zip
上传 , 若不能则可以将file.zip
重命名为file.jpg
,file.png
等等 , 按照需求来3 . #
后的内容在URL中会被忽略 . 所以在使用Get请求时必须要将
#编码为
%234 . 必须使用压缩文件的绝对路径 , 相对路径是不可以的 !
看个demo ( php7+ 默认是没有装
php7.x-zip
这个模块的 , 自行安装 )在解压时可以把压缩包命名为任何后缀 , 根据题目需求变化
Bzip2:// 协议
利用方法
compress.bzip2:// [ 文件路径 ]
这里文件路径可以使用文件绝对路径 , 也可以使用相对路径
看个demo ( 同样需要开启 php7.x-bz2 这个模块 )
Zlib:// 协议
利用方法
compress.zlib:// [ 文件路径 ]
同样这里的文件路径既可以是绝对路径 , 也可以是相对路径 . 其实
zlib://
与bzip2://
用法相同 , 只需要把.bz2
格式的压缩文件 改成.gz
格式即可看个demo
总结而言 , 上面这三种压缩流在CTF中还是比较常用的 , 因为可以在 双OFF 和 任意文件后缀 的情况下执行php代码 , 所以利用场合还是很多的 !
data:// 协议
data:// 协议必须在
allow_url_include
和allow_url_fopen
都为On
的时候才能正常使用利用方式
data://text/plain;base64,xxxxxx
看个demo
<?php phpinfo(); ?>
转换成base64编码PD9waHAgcGhwaW5mbygpOyA/Pg==
, 然后通过data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
执行php代码因为在双
On
的条件下已经有太多地方可以利用了 , 所以 data:// 并不是很常用 . 但是你可以用它来做很多事
总结而言 , PHP伪协议在CTF中用到的还是蛮多的 , 有个大佬总结了常用的伪协议及其Payload , 放在下面 . 至于一些复杂的问题我还没遇到 , 就写到这了 !
链接 : https://www.jianshu.com/p/d0de87ac4ae7