文件包含与php伪协议都是CTF的常客了,今天就来学习学习
常见文件包含函数
- include
| 1 | include("conn.php"); | 
- require
| 1 | require("conn.php"); | 
- 区别
| 函数 | 区别 | 
|---|---|
| include/require | include发生错误会跑出waring然后继续执行后面的内容,而require发生错误会直接停止程序 | 
常见的还有include_once、require_once、highlight_file 、show_source 、readfile 、file_get_contents 、fopen 、file,这里就不做赘述
利用场景
若include其中的变量能够被用户操控,则可能导致文件包含漏洞,导致任意代码执行或者任意文件读取
| 1 | 
 | 
执行任意命令
- 若该web服务存在文件上传的地方,我们将我们需要执行的恶意代码嵌入图片文件上传到服务器中,将include中的变量值改成我们存在恶意代码的图片路径这样在文件包含的时候就能执行我们想要执行的恶意代码。 
- 假设我们已将恶意图片上传到网站目录,例如test.jpg在网站根目录,但其真实内容是一段php代码 

- 将图片地址传入,恶意代码被执行

任意文件读取
很多网站由于业务需求,往往需要提供文件(附件)下载的功能块,但是如果对下载的文件没有做限制,直接通过绝对路径对其文件进行下载,那么,恶意用户就可以利用这种方式下载服务器的敏感文件,对服务器进行进一步的威胁和攻击。
- 在这里讨论使用php伪协议进行文件读取 
- include-1 

- exp
| 1 | ?file=php://filter/read=convert.base64- | 

解码即可得到flag
php伪协议
在上面的任意文件读取处用到了我们今天的另一个主角——php伪协议
环境概要:
PHP.ini:
allow_url_fopen :on  默认开启  该选项为on便是激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象文件等。
allow_url_include:off  默认关闭,该选项为on便是允许 包含URL 对象文件等。
协议总结
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()函数所决定的。
- 用法
/path/to/file.ext
relative/path/to/file.ext
fileInCwd.ext
C:/path/to/winfile.ext
C:\path\to\winfile.ext
\smbserver\share\path\to\winfile.ext
file:///path/to/file.ext
- 示例
- file://[文件的绝对路径和文件名] - http://127.0.0.1/include.php?file=file://E:\phpStudy\PHPTutorial\WWW\phpinfo.txt 
- [文件的相对路径和文件名] 
- [http://网络路径和文件名] - http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt 
php://协议
- 条件 - 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://input | 可以访问请求的原始数据的只读流,在POST请求中访问POST的 data部分,在enctype="multipart/form-data"的时候php://input 是无效的。 | 
| php://output | 只写的数据流,允许以 print 和 echo 一样的方式写入到输出缓冲区。 | 
| php://fd | (>=5.3.6)允许直接访问指定的文件描述符。例如 php://fd/3引用了文件描述符 3。 | 
| php://memory php://temp | (>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory总是把数据储存在内存中,而php://temp会在内存量达到预定义的限制后(默认是2MB)存入临时文件中。临时文件位置的决定和sys_get_temp_dir()的方式一致。 | 
| php://filter | (>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式 (all-in-one)的文件函数非常有用,类似readfile()、file()和file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。 | 
php://filter参数详解(重点)
该协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递。具体参考如下:
| php://filter 参数 | 描述 | |
|---|---|---|
| resource=<要过滤的数据流> | 必须项。它指定了你要筛选过滤的数据流。 | |
| read=<读链的过滤器> | 可选项。可以设定一个或多个过滤器名称,以管道符(*\ | *)分隔。 | 
| write=<写链的过滤器> | 可选项。可以设定一个或多个过滤器名称,以管道符(\ | )分隔。 | 
| <; 两个链的过滤器> | 任何没有以 read= 或 write= 作前缀的筛选器列表会视情况应用于读或写链。 | 
可用的过滤器列表(4类)
此处列举主要的过滤器类型,详细内容请参考:https://www.php.net/manual/zh/filters.php
| 字符串过滤器 | 作用 | 
|---|---|
| string.rot13 | 等同于 str_rot13(),rot13变换 | 
| string.toupper | 等同于 strtoupper(),转大写字母 | 
| string.tolower | 等同于 strtolower(),转小写字母 | 
| string.strip_tags | 等同于 strip_tags(),去除html、PHP语言标签 | 
| 转换过滤器 | 作用 | 
|---|---|
| convert.base64-encode & convert.base64-decode | 等同于 base64_encode()和base64_decode(),base64编码解码 | 
| convert.quoted-printable-encode & convert.quoted-printable-decode | quoted-printable 字符串与 8-bit 字符串编码解码 | 
| 压缩过滤器 | 作用 | 
|---|---|
| zlib.deflate & zlib.inflate | 在本地文件系统中创建 gzip 兼容文件的方法,但不产生命令行工具如 gzip的头和尾信息。只是压缩和解压数据流中的有效载荷部分。 | 
| bzip2.compress & bzip2.decompress | 同上,在本地文件系统中创建 bz2 兼容文件的方法。 | 
| 加密过滤器 | 作用 | 
|---|---|
| mcrypt.* | libmcrypt 对称加密算法 | 
| mdecrypt.* | libmcrypt 对称解密算法 | 
- 示例
- 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部分]
例
http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
‘); ?>
zip:// & bzip:// & zlib://协议
- 条件 - allow_url_fopen:off/on
- allow_url_include:off/on
 
- 作用 
zip:// & bzip2:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等。
- 示例
- zip://[压缩文件绝对路径]%23[压缩文件内的子文件名] - %23=># - http://127.0.0.1/include.php?file=zip://E:\phpStudy\PHPTutorial\WWW\phpinfo.jpg%23phpinfo.txt - 压缩 phpinfo.txt 为 phpinfo.zip ,压缩包重命名为 phpinfo.jpg ,并上传 
- compress.bzip2://file.bz2 - http://127.0.0.1/include.php?file=compress.bzip2://E:\phpStudy\PHPTutorial\WWW\phpinfo.bz2 - 压缩文件phpinfo.txt为phpinfo.bz2并上传,支持任意后缀名 
- compress.zlib://file.gz - 同上 
data://协议
- 条件 - allow_url_fopen:on
- allow_url_include:on
 
- 作用 - 自 - PHP>=5.2.0起,可以使用- data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。
- 用法 - data://text/plain 例:?file=data://text/plain, - data://text/plain;base64 例:?file=data://plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b 
http:// & https://协议
- 条件 - allow_url_fopen:on
- allow_url_include:on
 
- 作用:常规url形式,允许通过 - HTTP 1.0的GET方法
- 用法 - 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 
phar://协议
phar://协议与zip://协议类似,同样可以访问zip格式压缩包文件内容
phar://协议还可以用到php反序列化漏洞中,这里不做介绍,会在后续学习中深入了解
题目
include-1
一一测试后发现只有php://协议可以用上,尝试直接读取flag.php

解码即可得到flag
include-2
测试得data://可以使用

data://协议用法是data://text/plain,[php语句]
所以我们可以借此查看网站根目录并找到想要的信息

猜测flag就在flag.php中

flag就在网站源码中

