【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei

代码审计题目,总共有3关

 

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


"; // 第二关:好像正则拦截没啥卵用,也不需要访问flag的文件 if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ // 第三关:反序列化激活变量password include($file); //useless.php // 可利用伪协议 $password = unserialize($password); echo $password; } } else{ highlight_file(__FILE__); } ?>

第一关:伪造文件输入流

其实我对伪协议没什么了解,因为伪协议限制多,要开启很多开关

也没碰到过像样的文件包含漏洞,更加没写过。

这一关按正常代码理解是要打开一个文件,

文件里面的内容刚好是welcome to the zjctf,

爆破扫描了一下,也没有这种文件。

看了别人的flag才知道原来是伪造文件输入流,

以前其实学过的,后来因为几乎没用过就忘了

【方法1】php://input

利用:php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。
通俗一点讲就是,php://input作为被包含的参数时,也是文件包含,不过是包含的对象是post的数据,而post的数据为用户所传入,所以也相当于任意命令执行。

条件:
allow_url_fopen:off/on
allow_url_include:On
 

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第1张图片

【方法2】data://

条件:
allow_url_fopen: on
allow_url_include: on
利用:
data://数据流封装器,以传递指定格式的数据,可以用来执行PHP代码。
示例:
/?file=data://text/plain;[base64],[执行的php代码]

因为文字有空格,GET请求方式好像就需要编码成base64才能执行

text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第2张图片

第二关:伪协议读取文件

虽然知道了提示文件的名字:useless.php

但是不能直接包含,因为直接包含相当于运行了文件

所以要用base64加密来显示,之后再解密看源码

php://filter

利用:是php中独有的一个协议,可以作为一个中间过滤器来处理目标数据流,可以进行任意文件的读取,且该协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递,相当于可构造多个过滤器。

条件:
读,开启 allow_url_fopen,不需要开启 allow_url_include;
写,则要两者都开启。

示例:
?file=php://filter/read=convert.base64-encode/resource=xxx

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

用伪协议直接访问,用base64加密是为了不让代码执行,复制粘贴解密就能看到里面代码了
【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第3张图片

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第4张图片

file)){  
            echo file_get_contents($this->file); 
            echo "
"; return ("U R SO CLOSE !///COME ON PLZ"); } } } ?>

第三关:反序列化

这里我其实理解了一整天,加上自己写代码才完全理解

先理解代码逻辑,这个php代码有一个类,

类里面有一个变量,有一个固定函数:__tostring()

还有一个系统固定函数:file_get_contents()

重点在file_get_contents函数

file_get_contents函数读取文件

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第5张图片

这里自己写一下函数试试,echo出读取的内容

有不一样的效果,有的是在注释,有的是直接显示到页面

__tostring()类当成是字符串触发

第二个要理解的是这个类的内置固定函数

当类被当成字符串去玩的时候,就触发这个函数

一开始我也不理解,然后发现直接echo就行了

class test{
    
    function __toString(){
        return "tostring函数触发了";
    }
}

$a = new test();   // 正常实例化

echo $a;  // 直接echo打印就能触发

理解类的逻辑

正常显示flag.php内容其实,只需要在变量存入 flag.php字符串

然后echo一下实例化的类即可

file)){  
            echo file_get_contents($this->file); // 读取文件,文件名是变量file

            // 下面不重要,就是给你们看看回显有没有执行成功而已
            echo "
"; return ("U R SO CLOSE !///COME ON PLZ"); } } } ?>

要不是flag这四个字有正则表达式的拦截

直接 file=flag.php ,然后echo一下实例化的类,就完事了(忘记了上去看一下一开始的源码)

最后冲锋,简单的反序列化利用

想完全理解,并不难,把下面代码写下就行,text参数因为是独立的,所以就省略

就两个文件代码,自己写一下才真正了解

所以正确的是:

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第6张图片

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

那么最后text不变,file参数直接写useless.php(因为需要把这个文件包含进来)

文件包含进来相当于执行了php的代码

执行才能反序列化

那么password就把上面序列化的东西放进去

一运行就是反序列化+echo触发__tostring()函数

就读取了flag.php文件,然后echo显示出来到页面上(题目的flag好像是在注释)

【web | CTF】BUUCTF [ZJCTF 2019]NiZhuanSiWei_第7张图片

你可能感兴趣的:(CTF,前端,java,android)