目录
解题思路
-
先看题目
-
打开题目场景
-
我们看到用了file_get_contents()函数
-
这里我忘了这个函数是什么意思了,于是又去翻了翻文档
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 中新增的。 提示:该函数是二进制安全的。(意思是二进制数据(如图像)和字符数据都可以使用此函数写入。)
-
下面测试一下这个函数的用法
-
我们创建两个文件
-
main.php和test.txt
-
文件路径: test-environment/first
-
两个文件内容如下:
#main.php:
#test.txtThis is a String.Hello World;
-
我们访问main.php文件
-
文件里面的内容被当作一个字符串返回
-
至此我们明白了file_get_contents()函数的基本作用
-
言归正传,我们到这里就明白了,源码中的意思:需要file2返回的值为 "hello ctf"
-
而这个file2的值是我们可以控制的一个参数,因此我们只需要让 file2="hello ctf"即可
-
我们看到代码开头部分有个flag.php 文件,猜测大概率flag就在这里面
-
因此我们需要对该文件做一个读取,在这里我们需要用到 php伪协议
PHP伪协议
PHP有很多内置 URL风格的封装协议,这类协议与fopen()、 copy()、 file_exists()和filesize()的文件系统函数所提供的功能类似。
在文件包含漏洞这里,我们便可以利用这些伪协议对文件进行一些相关的操作从而达到我们的目的
常用的伪协议如下:
php://filter 读取文件源码
php://input 任意代码执行
data://text/plain 任意代码执行
zip:// 配合文件上传开启后门
php://filter
-
介绍:php://filter 协议可以对打开的数据流进行筛选和过滤,常用于读取文件源码
(allow_url_include和allow_url_fopen都不做要求)
-
注意:使用文件包含函数包含文件时,文件中的代码会被执行,如果想要读取文件源码,可以使用base64对文件内容进行编码,编码后的文 件内容不会被执行,而是展示在页面中,我们将页面中的内容使用base64解码,就可以获取文件的源码了
-
用法:
?page=php://filter/read=convert.base64-encode/resource={要读取的文件名}
-
各个参数详解:
名称 | 描述 |
---|---|
resource=<要过滤的数据流> | 这个参数是必须的,它指定了你要筛选过滤的数据流 |
read=<读链的筛选列表> | 可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
write=<写链的筛选列表> | 可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
任何没有以read=和write=做前缀的,都会视情况应用于读写链 |
-
测试:
-
测试地址:D:\phpstudy_pro\WWW\test-environment\second
-
我们创建一个文件:demo.php
-
写入以下内容:
-
#此文件用来测试
-
在创建一个文件:test.php
-
写入以下内容:
-
-
接下来我们启动phpstudy去访问test.php文件,并传入参数?file=demo.php
-
按照正常的逻辑demo.php的内容会被解析
-
-
-
-
我们发现事实却是是如此,但是如果我们不想demo.php被解析,而是想要获取它的源码怎么办,这个时候我们就需要用file://filter伪协议了
-
我们构造以下payload:
-
?file=php://filter/read=convert.base64-encode/resource=demo.php
-
得到目标文件的源码的base64编码,我们拿去解码看看是不是和源码一致
-
-
答案是正确,至此,我们对php://filter有了一定的了解
php://input
-
利用php中流的概念,将原本的include的文件流重定向到了用户可控制的输入流中命令执行
-
(allow_url_include:on,allow_url_fopen不做要求)
-
用法
-
?page=php://input
-
然后用post请求输入想要执行的代码
-
-
测试:
-
测试环境和前面一样,可以往上翻看看,但是这次我们只用test.php一个文件即可,不需要包含demo.php文件,因为我们输入什么就会执行什么
-
-
正常情况下会返回,但是我这里不知道为什么hackbar点击execute没有反应,于是我改变方法抓包试试
-
-
我直接把post请求体写在了这里,放包试试
-
-
成功!!!
-
后来找到hackbar为什么post请求提交不上去的原因了,因为参数必须写成键值对的形式才可以,如key=value
-
data://text/plain
-
协议格式: data:资源类型;编码,内容
-
php版本大于等于5.2,allow_url_include和allow_url_fopen都为on的状态
-
data://协议通过执行资源类型,使后面的内容当做文件内容来执行,从而造成任意代码执行
-
用法如下:
-
?url=data://text/plain,
-
和input有点像,但是又不太一样
-
zip://
-
ziip://协议用来读取压缩包中的文件,可以配合文件上传开启后门,获取webshell
将shell.txt压缩成zip,再将后缀名改为jpg上传至服务器,再通过zip伪协议访问压缩包里的文件,从而链接木马
-
用法:
-
?url=zip://shell.jpg
-
解题思路续
-
经过上面的知识补充,我们对伪协议有了进一步的认识
-
那么我们重归此题,我们此时便可以构造下面的payload
-
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input
-
burp抓包
-
-
将post请求体内容改为 hello ctf,放包
-
-
得到flag,base64解码即可
-
-
现在提供另一种方法
-
就是用data://协议流
-
payload:
-
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain;base64,aGVsbG8gY3Rm
-
-
data伪协议,base64编码传输,也可达成目的
-
至此完成,flag为
-
PD9waHAKZWNobyAiV1JPTkcgV0FZISI7Ci8vICRmbGFnID0gY3liZXJwZWFjZXs0Y2Y3N2ZhYWZiYjNmZDRkMjlkMDM2YmRiYjM5NzcwN30=
-
cyberpeace{4cf77faafbb3fd4d29d036bdbb397707}
-
-
来源地址:https://blog.csdn.net/henghengzhao_/article/details/127328881